Skip to content

Commit 7f68f50

Browse files
authored
Merge pull request #9 from timvw/linux-e2e-docker-matrix
feat: add Linux e2e tests for bash and zsh
2 parents 3ca8311 + 4fc182b commit 7f68f50

File tree

11 files changed

+1135
-0
lines changed

11 files changed

+1135
-0
lines changed

.github/workflows/e2e-linux.yml

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
name: Linux E2E Tests
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
workflow_dispatch:
9+
10+
jobs:
11+
e2e-linux:
12+
name: E2E Tests (Linux)
13+
runs-on: ubuntu-latest
14+
strategy:
15+
fail-fast: false
16+
matrix:
17+
shell: [bash, zsh]
18+
# Note: fish is excluded for now as wt shellenv doesn't support fish yet
19+
20+
steps:
21+
- name: Generate GitHub App token
22+
id: generate-token
23+
if: ${{ secrets.BOT_APP_ID != '' }}
24+
uses: actions/create-github-app-token@v1
25+
with:
26+
app-id: ${{ secrets.BOT_APP_ID }}
27+
private-key: ${{ secrets.BOT_PRIVATE_KEY }}
28+
29+
- name: Checkout code
30+
uses: actions/checkout@v4
31+
with:
32+
token: ${{ steps.generate-token.outputs.token || github.token }}
33+
34+
- name: Set up Go
35+
uses: actions/setup-go@v5
36+
with:
37+
go-version: '1.23'
38+
39+
- name: Install zsh
40+
if: matrix.shell == 'zsh'
41+
run: |
42+
sudo apt-get update
43+
sudo apt-get install -y zsh
44+
45+
- name: Download dependencies
46+
run: go mod download
47+
48+
- name: Build wt binary
49+
run: |
50+
mkdir -p bin
51+
go build -o bin/wt .
52+
53+
- name: Verify binary
54+
run: |
55+
./bin/wt --help
56+
file bin/wt
57+
58+
- name: Run e2e tests for ${{ matrix.shell }}
59+
run: |
60+
# Set up isolated test environment
61+
export TMPDIR=$(mktemp -d)
62+
export HOME=$TMPDIR
63+
64+
# Run e2e tests with verbose output
65+
if [ "${{ matrix.shell }}" = "bash" ]; then
66+
go test -v -run TestE2EAutoCdWithNonInteractiveCommand ./...
67+
go test -v -run TestE2EAutoCdWithCreate ./...
68+
elif [ "${{ matrix.shell }}" = "zsh" ]; then
69+
go test -v -run TestE2EAutoCdInZsh ./...
70+
fi
71+
72+
- name: Test shellenv output
73+
run: |
74+
# Capture shellenv output for inspection
75+
./bin/wt shellenv > shellenv-${{ matrix.shell }}.txt
76+
77+
# Verify shellenv produces output
78+
if [ ! -s shellenv-${{ matrix.shell }}.txt ]; then
79+
echo "ERROR: shellenv produced no output"
80+
exit 1
81+
fi
82+
83+
# Check for key components (wt function)
84+
if ! grep -q "wt()" shellenv-${{ matrix.shell }}.txt; then
85+
echo "ERROR: wt function not found in shellenv output"
86+
exit 1
87+
fi
88+
89+
# Verify shell-specific features
90+
if [ "${{ matrix.shell }}" = "bash" ]; then
91+
grep -q "BASH_VERSION" shellenv-${{ matrix.shell }}.txt || (echo "ERROR: bash-specific code not found" && exit 1)
92+
elif [ "${{ matrix.shell }}" = "zsh" ]; then
93+
grep -q "ZSH_VERSION" shellenv-${{ matrix.shell }}.txt || (echo "ERROR: zsh-specific code not found" && exit 1)
94+
fi
95+
96+
echo "shellenv validation passed for ${{ matrix.shell }}"
97+
98+
- name: Test worktree CRUD operations with auto-cd
99+
run: |
100+
# Save workspace directory before creating test repo
101+
WORKSPACE_DIR=$(pwd)
102+
WT_BIN="$WORKSPACE_DIR/bin/wt"
103+
WT_BIN_DIR="$WORKSPACE_DIR/bin"
104+
105+
# Create isolated test environment
106+
export WORKTREE_ROOT=$(mktemp -d)/worktrees
107+
export PATH=$WT_BIN_DIR:$PATH
108+
109+
# Create a test git repo
110+
TEST_REPO=$(mktemp -d)/test-repo
111+
mkdir -p $TEST_REPO
112+
cd $TEST_REPO
113+
git init
114+
git config user.email "test@example.com"
115+
git config user.name "Test User"
116+
git commit --allow-empty -m "initial commit"
117+
git branch -M main
118+
119+
# Create a test branch
120+
git checkout -b test-branch
121+
git commit --allow-empty -m "test commit"
122+
git checkout main
123+
124+
# Test with shell integration
125+
if [ "${{ matrix.shell }}" = "bash" ]; then
126+
SHELL_CMD="bash"
127+
else
128+
SHELL_CMD="zsh"
129+
fi
130+
131+
# Generate shellenv script for the shell
132+
$WT_BIN shellenv > /tmp/wt-shellenv-${{ matrix.shell }}.sh
133+
134+
# Run test in a subshell with shellenv sourced
135+
$SHELL_CMD -c "
136+
export WORKTREE_ROOT=$WORKTREE_ROOT
137+
export PATH=$WT_BIN_DIR:\$PATH
138+
cd $TEST_REPO
139+
source /tmp/wt-shellenv-${{ matrix.shell }}.sh
140+
141+
echo 'Testing: wt checkout test-branch'
142+
wt checkout test-branch
143+
144+
# Verify we're in the worktree directory
145+
CURRENT_DIR=\$(pwd)
146+
EXPECTED_DIR=$WORKTREE_ROOT/test-repo/test-branch
147+
if [[ \"\$CURRENT_DIR\" != \"\$EXPECTED_DIR\" ]]; then
148+
echo \"ERROR: Auto-cd failed. Expected: \$EXPECTED_DIR, Got: \$CURRENT_DIR\"
149+
exit 1
150+
fi
151+
echo \"✓ Auto-cd to worktree verified: \$CURRENT_DIR\"
152+
153+
# Verify worktree was created
154+
wt list | grep test-branch || (echo 'ERROR: worktree not in list' && exit 1)
155+
echo '✓ Worktree created and listed'
156+
157+
# Go back to original repo to test create
158+
cd $TEST_REPO
159+
160+
# Test create command
161+
echo 'Testing: wt create feature-test'
162+
wt create feature-test
163+
CURRENT_DIR=\$(pwd)
164+
EXPECTED_DIR=$WORKTREE_ROOT/test-repo/feature-test
165+
if [[ \"\$CURRENT_DIR\" != \"\$EXPECTED_DIR\" ]]; then
166+
echo \"ERROR: Auto-cd failed for create. Expected: \$EXPECTED_DIR, Got: \$CURRENT_DIR\"
167+
exit 1
168+
fi
169+
echo \"✓ Auto-cd to new worktree verified: \$CURRENT_DIR\"
170+
171+
# Go back to original repo to test remove
172+
cd $TEST_REPO
173+
174+
# Test remove command
175+
echo 'Testing: wt remove test-branch'
176+
wt remove test-branch
177+
178+
# Verify worktree was removed
179+
if wt list | grep test-branch; then
180+
echo 'ERROR: worktree not removed'
181+
exit 1
182+
fi
183+
echo '✓ Worktree removed successfully'
184+
185+
echo 'CRUD operations with auto-cd test passed!'
186+
"
187+
188+
- name: Upload shellenv output as artifact
189+
if: always()
190+
uses: actions/upload-artifact@v4
191+
with:
192+
name: shellenv-output-${{ matrix.shell }}
193+
path: shellenv-${{ matrix.shell }}.txt
194+
retention-days: 7
195+
196+
- name: Upload test logs
197+
if: failure()
198+
uses: actions/upload-artifact@v4
199+
with:
200+
name: e2e-logs-${{ matrix.shell }}
201+
path: |
202+
/tmp/*.log
203+
/var/tmp/*.log
204+
retention-days: 7
205+
if-no-files-found: ignore

e2e/docker/Dockerfile

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Docker image for wt e2e tests with multiple shells
2+
FROM golang:1.23-bookworm
3+
4+
# Install git and shells (bash is already present)
5+
RUN apt-get update && apt-get install -y \
6+
git \
7+
zsh \
8+
fish \
9+
&& rm -rf /var/lib/apt/lists/*
10+
11+
# Create non-root user for realistic shell testing
12+
RUN useradd -m -s /bin/bash testuser
13+
14+
# Set up git config for testuser
15+
USER testuser
16+
RUN git config --global user.email "test@example.com" && \
17+
git config --global user.name "Test User"
18+
19+
WORKDIR /workspace

e2e/docker/README.md

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# Docker-based E2E Tests (Local Development Only)
2+
3+
This directory contains Docker-based end-to-end tests for local development and debugging. **These tests do NOT run in CI** - the GitHub Actions workflow uses native runner tests instead (see `e2e/native/`).
4+
5+
## Overview
6+
7+
The Docker-based E2E suite verifies that `wt` works correctly in different shell environments by:
8+
9+
1. Building the `wt` binary from source inside a container
10+
2. Creating a temporary git repository with test branches
11+
3. Loading the shell environment via `wt shellenv`
12+
4. Running core operations: `checkout`, `create`, `list`, and `remove`
13+
5. Verifying auto-cd functionality and worktree management
14+
15+
**Note:** These Docker tests are provided for local development and debugging. CI uses the native runner approach (e2e/native/) which is faster and more realistic.
16+
17+
## Running Locally
18+
19+
### Prerequisites
20+
21+
- Docker installed and running
22+
- From the repository root
23+
24+
### Build the test image
25+
26+
```bash
27+
docker build -t wt-e2e -f e2e/docker/Dockerfile .
28+
```
29+
30+
### Run tests for a specific shell
31+
32+
```bash
33+
# Bash
34+
docker run --rm -v $(pwd):/workspace -w /workspace wt-e2e bash e2e/docker/test-bash.sh
35+
36+
# Zsh
37+
docker run --rm -v $(pwd):/workspace -w /workspace wt-e2e zsh e2e/docker/test-zsh.sh
38+
39+
# Fish (NOT YET SUPPORTED - wt shellenv doesn't generate fish syntax)
40+
# docker run --rm -v $(pwd):/workspace -w /workspace wt-e2e fish e2e/docker/test-fish.sh
41+
```
42+
43+
**Note:** Fish shell tests are included for future development but will currently fail since `wt shellenv` does not yet generate fish-compatible syntax.
44+
45+
### Run all tests
46+
47+
```bash
48+
./e2e/docker/run-all.sh
49+
```
50+
51+
## Test Structure
52+
53+
Each shell test script (`test-bash.sh`, `test-zsh.sh`, `test-fish.sh`) follows the same pattern:
54+
55+
1. **Setup**: Build `wt` binary and create temporary test repository
56+
2. **Test 1**: Verify `wt checkout` with existing branch and auto-cd
57+
3. **Test 2**: Verify `wt create` with new branch and auto-cd
58+
4. **Test 3**: Verify `wt list` displays worktrees
59+
5. **Test 4**: Verify `wt remove` deletes worktree
60+
6. **Cleanup**: Remove temporary directories
61+
62+
## CI Integration
63+
64+
**These Docker tests do NOT run in CI.** GitHub Actions uses the native runner approach (`e2e/native/`) instead, which:
65+
66+
- Runs tests directly on ubuntu-latest (no Docker overhead)
67+
- Executes existing Go e2e tests + shellenv validation + CRUD tests
68+
- Completes in ~30-50 seconds per shell (vs 5-6 minutes with Docker)
69+
- Follows the same pattern as macOS e2e tests (PR #8)
70+
71+
The Docker approach is provided as an alternative for local development and debugging.
72+
73+
## Troubleshooting
74+
75+
If tests fail locally:
76+
77+
1. Ensure Docker is running
78+
2. Check that you're running from the repository root
79+
3. Verify the Docker image builds successfully
80+
4. Run with verbose output: add `set -x` to the test script
81+
82+
If tests fail in CI:
83+
84+
1. Check the uploaded test logs in the Actions artifacts
85+
2. Look for shell-specific issues in the shellenv output
86+
3. Verify git configuration is set correctly

e2e/docker/run-all.sh

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#!/bin/bash
2+
set -euo pipefail
3+
4+
# Script to run all Docker-based e2e tests locally
5+
6+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
7+
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
8+
IMAGE_NAME="wt-e2e:latest"
9+
10+
echo "=== Building Docker image for e2e tests ==="
11+
docker build -t "$IMAGE_NAME" -f "$SCRIPT_DIR/Dockerfile" "$REPO_ROOT"
12+
13+
echo ""
14+
echo "=== Running e2e tests in all shells ==="
15+
echo "Note: Fish is excluded - wt shellenv doesn't support fish yet"
16+
echo ""
17+
18+
SHELLS=(bash zsh)
19+
FAILED=()
20+
21+
for shell in "${SHELLS[@]}"; do
22+
echo ""
23+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
24+
echo "Running tests in $shell..."
25+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
26+
27+
if docker run --rm \
28+
-v "$REPO_ROOT:/workspace" \
29+
-w /workspace \
30+
"$IMAGE_NAME" \
31+
"$shell" "e2e/docker/test-$shell.sh"; then
32+
echo "$shell tests passed"
33+
else
34+
echo "$shell tests failed"
35+
FAILED+=("$shell")
36+
fi
37+
done
38+
39+
echo ""
40+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
41+
echo "Summary"
42+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
43+
44+
if [ ${#FAILED[@]} -eq 0 ]; then
45+
echo "✓ All tests passed!"
46+
exit 0
47+
else
48+
echo "✗ Tests failed in: ${FAILED[*]}"
49+
exit 1
50+
fi

0 commit comments

Comments
 (0)