Skip to content

Fly.io deploy manifest + CI auto-deploy (#38) #96

Fly.io deploy manifest + CI auto-deploy (#38)

Fly.io deploy manifest + CI auto-deploy (#38) #96

Workflow file for this run

name: ci
on:
push:
branches: [main]
pull_request:
permissions:
contents: read
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-go@v6
with:
go-version: '1.26.x'
- name: go vet
run: go vet ./...
- name: go test
run: go test -race ./...
- name: build
run: make build
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-go@v6
with:
go-version: '1.26.x'
- name: install gosec
run: go install github.com/securego/gosec/v2/cmd/gosec@latest
# Tracks: golang.org/x/vuln/cmd/govulncheck@v1.1.4
# Pinned to an explicit version so a compromised or buggy upstream
# release cannot silently land in CI between Renovate bumps. The
# tracked tag in this comment must move in lockstep with the
# `@vX.Y.Z` below — same convention as the Trivy action pin in the
# `image-scan` job (#68) and the Dockerfile base-image digest pins
# (#32).
- name: install govulncheck
run: go install golang.org/x/vuln/cmd/govulncheck@v1.1.4
- name: gosec
run: gosec ./...
- name: govulncheck
run: govulncheck ./...
image-scan:
runs-on: ubuntu-latest
# Belt-and-suspenders: the workflow-level permissions block above
# already grants only `contents: read`, but a future top-level
# escalation would silently widen this job's scope without the
# explicit declaration. Pin the minimum here so a regression in the
# workflow header doesn't grant the scanner write tokens.
permissions:
contents: read
steps:
- uses: actions/checkout@v6
- name: build image
# The scan operates on the same artifact a PR would publish.
run: docker build -t pyrycode-relay:${{ github.sha }} .
# Tracks: aquasecurity/trivy-action@v0.36.0
# Pinned by commit SHA so a tag-swap upstream cannot change what
# runs against our image between Renovate bumps. Refresh the
# comment in lockstep with the SHA so a reviewer can sanity-check
# which release the digest refers to. Same convention as the
# Dockerfile base-image digest pins (#32).
- name: trivy image scan
uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25
with:
image-ref: pyrycode-relay:${{ github.sha }}
format: table
severity: CRITICAL,HIGH
# Only fixable CVEs fail the build. CVEs with no upstream
# patch produce no actionable work and would block every PR
# until someone unrelated to the change fixes them.
ignore-unfixed: true
# Cover both OS packages and language manifests / Go binary
# content Trivy can re-derive. Some overlap with govulncheck
# (#41) is intentional: govulncheck audits source + reachability;
# Trivy audits what physically shipped in the image.
vuln-type: os,library
exit-code: '1'
deploy:
# Runs only on push to main. PRs (including from forks) never satisfy
# this condition, so `FLY_API_TOKEN` is structurally unreachable from
# any job that runs untrusted PR code.
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
needs: [test, security, image-scan]
runs-on: ubuntu-latest
# Belt-and-suspenders: the workflow-level permissions block above
# already grants only `contents: read`, but a future top-level
# escalation would silently widen this job's scope. Pin the minimum
# here so the deploy job stays read-only against the repo even if
# the header drifts. `flyctl` itself authenticates to Fly via
# `FLY_API_TOKEN`, not via GitHub permissions.
permissions:
contents: read
steps:
- uses: actions/checkout@v6
# Tracks: superfly/flyctl-actions/setup-flyctl@1.6
# Pinned by commit SHA so a tag-swap upstream cannot change what
# holds `FLY_API_TOKEN` during the next deploy. Refresh the comment
# in lockstep with the SHA. Same convention as the Trivy pin in
# `image-scan` (#68) and the govulncheck pin in `security` (#41).
- uses: superfly/flyctl-actions/setup-flyctl@ed8efb33836e8b2096c7fd3ba1c8afe303ebbff1
- name: flyctl deploy
run: flyctl deploy --remote-only
env:
FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}