198 lines
7.4 KiB
YAML
198 lines
7.4 KiB
YAML
name: CI and deploy
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
pull_request:
|
|
branches: [main]
|
|
workflow_dispatch:
|
|
|
|
jobs:
|
|
verify:
|
|
runs-on: docker
|
|
steps:
|
|
- name: Check out repository
|
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
|
|
|
- name: Scan secrets
|
|
run: |
|
|
docker run --rm -v "$PWD:/repo" \
|
|
ghcr.io/gitleaks/gitleaks:v8.30.1 \
|
|
detect --source /repo --redact -v
|
|
|
|
- name: Test API
|
|
run: |
|
|
docker run --rm -v "$PWD/apps/api:/src" -w /src golang:1.26 \
|
|
bash -ec 'go vet ./... && go test -race ./...'
|
|
|
|
- name: Test load generator
|
|
run: |
|
|
docker run --rm -v "$PWD/apps/loadgen:/src" -w /src golang:1.26 \
|
|
bash -ec 'go vet ./... && go test -race ./... && test "$(wc -l < main.go)" -lt 200'
|
|
|
|
- name: Lint Go
|
|
run: |
|
|
docker run --rm -v "$PWD:/repo" -w /repo/apps/api \
|
|
golangci/golangci-lint:v2.12.2 golangci-lint run
|
|
docker run --rm -v "$PWD:/repo" -w /repo/apps/loadgen \
|
|
golangci/golangci-lint:v2.12.2 golangci-lint run
|
|
|
|
- name: Check reachable Go vulnerabilities
|
|
run: |
|
|
docker run --rm -v "$PWD/apps/api:/src" -w /src golang:1.26 \
|
|
bash -ec 'go run golang.org/x/vuln/cmd/govulncheck@v1.7.0 ./...'
|
|
docker run --rm -v "$PWD/apps/loadgen:/src" -w /src golang:1.26 \
|
|
bash -ec 'go run golang.org/x/vuln/cmd/govulncheck@v1.7.0 ./...'
|
|
|
|
- name: Check frontend and shell syntax
|
|
run: |
|
|
docker run --rm -v "$PWD:/repo" -w /repo node:24-alpine \
|
|
node --check apps/web/app.js
|
|
docker run --rm -v "$PWD:/repo" -w /repo bash:5.3 \
|
|
bash -ec 'for file in scripts/k3d/lab.sh scripts/provision/bootstrap.sh scripts/provision/lab.sh; do bash -n "$file"; done'
|
|
|
|
- name: Validate Terraform
|
|
run: |
|
|
for stack in terraform/infra terraform/platform
|
|
do
|
|
docker run --rm -v "$PWD:/work" -w "/work/$stack" \
|
|
hashicorp/terraform:1.15.9 fmt -check
|
|
docker run --rm -v "$PWD:/work" -w "/work/$stack" \
|
|
hashicorp/terraform:1.15.9 init -backend=false -lockfile=readonly
|
|
docker run --rm -v "$PWD:/work" -w "/work/$stack" \
|
|
hashicorp/terraform:1.15.9 validate
|
|
done
|
|
|
|
- name: Validate Compose and Kubernetes configuration
|
|
env:
|
|
CLUSTER_API_UPSTREAM: 192.0.2.1:8080
|
|
NEREUS_HOST: nereus.example.test
|
|
run: |
|
|
docker compose -f compose.yaml config -q
|
|
docker compose -f build/compose.mini.yaml config -q
|
|
for path in \
|
|
deploy/base \
|
|
deploy/overlays/dev \
|
|
deploy/overlays/prod \
|
|
deploy/rollouts \
|
|
deploy/observability
|
|
do
|
|
docker run --rm -v "$PWD:/work" -w /work \
|
|
registry.k8s.io/kubectl:v1.33.4 kustomize "$path" >/dev/null
|
|
done
|
|
|
|
- name: Scan configuration
|
|
run: |
|
|
docker run --rm -v "$PWD:/repo" -w /repo aquasec/trivy:0.74.0 \
|
|
config --severity HIGH,CRITICAL --exit-code 1 \
|
|
--skip-dirs .git --skip-dirs terraform .
|
|
|
|
publish:
|
|
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
|
needs: verify
|
|
runs-on: docker
|
|
env:
|
|
API_IMAGE: git.fiwlabs.dev/fiwdev/nereus-api:${{ github.sha }}
|
|
LOADGEN_IMAGE: git.fiwlabs.dev/fiwdev/nereus-loadgen:${{ github.sha }}
|
|
WEB_IMAGE: git.fiwlabs.dev/fiwdev/nereus-web:${{ github.sha }}
|
|
DOCKER_CONFIG: ${{ github.workspace }}/.ci/docker
|
|
steps:
|
|
- name: Check out repository
|
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
|
|
|
- name: Log in to registry
|
|
env:
|
|
REGISTRY_USERNAME: ${{ secrets.REGISTRY_USERNAME }}
|
|
REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }}
|
|
run: |
|
|
install -d -m 0700 "$DOCKER_CONFIG"
|
|
printf '%s' "$REGISTRY_PASSWORD" | \
|
|
docker login git.fiwlabs.dev --username "$REGISTRY_USERNAME" --password-stdin
|
|
|
|
- name: Build and push images
|
|
run: |
|
|
docker build -f build/api.Dockerfile \
|
|
--build-arg "APP_VERSION=${{ github.sha }}" \
|
|
-t "$API_IMAGE" .
|
|
docker build -f build/loadgen.Dockerfile -t "$LOADGEN_IMAGE" .
|
|
docker build -f build/web.Dockerfile -t "$WEB_IMAGE" .
|
|
|
|
for image in "$API_IMAGE" "$LOADGEN_IMAGE" "$WEB_IMAGE"
|
|
do
|
|
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
|
|
aquasec/trivy:0.74.0 image --severity HIGH,CRITICAL \
|
|
--ignore-unfixed --exit-code 1 "$image"
|
|
done
|
|
|
|
docker push "$API_IMAGE"
|
|
docker push "$LOADGEN_IMAGE"
|
|
docker push "$WEB_IMAGE"
|
|
|
|
- name: Remove registry credentials
|
|
if: always()
|
|
run: rm -rf .ci
|
|
|
|
deploy:
|
|
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
|
needs: publish
|
|
runs-on: docker
|
|
steps:
|
|
- name: Check out repository
|
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
|
|
|
- name: Prepare cluster access
|
|
env:
|
|
REGISTRY_USERNAME: ${{ secrets.REGISTRY_USERNAME }}
|
|
REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }}
|
|
KUBECONFIG_B64: ${{ secrets.KUBECONFIG_B64 }}
|
|
run: |
|
|
install -d -m 0700 .ci
|
|
printf '%s' "$KUBECONFIG_B64" | base64 -d >.ci/kubeconfig
|
|
chmod 0600 .ci/kubeconfig
|
|
printf '%s' "$REGISTRY_PASSWORD" | \
|
|
docker --config "$PWD/.ci/docker" login git.fiwlabs.dev \
|
|
--username "$REGISTRY_USERNAME" --password-stdin
|
|
|
|
- name: Apply and verify rollout
|
|
run: |
|
|
kube() {
|
|
docker run --rm -i --network host \
|
|
-v "$PWD:/work" -w /work \
|
|
registry.k8s.io/kubectl:v1.33.4 \
|
|
--kubeconfig=/work/.ci/kubeconfig "$@"
|
|
}
|
|
|
|
kube create namespace nereus --dry-run=client -o yaml | kube apply -f -
|
|
kube create secret generic nereus-registry \
|
|
--namespace nereus \
|
|
--type kubernetes.io/dockerconfigjson \
|
|
--from-file=.dockerconfigjson=/work/.ci/docker/config.json \
|
|
--dry-run=client -o yaml | kube apply -f -
|
|
|
|
kube get secret nereus-db --namespace nereus >/dev/null
|
|
kube apply -k deploy/observability
|
|
|
|
# Set the built tag before applying. Applying the overlay first would
|
|
# roll out its pinned 0.1.0 tag and then roll out a second time on the
|
|
# patch, running the pre-promotion analysis against the wrong image.
|
|
install -d .ci/release
|
|
cat >.ci/release/kustomization.yaml <<'EOF'
|
|
resources:
|
|
- ../../deploy/overlays/prod
|
|
images:
|
|
- name: git.fiwlabs.dev/fiwdev/nereus-api
|
|
newTag: ${{ github.sha }}
|
|
- name: git.fiwlabs.dev/fiwdev/nereus-loadgen
|
|
newTag: ${{ github.sha }}
|
|
EOF
|
|
kube apply -k .ci/release
|
|
|
|
kube rollout status deployment/nereus-loadgen --namespace nereus --timeout=5m
|
|
kube rollout status deployment/nereus-loadgen-preview --namespace nereus --timeout=5m
|
|
kube wait rollout.argoproj.io/nereus-api --namespace nereus \
|
|
--for=jsonpath='{.status.phase}'=Healthy --timeout=10m
|
|
kube get rollout.argoproj.io/nereus-api --namespace nereus
|
|
|
|
- name: Remove cluster credentials
|
|
if: always()
|
|
run: rm -rf .ci
|