Skip to content

Commit 06732f4

Browse files
liorrclaudeekampfCopilot
authored
feat: add support for running the action inside container (#71)
* Add Linux Docker test job to workflows Add a test-linux-docker job to both .github/workflows/ci.yaml and .github/workflows/integration-tests.yaml. The job runs in an ubuntu:24.04 container (--privileged) with a 10-minute timeout, verifies Twingate status and attempts to access a secure resource via curl. In CI it invokes the local action (./) with the SERVICE_KEY secret; in integration-tests it exercises the published action twingate/github-action@main (passing service-key and debug) to validate behavior in a Docker environment. * fix: use GITHUB_ACTION_PATH env var for container compatibility Use runtime environment variable instead of parse-time context expression to resolve action path correctly inside Docker containers. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: support running in minimal Docker containers - Add SUDO variable to linux-helpers.sh that's empty when root - Replace hardcoded sudo with $SUDO in all Linux steps - Auto-install curl and gnupg if missing in container environments Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * test: temporarily use branch for integration tests TODO: revert to @main after merging PR #71 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * revert: use @main for integration tests Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: address PR review feedback - Add "Print client logs" step to test-linux-docker jobs for debugging - Add SUDO logic to prerequisites step for non-root environments - Fix spacing in echo message Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: use /var/log/twingated.log in container environments When journalctl isn't available, Twingate logs to this file instead. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * fix error message * refactor sudo logic to be shared --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> Co-authored-by: Eran Kampf <205185+ekampf@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Eran Kampf <eran@ekampf.com>
1 parent 9c5fccb commit 06732f4

5 files changed

Lines changed: 126 additions & 21 deletions

File tree

.github/workflows/ci.yaml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,39 @@ jobs:
7575

7676
- run: echo "SUCCESS!!! 🤩 This job's status is ${{ job.status }}."
7777

78+
test-linux-docker:
79+
runs-on: ubuntu-latest
80+
container:
81+
image: ubuntu:24.04
82+
options: --privileged
83+
timeout-minutes: 10
84+
steps:
85+
- uses: actions/checkout@v6
86+
87+
- uses: ./
88+
with:
89+
service-key: ${{ secrets.SERVICE_KEY }}
90+
91+
- name: Verify Twingate status
92+
run: twingate status
93+
94+
- name: Access a secure resource
95+
env:
96+
TEST_URL: http://business.prod.beamreachinc.int/
97+
run: |
98+
curl -v $TEST_URL
99+
100+
- name: Print client logs
101+
if: always()
102+
run: |
103+
if command -v journalctl >/dev/null 2>&1; then
104+
journalctl -u twingate
105+
elif [ -f /var/log/twingated.log ]; then
106+
cat /var/log/twingated.log
107+
else
108+
echo "No Twingate logs found"
109+
fi
110+
78111
test-windows:
79112
strategy:
80113
max-parallel: 4

.github/workflows/integration-tests.yaml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,39 @@ jobs:
5151
if: always()
5252
run: journalctl -u twingate
5353

54+
test-linux-docker:
55+
runs-on: ubuntu-latest
56+
container:
57+
image: ubuntu:24.04
58+
options: --privileged
59+
timeout-minutes: 10
60+
steps:
61+
- name: Test published action
62+
uses: twingate/github-action@main
63+
with:
64+
service-key: ${{ secrets.SERVICE_KEY }}
65+
debug: ${{ inputs.debug || 'false' }}
66+
67+
- name: Verify Twingate status
68+
run: twingate status
69+
70+
- name: Access a secure resource
71+
env:
72+
TEST_URL: http://business.prod.beamreachinc.int/
73+
run: |
74+
curl -v $TEST_URL
75+
76+
- name: Print client logs
77+
if: always()
78+
run: |
79+
if command -v journalctl >/dev/null 2>&1; then
80+
journalctl -u twingate
81+
elif [ -f /var/log/twingated.log ]; then
82+
cat /var/log/twingated.log
83+
else
84+
echo "No Twingate logs found"
85+
fi
86+
5487
test-windows:
5588
strategy:
5689
max-parallel: 4

action.yml

Lines changed: 41 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,35 @@ runs:
2626
if: runner.os != 'Linux' && runner.os != 'Windows'
2727
shell: bash
2828
run: |
29-
source ${{ github.action_path }}/scripts/linux-helpers.sh
29+
source "$GITHUB_ACTION_PATH/scripts/linux-helpers.sh"
3030
log ERROR "Unsupported Runner OS: ${{ runner.os }}"
3131
exit 1
3232
33+
- name: Install prerequisites (Linux)
34+
if: runner.os == 'Linux'
35+
shell: bash
36+
run: |
37+
# Check if we're in a minimal container environment missing required tools
38+
MISSING_DEPS=""
39+
command -v curl >/dev/null 2>&1 || MISSING_DEPS="$MISSING_DEPS curl"
40+
command -v gpg >/dev/null 2>&1 || MISSING_DEPS="$MISSING_DEPS gnupg"
41+
42+
if [ -n "$MISSING_DEPS" ]; then
43+
# Detect if we need sudo for package installation
44+
source "$GITHUB_ACTION_PATH/scripts/sudo-detect.sh"
45+
46+
echo "Installing missing dependencies: $MISSING_DEPS"
47+
$SUDO apt-get update
48+
$SUDO apt-get install -y $MISSING_DEPS
49+
fi
50+
3351
- name: Get latest Twingate version (Linux)
3452
if: runner.os == 'Linux' && inputs.cache == 'true'
3553
id: twingate-version-linux
3654
shell: bash
3755
run: |
3856
export DEBUG_MODE='${{ inputs.debug }}'
39-
source ${{ github.action_path }}/scripts/linux-helpers.sh
57+
source "$GITHUB_ACTION_PATH/scripts/linux-helpers.sh"
4058
4159
VERSION=$(get_twingate_version)
4260
echo "version=$VERSION" >> $GITHUB_OUTPUT
@@ -50,7 +68,7 @@ runs:
5068
shell: powershell
5169
run: |
5270
$env:DEBUG_MODE = '${{ inputs.debug }}'
53-
. ${{ github.action_path }}/scripts/windows-helpers.ps1
71+
. "$env:GITHUB_ACTION_PATH/scripts/windows-helpers.ps1"
5472
5573
$version = Get-TwingateVersion
5674
Add-Content -Path $env:GITHUB_OUTPUT -Value "version=$version"
@@ -95,7 +113,7 @@ runs:
95113
shell: bash
96114
run: |
97115
export DEBUG_MODE='${{ inputs.debug }}'
98-
source ${{ github.action_path }}/scripts/linux-helpers.sh
116+
source "$GITHUB_ACTION_PATH/scripts/linux-helpers.sh"
99117
100118
VALID=$(validate_cache_linux)
101119
echo "valid=$VALID" >> $GITHUB_OUTPUT
@@ -106,7 +124,7 @@ runs:
106124
shell: powershell
107125
run: |
108126
$env:DEBUG_MODE = '${{ inputs.debug }}'
109-
. ${{ github.action_path }}/scripts/windows-helpers.ps1
127+
. "$env:GITHUB_ACTION_PATH/scripts/windows-helpers.ps1"
110128
111129
$cacheDir = "${{ runner.temp }}\twingate-cache"
112130
$isValid = Validate-CacheWindows -CacheDir $cacheDir
@@ -117,19 +135,19 @@ runs:
117135
shell: bash
118136
run: |
119137
export DEBUG_MODE='${{ inputs.debug }}'
120-
source ${{ github.action_path }}/scripts/linux-helpers.sh
138+
source "$GITHUB_ACTION_PATH/scripts/linux-helpers.sh"
121139
122140
log DEBUG "Installing Twingate from cache"
123141
# Install all packages from cache directory (twingate + dependencies)
124-
sudo dpkg -i ~/.twingate-cache/*.deb || true
125-
sudo apt-get install -f -yq
142+
$SUDO dpkg -i ~/.twingate-cache/*.deb || true
143+
$SUDO apt-get install -f -yq
126144
127145
- name: Copy cached MSI to working directory (Windows)
128146
if: runner.os == 'Windows' && inputs.cache == 'true' && steps.validate-cache-windows.outputs.valid == 'true'
129147
shell: powershell
130148
run: |
131149
$env:DEBUG_MODE = '${{ inputs.debug }}'
132-
. ${{ github.action_path }}/scripts/windows-helpers.ps1
150+
. "$env:GITHUB_ACTION_PATH/scripts/windows-helpers.ps1"
133151
134152
log DEBUG "Copying cached MSI to working directory"
135153
$cacheDir = "${{ runner.temp }}\twingate-cache"
@@ -147,34 +165,36 @@ runs:
147165
if: runner.os == 'Linux' && (inputs.cache != 'true' || steps.cache-twingate-linux.outputs.cache-hit != 'true' || steps.validate-cache-linux.outputs.valid != 'true' || steps.twingate-version-linux.outputs.version == 'unknown')
148166
shell: bash
149167
run: |
168+
source "$GITHUB_ACTION_PATH/scripts/linux-helpers.sh"
169+
150170
# Import Twingate GPG key for signature verification
151-
curl -fsSL https://packages.twingate.com/apt/gpg.key | sudo gpg --batch --yes --no-tty --dearmor -o /usr/share/keyrings/twingate-client-keyring.gpg
171+
curl -fsSL https://packages.twingate.com/apt/gpg.key | $SUDO gpg --batch --yes --no-tty --dearmor -o /usr/share/keyrings/twingate-client-keyring.gpg
152172
153173
# Add Twingate repository with GPG key verification
154-
echo "deb [signed-by=/usr/share/keyrings/twingate-client-keyring.gpg] https://packages.twingate.com/apt/ * *" | sudo tee /etc/apt/sources.list.d/twingate.list
174+
echo "deb [signed-by=/usr/share/keyrings/twingate-client-keyring.gpg] https://packages.twingate.com/apt/ * *" | $SUDO tee /etc/apt/sources.list.d/twingate.list
155175
156-
sudo apt update
157-
sudo apt-get update -o Dir::Etc::sourcelist="sources.list.d/twingate.list" -o Dir::Etc::sourceparts="-" -o APT::Get::List-Cleanup="0"
176+
$SUDO apt update
177+
$SUDO apt-get update -o Dir::Etc::sourcelist="sources.list.d/twingate.list" -o Dir::Etc::sourceparts="-" -o APT::Get::List-Cleanup="0"
158178
159179
# Download all packages to cache if caching is enabled
160180
if [ "${{ steps.twingate-version-linux.outputs.version }}" != "unknown" ]; then
161181
mkdir -p ~/.twingate-cache
162182
# Download Twingate and all dependencies to cache directory
163-
sudo apt-get install -yq --download-only -o Dir::Cache::Archives="$HOME/.twingate-cache" twingate
183+
$SUDO apt-get install -yq --download-only -o Dir::Cache::Archives="$HOME/.twingate-cache" twingate
164184
# Install to resolve any missing dependencies, then download them
165-
sudo apt-get install -yq --download-only -o Dir::Cache::Archives="$HOME/.twingate-cache" -f
185+
$SUDO apt-get install -yq --download-only -o Dir::Cache::Archives="$HOME/.twingate-cache" -f
166186
# Fix permissions so cache action can save files
167-
sudo chown -R "$(id -u)":"$(id -g)" "$HOME/.twingate-cache"
187+
$SUDO chown -R "$(id -u)":"$(id -g)" "$HOME/.twingate-cache"
168188
fi
169189
170-
sudo apt install -yq twingate
190+
$SUDO apt install -yq twingate
171191
172192
- name: Download and cache Twingate MSI (Windows)
173193
if: runner.os == 'Windows' && (inputs.cache != 'true' || steps.cache-twingate-windows.outputs.cache-hit != 'true' || steps.validate-cache-windows.outputs.valid != 'true' || steps.twingate-version-windows.outputs.version == 'unknown')
174194
shell: powershell
175195
run: |
176196
$env:DEBUG_MODE = '${{ inputs.debug }}'
177-
. ${{ github.action_path }}/scripts/windows-helpers.ps1
197+
. "$env:GITHUB_ACTION_PATH/scripts/windows-helpers.ps1"
178198
179199
# Download MSI
180200
$msiUrl = "https://api.twingate.com/download/windows?installer=msi"
@@ -200,9 +220,9 @@ runs:
200220
shell: bash
201221
run: |
202222
export DEBUG_MODE='${{ inputs.debug }}'
203-
source ${{ github.action_path }}/scripts/linux-helpers.sh
223+
source "$GITHUB_ACTION_PATH/scripts/linux-helpers.sh"
204224
205-
echo '${{ inputs.service-key }}' | sudo twingate setup --headless -
225+
echo '${{ inputs.service-key }}' | $SUDO twingate setup --headless -
206226
MAX_RETRIES=5
207227
WAIT_TIME=5
208228
n=0
@@ -248,7 +268,7 @@ runs:
248268
shell: powershell
249269
run: |
250270
$env:DEBUG_MODE = '${{ inputs.debug }}'
251-
. ${{ github.action_path }}/scripts/windows-helpers.ps1
271+
. "$env:GITHUB_ACTION_PATH/scripts/windows-helpers.ps1"
252272
253273
# Install Twingate client and start service
254274
Set-Content .\key.json '${{ inputs.service-key }}'

scripts/linux-helpers.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
# Linux helper functions for logging, version detection, and cache validation
33
# Usage: source ./scripts/linux-helpers.sh
44

5+
# Source SUDO detection
6+
source "$(dirname "${BASH_SOURCE[0]}")/sudo-detect.sh"
7+
58
log() {
69
local level=$1
710
shift

scripts/sudo-detect.sh

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#!/bin/bash
2+
# Detects and sets SUDO variable for privilege escalation
3+
# Usage: source sudo-detect.sh
4+
5+
if [ "$(id -u)" -eq 0 ]; then
6+
SUDO=""
7+
else
8+
if command -v sudo >/dev/null 2>&1; then
9+
SUDO="sudo"
10+
else
11+
echo "[ERROR] sudo is not available. Please run this script as root." >&2
12+
exit 1
13+
fi
14+
fi
15+
16+
export SUDO

0 commit comments

Comments
 (0)