Skip to content

Commit 1199393

Browse files
committed
feat: setup-mockd GitHub Action v1
Composite action to install and optionally start mockd for CI testing. - Version resolution (latest or pinned) - Platform detection (linux/darwin, amd64/arm64) - SHA256 checksum verification - Binary caching via actions/cache - Background server with health check polling - Config file support
1 parent f4f4461 commit 1199393

3 files changed

Lines changed: 367 additions & 0 deletions

File tree

.github/workflows/test.yml

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
name: Test
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
8+
jobs:
9+
install-only:
10+
name: Install only (${{ matrix.os }})
11+
strategy:
12+
matrix:
13+
os: [ubuntu-latest, macos-latest]
14+
runs-on: ${{ matrix.os }}
15+
steps:
16+
- uses: actions/checkout@v4
17+
18+
- name: Setup mockd (install only)
19+
uses: ./
20+
id: mockd
21+
22+
- name: Verify installation
23+
run: |
24+
mockd version
25+
echo "Installed version: ${{ steps.mockd.outputs.version }}"
26+
test -n "${{ steps.mockd.outputs.version }}"
27+
28+
install-and-start:
29+
name: Install + start (${{ matrix.os }})
30+
strategy:
31+
matrix:
32+
os: [ubuntu-latest, macos-latest]
33+
runs-on: ${{ matrix.os }}
34+
steps:
35+
- uses: actions/checkout@v4
36+
37+
- name: Setup mockd (with server)
38+
uses: ./
39+
id: mockd
40+
with:
41+
start: true
42+
43+
- name: Verify server is running
44+
run: |
45+
curl -sf "${{ steps.mockd.outputs.admin-url }}/health"
46+
echo "Server healthy at ${{ steps.mockd.outputs.mockd-url }}"
47+
48+
- name: Create and test a mock
49+
run: |
50+
# Create a mock via admin API
51+
curl -sf -X POST "${{ steps.mockd.outputs.admin-url }}/mocks" \
52+
-H 'Content-Type: application/json' \
53+
-d '{"name":"Test","type":"http","http":{"matcher":{"method":"GET","path":"/hello"},"response":{"statusCode":200,"body":"{\"msg\":\"world\"}"}}}'
54+
55+
# Hit the mock
56+
RESPONSE=$(curl -sf "${{ steps.mockd.outputs.mockd-url }}/hello")
57+
echo "Response: $RESPONSE"
58+
echo "$RESPONSE" | grep -q "world"
59+
60+
pinned-version:
61+
name: Pinned version
62+
runs-on: ubuntu-latest
63+
steps:
64+
- uses: actions/checkout@v4
65+
66+
- name: Setup mockd v0.4.4
67+
uses: ./
68+
id: mockd
69+
with:
70+
version: '0.4.4'
71+
72+
- name: Verify version
73+
run: |
74+
mockd version | grep -q "0.4.4"
75+
76+
with-config:
77+
name: With config file
78+
runs-on: ubuntu-latest
79+
steps:
80+
- uses: actions/checkout@v4
81+
82+
- name: Create test config
83+
run: |
84+
cat > /tmp/test-mocks.yaml << 'EOF'
85+
mocks:
86+
- name: "Health"
87+
type: http
88+
http:
89+
matcher:
90+
method: GET
91+
path: /api/health
92+
response:
93+
statusCode: 200
94+
body: '{"status": "ok"}'
95+
EOF
96+
97+
- name: Setup mockd with config
98+
uses: ./
99+
id: mockd
100+
with:
101+
start: true
102+
config: /tmp/test-mocks.yaml
103+
104+
- name: Verify config loaded
105+
run: |
106+
# Wait a moment for config to load
107+
sleep 2
108+
curl -sf "${{ steps.mockd.outputs.mockd-url }}/api/health" | grep -q "ok"
109+
110+
cache-test:
111+
name: Cache hit test
112+
runs-on: ubuntu-latest
113+
steps:
114+
- uses: actions/checkout@v4
115+
116+
- name: First install (cache miss)
117+
uses: ./
118+
id: first
119+
120+
- name: Check cache status
121+
run: |
122+
echo "Cache hit: ${{ steps.first.outputs.cache-hit }}"
123+
echo "Version: ${{ steps.first.outputs.version }}"

README.md

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# setup-mockd
2+
3+
GitHub Action to install and optionally start the [mockd](https://github.com/getmockd/mockd) mock server for integration testing.
4+
5+
## Usage
6+
7+
### Install only
8+
9+
```yaml
10+
- uses: getmockd/setup-mockd@v1
11+
- run: mockd version
12+
```
13+
14+
### Install + start server
15+
16+
```yaml
17+
- uses: getmockd/setup-mockd@v1
18+
id: mockd
19+
with:
20+
start: true
21+
config: tests/mocks.yaml
22+
23+
- run: npm test
24+
env:
25+
API_URL: ${{ steps.mockd.outputs.mockd-url }}
26+
```
27+
28+
### Pin version
29+
30+
```yaml
31+
- uses: getmockd/setup-mockd@v1
32+
with:
33+
version: '0.4.4'
34+
start: true
35+
```
36+
37+
### Custom ports
38+
39+
```yaml
40+
- uses: getmockd/setup-mockd@v1
41+
with:
42+
start: true
43+
port: '8080'
44+
admin-port: '8090'
45+
```
46+
47+
## Inputs
48+
49+
| Input | Description | Default |
50+
|-------|-------------|---------|
51+
| `version` | mockd version to install | `latest` |
52+
| `github-token` | GitHub token for API requests | `${{ github.token }}` |
53+
| `start` | Start server in background | `false` |
54+
| `config` | Path to mockd.yaml config file | |
55+
| `port` | Mock server port | `4280` |
56+
| `admin-port` | Admin API port | `4290` |
57+
| `log-level` | Log level: debug, info, warn, error | `warn` |
58+
59+
## Outputs
60+
61+
| Output | Description |
62+
|--------|-------------|
63+
| `version` | Installed mockd version |
64+
| `mockd-url` | Mock server URL (e.g., `http://localhost:4280`) |
65+
| `admin-url` | Admin API URL (e.g., `http://localhost:4290`) |
66+
| `cache-hit` | Whether the binary was found in cache |
67+
68+
## Features
69+
70+
- **Version resolution** — `latest` resolves to the newest GitHub release automatically
71+
- **Binary caching** — Downloaded binary is cached across workflow runs via `actions/cache`
72+
- **SHA256 verification** — Every download is checksum-verified against the release `.sha256` file
73+
- **Platform detection** — Supports linux/amd64, linux/arm64, darwin/amd64, darwin/arm64
74+
- **Background server** — Optional `start: true` launches mockd in the background with health check polling
75+
76+
## License
77+
78+
Apache 2.0

action.yml

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
name: 'Setup mockd'
2+
description: 'Install and optionally start the mockd mock server for integration testing'
3+
author: 'Mockd LLC'
4+
branding:
5+
icon: 'server'
6+
color: 'purple'
7+
8+
inputs:
9+
version:
10+
description: 'mockd version to install (e.g., "0.4.4"). Default: latest release.'
11+
required: false
12+
default: 'latest'
13+
github-token:
14+
description: 'GitHub token for API requests (avoids rate limiting when resolving latest version)'
15+
required: false
16+
default: ${{ github.token }}
17+
start:
18+
description: 'Start mockd server in background after install'
19+
required: false
20+
default: 'false'
21+
config:
22+
description: 'Path to mockd.yaml config file to load on start'
23+
required: false
24+
port:
25+
description: 'Mock server port (default: 4280)'
26+
required: false
27+
default: '4280'
28+
admin-port:
29+
description: 'Admin API port (default: 4290)'
30+
required: false
31+
default: '4290'
32+
log-level:
33+
description: 'Server log level: debug, info, warn, error'
34+
required: false
35+
default: 'warn'
36+
37+
outputs:
38+
version:
39+
description: 'Installed mockd version'
40+
value: ${{ steps.install.outputs.version }}
41+
mockd-url:
42+
description: 'Mock server base URL (e.g., http://localhost:4280)'
43+
value: ${{ steps.start-server.outputs.mockd-url }}
44+
admin-url:
45+
description: 'Admin API base URL (e.g., http://localhost:4290)'
46+
value: ${{ steps.start-server.outputs.admin-url }}
47+
cache-hit:
48+
description: 'Whether the binary was found in cache'
49+
value: ${{ steps.cache.outputs.cache-hit }}
50+
51+
runs:
52+
using: 'composite'
53+
steps:
54+
- name: Resolve version
55+
id: resolve
56+
shell: bash
57+
env:
58+
INPUT_VERSION: ${{ inputs.version }}
59+
GH_TOKEN: ${{ inputs.github-token }}
60+
run: |
61+
if [ "$INPUT_VERSION" = "latest" ]; then
62+
VERSION=$(gh api repos/getmockd/mockd/releases/latest --jq '.tag_name' | sed 's/^v//')
63+
echo "Resolved latest version: $VERSION"
64+
else
65+
VERSION=$(echo "$INPUT_VERSION" | sed 's/^v//')
66+
fi
67+
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
68+
69+
- name: Detect platform
70+
id: platform
71+
shell: bash
72+
run: |
73+
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
74+
ARCH=$(uname -m)
75+
case "$ARCH" in
76+
x86_64|amd64) ARCH="amd64" ;;
77+
aarch64|arm64) ARCH="arm64" ;;
78+
*) echo "::error::Unsupported architecture: $ARCH"; exit 1 ;;
79+
esac
80+
case "$OS" in
81+
linux|darwin) ;;
82+
mingw*|msys*|cygwin*) OS="windows" ;;
83+
*) echo "::error::Unsupported OS: $OS"; exit 1 ;;
84+
esac
85+
BINARY="mockd-${OS}-${ARCH}"
86+
[ "$OS" = "windows" ] && BINARY="${BINARY}.exe"
87+
echo "os=$OS" >> "$GITHUB_OUTPUT"
88+
echo "arch=$ARCH" >> "$GITHUB_OUTPUT"
89+
echo "binary=$BINARY" >> "$GITHUB_OUTPUT"
90+
91+
- name: Cache mockd binary
92+
id: cache
93+
uses: actions/cache@v4
94+
with:
95+
path: ${{ runner.temp }}/mockd-bin
96+
key: mockd-${{ steps.resolve.outputs.version }}-${{ steps.platform.outputs.os }}-${{ steps.platform.outputs.arch }}
97+
98+
- name: Download mockd
99+
if: steps.cache.outputs.cache-hit != 'true'
100+
shell: bash
101+
env:
102+
VERSION: ${{ steps.resolve.outputs.version }}
103+
BINARY: ${{ steps.platform.outputs.binary }}
104+
run: |
105+
mkdir -p "$RUNNER_TEMP/mockd-bin"
106+
URL="https://github.com/getmockd/mockd/releases/download/v${VERSION}/${BINARY}"
107+
CHECKSUM_URL="${URL}.sha256"
108+
echo "Downloading mockd v${VERSION} from ${URL}"
109+
curl -fsSL -o "$RUNNER_TEMP/mockd-bin/mockd" "$URL"
110+
curl -fsSL -o "$RUNNER_TEMP/mockd-bin/mockd.sha256" "$CHECKSUM_URL"
111+
112+
# Verify checksum
113+
EXPECTED=$(awk '{print $1}' "$RUNNER_TEMP/mockd-bin/mockd.sha256")
114+
ACTUAL=$(sha256sum "$RUNNER_TEMP/mockd-bin/mockd" | awk '{print $1}')
115+
if [ "$EXPECTED" != "$ACTUAL" ]; then
116+
echo "::error::SHA256 checksum mismatch! Expected: $EXPECTED, Got: $ACTUAL"
117+
exit 1
118+
fi
119+
echo "Checksum verified: $ACTUAL"
120+
chmod +x "$RUNNER_TEMP/mockd-bin/mockd"
121+
122+
- name: Install mockd
123+
id: install
124+
shell: bash
125+
env:
126+
VERSION: ${{ steps.resolve.outputs.version }}
127+
run: |
128+
echo "$RUNNER_TEMP/mockd-bin" >> "$GITHUB_PATH"
129+
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
130+
"$RUNNER_TEMP/mockd-bin/mockd" version
131+
echo "::notice::mockd v${VERSION} installed"
132+
133+
- name: Start mockd server
134+
id: start-server
135+
if: inputs.start == 'true'
136+
shell: bash
137+
env:
138+
PORT: ${{ inputs.port }}
139+
ADMIN_PORT: ${{ inputs.admin-port }}
140+
LOG_LEVEL: ${{ inputs.log-level }}
141+
CONFIG: ${{ inputs.config }}
142+
run: |
143+
ARGS="--no-auth --port $PORT --admin-port $ADMIN_PORT --log-level $LOG_LEVEL"
144+
[ -n "$CONFIG" ] && ARGS="$ARGS --config $CONFIG"
145+
146+
echo "Starting mockd serve $ARGS"
147+
nohup "$RUNNER_TEMP/mockd-bin/mockd" serve $ARGS > "$RUNNER_TEMP/mockd.log" 2>&1 &
148+
PID=$!
149+
echo "$PID" > "$RUNNER_TEMP/mockd.pid"
150+
echo "mockd started with PID $PID"
151+
152+
# Wait for health check
153+
for i in $(seq 1 30); do
154+
if curl -sf "http://localhost:${ADMIN_PORT}/health" > /dev/null 2>&1; then
155+
echo "mockd is healthy after ${i}s"
156+
echo "mockd-url=http://localhost:${PORT}" >> "$GITHUB_OUTPUT"
157+
echo "admin-url=http://localhost:${ADMIN_PORT}" >> "$GITHUB_OUTPUT"
158+
echo "::notice::mockd server running on :${PORT} (admin :${ADMIN_PORT})"
159+
exit 0
160+
fi
161+
sleep 1
162+
done
163+
164+
echo "::error::mockd failed to start within 30s"
165+
cat "$RUNNER_TEMP/mockd.log"
166+
exit 1

0 commit comments

Comments
 (0)