initial commit
Some checks failed
ci / go (push) Has been cancelled
ci / admin-ui (push) Has been cancelled
ci / runtime-sdk (push) Has been cancelled
ci / helm (push) Has been cancelled
ci / openapi (push) Has been cancelled
ci / container (push) Has been cancelled
ci / release-config (push) Has been cancelled
ci / shared styling (push) Has been cancelled
ci / security (push) Has been cancelled
ci / all green (push) Has been cancelled
Some checks failed
ci / go (push) Has been cancelled
ci / admin-ui (push) Has been cancelled
ci / runtime-sdk (push) Has been cancelled
ci / helm (push) Has been cancelled
ci / openapi (push) Has been cancelled
ci / container (push) Has been cancelled
ci / release-config (push) Has been cancelled
ci / shared styling (push) Has been cancelled
ci / security (push) Has been cancelled
ci / all green (push) Has been cancelled
This commit is contained in:
commit
951dd8d26b
175 changed files with 50041 additions and 0 deletions
289
.github/workflows/ci.yml
vendored
Normal file
289
.github/workflows/ci.yml
vendored
Normal file
|
|
@ -0,0 +1,289 @@
|
|||
name: ci
|
||||
|
||||
# One workflow for the whole pre-merge gate, with the jobs split so that a failure
|
||||
# names the thing that broke instead of "the build".
|
||||
#
|
||||
# The job set is deliberately the same as `make verify`, and each job calls the
|
||||
# Makefile rather than repeating the commands. A CI script that differs from the
|
||||
# Makefile eventually differs in a way nobody notices, and then the Makefile stops
|
||||
# being a usable local gate.
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
merge_group:
|
||||
|
||||
# A new push to the same branch makes the in-flight run irrelevant: cancelling it
|
||||
# saves runner minutes and stops an old result being reported against new code.
|
||||
concurrency:
|
||||
group: ci-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
# Matches the Go directive in go.mod. setup-go would read it from there, but
|
||||
# pinning it here means a toolchain bump shows up as a reviewable diff here too.
|
||||
GO_VERSION: "1.27.1"
|
||||
NODE_VERSION: "24"
|
||||
|
||||
jobs:
|
||||
go:
|
||||
name: go
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
# The module and build caches live in the runner's cache rather than in
|
||||
# the workspace, so a checkout never carries a stale artefact into a test.
|
||||
cache: true
|
||||
|
||||
- name: Verify formatting
|
||||
run: make fmt-check
|
||||
|
||||
- name: Vet
|
||||
run: go vet ./cmd/... ./internal/...
|
||||
|
||||
- name: Lint
|
||||
run: make lint-go
|
||||
env:
|
||||
# golangci-lint caches analysis keyed on the Go version and the source.
|
||||
GOLANGCI_LINT_CACHE: ${{ github.workspace }}/.cache/golangci-lint
|
||||
|
||||
- name: Test with the race detector
|
||||
run: make test-go
|
||||
|
||||
- name: Build
|
||||
run: make build-go
|
||||
|
||||
web:
|
||||
name: admin-ui
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
cache: npm
|
||||
cache-dependency-path: web/package-lock.json
|
||||
|
||||
- name: Install
|
||||
# `npm ci`, never `npm install`: it installs exactly the lockfile, and it
|
||||
# fails when the lockfile and package.json disagree instead of quietly
|
||||
# resolving something new.
|
||||
run: npm ci --no-audit --no-fund
|
||||
working-directory: web
|
||||
|
||||
- name: Lint
|
||||
run: make lint-web
|
||||
|
||||
- name: Test
|
||||
run: make test-web
|
||||
|
||||
- name: Build
|
||||
run: make build-web
|
||||
|
||||
sdk:
|
||||
name: runtime-sdk
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
cache: npm
|
||||
cache-dependency-path: sdk/package-lock.json
|
||||
|
||||
- name: Install
|
||||
run: npm ci --no-audit --no-fund
|
||||
working-directory: sdk
|
||||
|
||||
- name: Lint and typecheck
|
||||
run: make lint-sdk
|
||||
|
||||
- name: Test
|
||||
run: make test-sdk
|
||||
|
||||
- name: Build
|
||||
run: make build-sdk
|
||||
|
||||
helm:
|
||||
name: helm
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- uses: azure/setup-helm@v5
|
||||
with:
|
||||
version: v3.19.0
|
||||
|
||||
- name: Lint strictly
|
||||
# --strict turns warnings into errors, which is what stops a chart shipping
|
||||
# with an icon or maintainer field quietly missing.
|
||||
run: helm lint --strict deploy/helm/go-bananas
|
||||
|
||||
- name: Render the whole configuration matrix
|
||||
# Not `helm lint`: lint only sees the default values. This renders every
|
||||
# documented configuration and checks both that each valid one produces
|
||||
# parseable YAML and that each invalid one is refused with a message
|
||||
# naming the value to change.
|
||||
run: make helm-matrix
|
||||
|
||||
contract:
|
||||
name: openapi
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: The document must be valid OpenAPI 3.1
|
||||
# A specification that does not parse is worse than no specification,
|
||||
# because every client generator will trust it.
|
||||
run: npx --yes @redocly/cli@latest lint openapi.yaml
|
||||
|
||||
container:
|
||||
name: container
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- uses: docker/setup-buildx-action@v3
|
||||
|
||||
# Load the image into the local daemon so the steps after this can run it.
|
||||
# Without `load` the result only exists in the build cache, and there is
|
||||
# nothing to inspect.
|
||||
- name: Build
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: Dockerfile
|
||||
push: false
|
||||
load: true
|
||||
tags: go-bananas:ci
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
|
||||
- name: The image must actually serve
|
||||
run: |
|
||||
set -eu
|
||||
docker run -d --name bananas \
|
||||
-e BANANAS_ENVIRONMENT=development \
|
||||
-e BANANAS_AUTH_MODE=dev \
|
||||
-e BANANAS_PUBLIC_BASE_URL=http://localhost:8080 \
|
||||
-p 8080:8080 \
|
||||
go-bananas:ci
|
||||
|
||||
# Poll rather than sleeping a fixed time: a fixed sleep is either too
|
||||
# short on a loaded runner or wasted time on a fast one.
|
||||
for i in $(seq 1 60); do
|
||||
if curl -fsS http://localhost:8080/healthz >/dev/null 2>&1; then
|
||||
echo "healthy after ${i}s"
|
||||
break
|
||||
fi
|
||||
if [ "$i" -eq 60 ]; then
|
||||
echo "the container never became healthy"
|
||||
docker logs bananas
|
||||
exit 1
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
# The admin UI must be served from the image, not just the API: a
|
||||
# container that starts and then 404s on its own dashboard is a
|
||||
# regression the health check would not catch.
|
||||
curl -fsS http://localhost:8080/rt/v1/manifest.json >/dev/null
|
||||
curl -fsS http://localhost:8080/api/v1/auth/me | grep -q '"mode"'
|
||||
|
||||
echo "--- running as ---"
|
||||
docker exec bananas id
|
||||
# The image declares USER 65532, so anything else means the build lost it.
|
||||
test "$(docker exec bananas id -u)" = "65532"
|
||||
|
||||
- name: Logs on failure
|
||||
if: failure()
|
||||
run: docker logs bananas || true
|
||||
|
||||
- name: Clean up
|
||||
if: always()
|
||||
run: docker rm -f bananas || true
|
||||
|
||||
release-config:
|
||||
name: release-config
|
||||
runs-on: ubuntu-latest
|
||||
# Validating the release configuration on every push is cheap, and a broken
|
||||
# goreleaser config discovered at tag time is a release that cannot be cut.
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
|
||||
- name: Install GoReleaser
|
||||
uses: goreleaser/goreleaser-action@v6
|
||||
with:
|
||||
distribution: goreleaser
|
||||
version: v2.18.2
|
||||
args: check
|
||||
|
||||
styling:
|
||||
name: shared styling
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
|
||||
- uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
|
||||
# The two checks that cannot be done in jsdom: whether the rendered contract CSS
|
||||
# resolves to the right computed values, and whether an application that has not
|
||||
# touched its stylesheet actually follows the contract. The second is the one that
|
||||
# decides whether the consolidation is real.
|
||||
- name: Contract and controls
|
||||
run: make check-contract
|
||||
|
||||
- name: go-loose pilot
|
||||
run: make check-pilot
|
||||
|
||||
security:
|
||||
name: security
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Dependency review
|
||||
uses: actions/dependency-review-action@v4
|
||||
with:
|
||||
# Only on pull requests: the API needs a base branch to compare against,
|
||||
# and it is the pull request that the review is protecting.
|
||||
fail-on-severity: moderate
|
||||
|
||||
all-green:
|
||||
name: all green
|
||||
# The single required status check. It depends on every job above and does
|
||||
# nothing itself, so that a branch can be made to require one stable name
|
||||
# instead of a list that has to be edited every time a job is added.
|
||||
if: always()
|
||||
needs: [go, web, sdk, helm, contract, container, styling, release-config, security]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Fail if any job failed
|
||||
run: |
|
||||
results='${{ toJSON(needs) }}'
|
||||
echo "$results" | jq -r 'to_entries[] | "\(.key): \(.value.result)"'
|
||||
if echo "$results" | jq -e 'to_entries | any(.value.result != "success")' >/dev/null; then
|
||||
echo "one or more jobs did not succeed"
|
||||
exit 1
|
||||
fi
|
||||
echo "all jobs succeeded"
|
||||
Loading…
Add table
Add a link
Reference in a new issue