Skip to content

Commit 141ec4f

Browse files
ci: add PR validation, smoke tests, and workflow security hardening (#30)
* ci: add PR validation, smoke tests, and workflow security hardening - Add CI workflow: compose config validation + service startup smoke tests on every PR - Add integration test workflow: regtest stack end-to-end validation on dev push - Add zizmor workflow: GitHub Actions security scanning (SARIF → Security tab) - Add Dependabot for GitHub Actions (monthly, with cooldown) - Pin all actions to commit SHAs and update to latest versions - Harden all workflows: persist-credentials: false, permissions: {}t The smoke tests would have directly caught #28 (missing zaino start subcommand)
1 parent fc11393 commit 141ec4f

5 files changed

Lines changed: 153 additions & 8 deletions

File tree

.github/dependabot.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
version: 2
2+
updates:
3+
- package-ecosystem: github-actions
4+
directory: /
5+
schedule:
6+
interval: monthly
7+
groups:
8+
github-actions:
9+
patterns: ["*"]
10+
cooldown:
11+
default-days: 7

.github/workflows/ci.yaml

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
name: CI
2+
3+
concurrency:
4+
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
5+
cancel-in-progress: true
6+
7+
on:
8+
pull_request:
9+
push:
10+
branches: [dev]
11+
12+
permissions: {}
13+
14+
jobs:
15+
smoke-test:
16+
name: Service smoke tests
17+
runs-on: ubuntu-latest
18+
env:
19+
COMPOSE_PROJECT_NAME: z3-smoke
20+
COMPOSE_FILE: docker-compose.yml:docker-compose.regtest.yml
21+
steps:
22+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
23+
with:
24+
persist-credentials: false
25+
26+
- name: Generate TLS certs and regtest configs
27+
run: |
28+
mkdir -p config/tls config/regtest
29+
openssl req -x509 -newkey rsa:2048 \
30+
-keyout config/tls/zaino.key -out config/tls/zaino.crt \
31+
-sha256 -days 1 -nodes -subj "/CN=localhost" 2>/dev/null
32+
chmod 644 config/tls/zaino.key config/tls/zaino.crt
33+
echo "# dummy identity for CI" > config/regtest/zallet_identity.txt
34+
SALT=$(openssl rand -hex 16)
35+
HASH=$(printf 'zebra' | openssl dgst -sha256 -mac HMAC -macopt "key:$SALT" | awk '{print $NF}')
36+
sed -i "s|__GENERATED_BY_INIT_SH__|${SALT}\$${HASH}|" config/regtest/zallet.toml
37+
38+
- name: Validate compose configs
39+
run: |
40+
docker compose config --quiet
41+
docker compose --env-file .env.regtest config --quiet
42+
43+
- name: Start Zebra (regtest)
44+
run: |
45+
docker compose --env-file .env.regtest up -d zebra
46+
echo "Waiting for Zebra RPC..."
47+
for i in $(seq 1 60); do
48+
if curl -sf -X POST -H "Content-Type: application/json" \
49+
-d '{"jsonrpc":"2.0","method":"getblockchaininfo","params":[],"id":1}' \
50+
http://127.0.0.1:18232 > /dev/null 2>&1; then
51+
echo "Zebra is ready"
52+
break
53+
fi
54+
if [ "$i" -eq 60 ]; then echo "Zebra failed to start" && exit 1; fi
55+
sleep 2
56+
done
57+
58+
- name: Verify Zebra is serving RPC
59+
run: |
60+
curl -sf -X POST -H "Content-Type: application/json" \
61+
-d '{"jsonrpc":"2.0","method":"getblockchaininfo","params":[],"id":1}' \
62+
http://127.0.0.1:18232 | jq .
63+
64+
- name: Mine block 1 (required for Zaino sync)
65+
run: |
66+
curl -sf -u zebra:zebra -X POST -H "Content-Type: application/json" \
67+
-d '{"jsonrpc":"2.0","method":"generate","params":[1],"id":1}' \
68+
http://127.0.0.1:18232 | jq .
69+
70+
- name: Start Zaino and verify JSON-RPC proxy
71+
run: |
72+
docker compose --env-file .env.regtest up -d zaino
73+
echo "Waiting for Zaino JSON-RPC..."
74+
for i in $(seq 1 30); do
75+
if RESULT=$(curl -sf -X POST -H "Content-Type: application/json" \
76+
-d '{"jsonrpc":"2.0","method":"getblockchaininfo","params":[],"id":1}' \
77+
http://127.0.0.1:8237 2>/dev/null); then
78+
echo "Zaino is ready"
79+
echo "$RESULT" | jq .
80+
break
81+
fi
82+
if [ "$i" -eq 30 ]; then
83+
echo "Zaino failed to start"
84+
docker compose --env-file .env.regtest logs zaino --tail 20
85+
exit 1
86+
fi
87+
sleep 2
88+
done
89+
90+
- name: Verify Zallet accepts compose command
91+
run: docker compose --env-file .env.regtest run --rm --no-deps zallet --help
92+
93+
- name: Collect logs on failure
94+
if: failure()
95+
run: |
96+
echo "=== Zebra logs ==="
97+
docker compose --env-file .env.regtest logs zebra --tail 50 2>&1 || true
98+
echo "=== Zaino logs ==="
99+
docker compose --env-file .env.regtest logs zaino --tail 50 2>&1 || true
100+
echo "=== Container status ==="
101+
docker compose --env-file .env.regtest ps 2>&1 || true

.github/workflows/sub-build-docker-image.yaml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -74,27 +74,27 @@ jobs:
7474
steps:
7575

7676
- name: Checkout ${{ inputs.repository }}
77-
uses: actions/checkout@v4.2.2
77+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
7878
with:
7979
repository: ${{ inputs.repository }}
8080
ref: ${{ inputs.ref }}
8181
persist-credentials: false
8282

8383
- name: Checkout Z3
84-
uses: actions/checkout@v4.1.1
84+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
8585
with:
8686
path: z3
8787
persist-credentials: false
8888

8989
- name: Inject slug/short variables
90-
uses: rlespinasse/github-slug-action@v5.1.0
90+
uses: rlespinasse/github-slug-action@9e7def61550737ba68c62d34a32dd31792e3f429 # v5.5.0
9191
with:
9292
short-length: 7
9393

9494
# Automatic tag management and OCI Image Format Specification for labels
9595
- name: Docker meta
9696
id: meta
97-
uses: docker/metadata-action@v5.7.0
97+
uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6.0.0
9898
with:
9999
# list of Docker images to use as base name for tags
100100
# We only publish images to DockerHub if a release is not a pre-release
@@ -116,7 +116,7 @@ jobs:
116116
type=sha,event=branch
117117
118118
- name: Login to GitHub Container Registry
119-
uses: docker/login-action@v3.4.0
119+
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
120120
with:
121121
registry: ghcr.io
122122
username: ${{ github.actor }}
@@ -125,12 +125,12 @@ jobs:
125125
# Setup Docker Buildx to use Docker Build Cloud
126126
- name: Set up Docker Buildx
127127
id: buildx
128-
uses: docker/setup-buildx-action@v3.10.0
128+
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
129129

130130
# Build and push image to GitHub Container Registry
131131
- name: Build & push
132132
id: docker_build
133-
uses: docker/build-push-action@v6.15.0
133+
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0
134134
with:
135135
target: ${{ inputs.dockerfile_target }}
136136
context: .

.github/workflows/zizmor.yaml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
name: GitHub Actions security analysis
2+
3+
on:
4+
push:
5+
branches: [dev]
6+
paths:
7+
- '.github/workflows/**'
8+
pull_request:
9+
paths:
10+
- '.github/workflows/**'
11+
12+
permissions: {}
13+
14+
jobs:
15+
zizmor:
16+
name: zizmor
17+
runs-on: ubuntu-latest
18+
permissions:
19+
security-events: write
20+
steps:
21+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
22+
with:
23+
persist-credentials: false
24+
- uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8.0.0
25+
- name: Run zizmor
26+
run: uvx zizmor --format sarif . > results.sarif
27+
env:
28+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
29+
- name: Upload SARIF
30+
uses: github/codeql-action/upload-sarif@5c8a8a642e79153f5d047b10ec1cba1d1cc65699 # v3.35.1
31+
with:
32+
sarif_file: results.sarif
33+
category: zizmor

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ Update `config/zallet.toml` to set `network = "test"` in the `[consensus]` secti
6464

6565
### Running Regtest
6666

67-
Regtest uses a compose overlay (`docker-compose.regtest.yml`) that adds the rpc-router service, disables TLS, and adjusts healthchecks for a peerless network. Volumes are automatically isolated via `COMPOSE_PROJECT_NAME=z3-regtest`.
67+
Regtest uses a compose overlay (`docker-compose.regtest.yml`) that adds the rpc-router service, switches from cookie auth to username/password auth, and adjusts healthchecks for a peerless network. Volumes are automatically isolated via `COMPOSE_PROJECT_NAME=z3-regtest`.
6868

6969
First-time setup (**required** before starting the stack):
7070

0 commit comments

Comments
 (0)