Release #4
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release | |
| "on": | |
| push: | |
| tags: | |
| - "v*" | |
| workflow_dispatch: | |
| inputs: | |
| release_tag: | |
| description: "Release tag to publish, for example v0.1.0" | |
| required: true | |
| type: string | |
| permissions: | |
| contents: write | |
| packages: write | |
| attestations: write | |
| artifact-metadata: write | |
| id-token: write | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.event.inputs.release_tag || github.ref_name || github.run_id }} | |
| cancel-in-progress: false | |
| jobs: | |
| metadata: | |
| name: Metadata | |
| runs-on: ubuntu-latest | |
| outputs: | |
| release_tag: ${{ steps.vars.outputs.release_tag }} | |
| checkout_ref: ${{ steps.vars.outputs.checkout_ref }} | |
| control_image: ${{ steps.vars.outputs.control_image }} | |
| control_image_name: ${{ steps.vars.outputs.control_image_name }} | |
| dataplane_image: ${{ steps.vars.outputs.dataplane_image }} | |
| dashboard_image: ${{ steps.vars.outputs.dashboard_image }} | |
| steps: | |
| - name: Compute release metadata | |
| id: vars | |
| run: | | |
| if [[ "${GITHUB_EVENT_NAME}" == "workflow_dispatch" ]]; then | |
| release_tag="${{ github.event.inputs.release_tag }}" | |
| else | |
| release_tag="${GITHUB_REF_NAME}" | |
| fi | |
| if [[ -z "${release_tag}" ]]; then | |
| echo "release tag is required" >&2 | |
| exit 1 | |
| fi | |
| owner_lc="${GITHUB_REPOSITORY_OWNER,,}" | |
| checkout_ref="refs/tags/${release_tag}" | |
| control_image_name="ghcr.io/${owner_lc}/nantian-controlplane" | |
| control_image="${control_image_name}:${release_tag}" | |
| dataplane_image="ghcr.io/${owner_lc}/dataplane:${release_tag}" | |
| dashboard_image="ghcr.io/${owner_lc}/dashboard:${release_tag}" | |
| { | |
| echo "release_tag=${release_tag}" | |
| echo "checkout_ref=${checkout_ref}" | |
| echo "control_image=${control_image}" | |
| echo "control_image_name=${control_image_name}" | |
| echo "dataplane_image=${dataplane_image}" | |
| echo "dashboard_image=${dashboard_image}" | |
| } >>"${GITHUB_OUTPUT}" | |
| security-scans: | |
| name: Security Scans | |
| needs: metadata | |
| permissions: | |
| contents: read | |
| security-events: read | |
| uses: ./.github/workflows/security-scans.yml | |
| with: | |
| checkout_ref: ${{ needs.metadata.outputs.checkout_ref }} | |
| controlplane: | |
| name: Controlplane Tests | |
| runs-on: ubuntu-latest | |
| needs: metadata | |
| timeout-minutes: 20 | |
| steps: | |
| - name: Checkout workflow helpers | |
| uses: actions/checkout@v6 | |
| - name: Checkout release source | |
| uses: actions/checkout@v6 | |
| with: | |
| ref: ${{ needs.metadata.outputs.checkout_ref }} | |
| path: release-src | |
| - name: Set up Go | |
| uses: actions/setup-go@v6 | |
| with: | |
| go-version-file: release-src/go.mod | |
| cache-dependency-path: release-src/go.sum | |
| - name: Run Go unit tests | |
| working-directory: release-src | |
| run: go test -count=1 -timeout 5m ./... | |
| kind-smoke: | |
| name: Kind Validation | |
| runs-on: ubuntu-latest | |
| needs: | |
| - metadata | |
| - controlplane | |
| timeout-minutes: 90 | |
| env: | |
| CLUSTER_NAME: release-validation | |
| GATEWAY_API_VERSION: v1.5.1 | |
| CONTROLPLANE_IMAGE: ${{ needs.metadata.outputs.control_image }} | |
| DATAPLANE_IMAGE: ${{ needs.metadata.outputs.dataplane_image }} | |
| DASHBOARD_IMAGE: ${{ needs.metadata.outputs.dashboard_image }} | |
| CONFORMANCE_EXPERIMENTAL: "true" | |
| ALL_FEATURES: "true" | |
| steps: | |
| - name: Checkout workflow helpers | |
| uses: actions/checkout@v6 | |
| - name: Checkout release source | |
| uses: actions/checkout@v6 | |
| with: | |
| ref: ${{ needs.metadata.outputs.checkout_ref }} | |
| fetch-depth: 0 | |
| path: release-src | |
| - name: Set up Go | |
| uses: actions/setup-go@v6 | |
| with: | |
| go-version-file: release-src/go.mod | |
| cache-dependency-path: release-src/go.sum | |
| - name: Install Kind tooling | |
| working-directory: release-src | |
| run: scripts/ci/install-kind-tools.sh | |
| - name: Create kind cluster | |
| working-directory: release-src | |
| run: scripts/ci/create-kind-cluster.sh | |
| - name: Install Gateway API CRDs | |
| working-directory: release-src | |
| run: scripts/ci/install-gateway-api-crds.sh | |
| - name: Build current control-plane image | |
| working-directory: release-src | |
| run: scripts/ci/build-controlplane-image.sh | |
| - name: Load images into kind | |
| working-directory: release-src | |
| run: scripts/ci/load-kind-images.sh | |
| - name: Deploy Nantian Gateway | |
| working-directory: release-src | |
| run: scripts/ci/deploy-kind-conformance.sh | |
| - name: Record image versions | |
| run: | | |
| echo "=== Images under test ===" | |
| kubectl get pods -n nantian-gw -o json | jq -r '.items[] | .spec.containers[] | " \(.name): \(.image)"' | |
| echo "=== Image digests ===" | |
| kubectl get pods -n nantian-gw -o json | jq -r '.items[] | .status.containerStatuses[] | " \(.name): \(.imageID)"' | |
| - name: Run smoke test | |
| run: CLUSTER_NAME="$CLUSTER_NAME" GATEWAY_HTTP_PORT=80 ./test/e2e/smoke/run.sh --no-cleanup --skip-bootstrap | |
| - name: Run full Gateway API conformance | |
| id: conformance | |
| env: | |
| RELEASE_TAG: ${{ needs.metadata.outputs.release_tag }} | |
| working-directory: release-src | |
| run: | | |
| mkdir -p dist/conformance | |
| report_path="${GITHUB_WORKSPACE}/release-src/dist/conformance/report.yaml" | |
| set +e | |
| go test -tags=conformance -count=1 -v -timeout 30m ./conformance/ \ | |
| -args \ | |
| -gateway-class nantian-gw \ | |
| -report-output "$report_path" \ | |
| -organization "Nantian Gateway" \ | |
| -project "Nantian Gateway" \ | |
| -url "https://github.com/nantian-gw/gateway" \ | |
| -version "${RELEASE_TAG}" \ | |
| -contact "https://github.com/nantian-gw/gateway/issues" 2>&1 \ | |
| | tee dist/conformance/run.log | |
| status=${PIPESTATUS[0]} | |
| echo "exit_code=${status}" >>"${GITHUB_OUTPUT}" | |
| exit "${status}" | |
| - name: Collect diagnostics on failure | |
| if: failure() | |
| working-directory: release-src | |
| run: ARTIFACT_DIR=tmp/conformance-diagnostics scripts/ci/collect-kind-diagnostics.sh | |
| - name: Upload conformance artifacts | |
| if: always() | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: conformance-${{ needs.metadata.outputs.release_tag }} | |
| path: | | |
| release-src/dist/conformance/ | |
| release-src/tmp/conformance-diagnostics/ | |
| if-no-files-found: warn | |
| - name: Cleanup | |
| if: always() | |
| run: command -v kind >/dev/null 2>&1 && kind delete cluster --name "$CLUSTER_NAME" || true | |
| publish: | |
| name: Publish Release Images | |
| runs-on: ubuntu-latest | |
| needs: | |
| - metadata | |
| - controlplane | |
| - kind-smoke | |
| timeout-minutes: 45 | |
| outputs: | |
| control_digest: ${{ steps.build-controlplane.outputs.digest }} | |
| steps: | |
| - name: Checkout workflow helpers | |
| uses: actions/checkout@v6 | |
| - name: Checkout release source | |
| uses: actions/checkout@v6 | |
| with: | |
| ref: ${{ needs.metadata.outputs.checkout_ref }} | |
| path: release-src | |
| - name: Set up Go | |
| uses: actions/setup-go@v6 | |
| with: | |
| go-version-file: release-src/go.mod | |
| cache-dependency-path: release-src/go.sum | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v4 | |
| - name: Log in to GitHub Container Registry | |
| uses: docker/login-action@v4 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Build and push controlplane image | |
| id: build-controlplane | |
| uses: docker/build-push-action@v7 | |
| with: | |
| context: release-src | |
| file: release-src/Dockerfile | |
| push: true | |
| tags: ${{ needs.metadata.outputs.control_image }} | |
| - name: Prepare image metadata directory | |
| run: mkdir -p release-src/dist/image-metadata | |
| - name: Generate image provenance | |
| env: | |
| RELEASE_TAG: ${{ needs.metadata.outputs.release_tag }} | |
| CONTROL_DIGEST: ${{ steps.build-controlplane.outputs.digest }} | |
| CONTROL_IMAGE: ${{ needs.metadata.outputs.control_image }} | |
| TIMESTAMP: ${{ github.event.repository.updated_at }} | |
| run: | | |
| cat > release-src/dist/image-metadata/provenance.json <<HEREDOC | |
| { | |
| "release": "${RELEASE_TAG}", | |
| "ci_run": "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}", | |
| "controlplane": { | |
| "image": "${CONTROL_IMAGE}", | |
| "digest": "${CONTROL_DIGEST}" | |
| }, | |
| "timestamp": "${TIMESTAMP}" | |
| } | |
| HEREDOC | |
| - name: Upload image metadata artifact | |
| if: always() | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: image-metadata-${{ needs.metadata.outputs.release_tag }} | |
| path: release-src/dist/image-metadata/ | |
| if-no-files-found: warn |