Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions .github/actions/validate-gcp-manifests/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
name: Validate GCP platform manifests
description: >-
Render each GCP tenant's platform manifest stream (kustomize overlay plus the
committed edge manifest) and validate it with kubeconform -strict. This is the
single definition shared by the deploy Validate job (_gcp-dev.yml) and the
PR-tier Lint (k8s schemas) quality job, so a pull request is rejected for
exactly what a deploy would reject. GKE CRDs (BackendConfig, FrontendConfig,
ManagedCertificate) have no schema here by design: they are rendered at deploy
time by scripts/gcp/render_edge_manifest.py, never in the kustomize base.

inputs:
environments:
description: Space-separated GCP overlay names under platform/k8s/gcp/overlays, or "all".
required: true

runs:
using: composite
steps:
- uses: azure/setup-kubectl@776406bce94f63e41d621b960d78ee25c8b76ede
with:
version: v1.34.1

- name: Install kubeconform
shell: bash
env:
KUBECONFORM_VERSION: v0.7.0
run: |
set -euo pipefail
# ADR-037-R3: verify the download against the release CHECKSUMS
# manifest before extraction. The archive is saved under the exact name
# the manifest references so `sha256sum -c` matches.
dir="${RUNNER_TEMP}/kubeconform-gcp"
mkdir -p "${dir}"
curl -fsSL -o "${dir}/kubeconform-linux-amd64.tar.gz" \
"https://github.com/yannh/kubeconform/releases/download/${KUBECONFORM_VERSION}/kubeconform-linux-amd64.tar.gz"
curl -fsSL -o "${dir}/CHECKSUMS" \
"https://github.com/yannh/kubeconform/releases/download/${KUBECONFORM_VERSION}/CHECKSUMS"
(cd "${dir}" && grep "kubeconform-linux-amd64.tar.gz" CHECKSUMS | sha256sum -c -)
tar -xzf "${dir}/kubeconform-linux-amd64.tar.gz" -C "${dir}" kubeconform

- name: Render and validate
shell: bash
env:
ENVIRONMENTS: ${{ inputs.environments }}
run: |
set -euo pipefail
overlays_root="platform/k8s/gcp/overlays"
if [ "${ENVIRONMENTS}" = "all" ]; then
environments=$(find "${overlays_root}" -mindepth 2 -maxdepth 2 -name kustomization.yaml \
-exec dirname {} \; | xargs -n1 basename | sort)
else
environments="${ENVIRONMENTS}"
fi
if [ -z "${environments}" ]; then
echo "::error::No GCP overlays to validate"
exit 1
fi

failed=0
for environment in ${environments}; do
if ! [[ "${environment}" =~ ^[a-z0-9-]+$ ]] || [ ! -f "${overlays_root}/${environment}/kustomization.yaml" ]; then
echo "::error::Unknown GCP overlay '${environment}'"
failed=1
continue
fi
rendered="${RUNNER_TEMP}/gcp-platform-${environment}.yaml"
(
kubectl kustomize "${overlays_root}/${environment}"
printf '\n---\n'
cat "${overlays_root}/${environment}/platform-edge.generated.yaml"
) > "${rendered}"
echo "Validating ${environment}"
if ! "${RUNNER_TEMP}/kubeconform-gcp/kubeconform" -strict -summary "${rendered}"; then
echo "::error::GCP overlay '${environment}' failed strict manifest validation"
failed=1
fi
done
exit "${failed}"
2 changes: 2 additions & 0 deletions .github/quality-path-filters.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ schema_version: 1

force_full_matrix:
- .github/workflows/**
# Local composite actions are CI control plane called by the workflows.
- .github/actions/**
- .github/quality-path-filters.yaml

quality_units:
Expand Down
29 changes: 5 additions & 24 deletions .github/workflows/_gcp-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,43 +73,24 @@ jobs:
name: Validate (${{ inputs.environment }})
# Validation does not need deploy-network access; keep PR checks off the deploy runner pool.
runs-on: ubuntu-latest
env:
GCP_ENVIRONMENT: ${{ inputs.environment }}
KUBECONFORM_VERSION: v0.7.0
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
persist-credentials: false
- uses: hashicorp/setup-terraform@b9cd54a3c349d3f38e8881555d616ced269862dd
with:
terraform_version: "1.16.1"
- uses: azure/setup-kubectl@776406bce94f63e41d621b960d78ee25c8b76ede
with:
version: v1.34.1
- name: Install kubeconform
run: |
# ADR-037-R3: verify the download against the release CHECKSUMS
# manifest before extraction. The archive is saved under the exact name
# the manifest references so `sha256sum -c` matches.
curl -fsSL -o /tmp/kubeconform-linux-amd64.tar.gz \
"https://github.com/yannh/kubeconform/releases/download/${KUBECONFORM_VERSION}/kubeconform-linux-amd64.tar.gz"
curl -fsSL -o /tmp/kubeconform.CHECKSUMS \
"https://github.com/yannh/kubeconform/releases/download/${KUBECONFORM_VERSION}/CHECKSUMS"
(cd /tmp && grep "kubeconform-linux-amd64.tar.gz" kubeconform.CHECKSUMS | sha256sum -c -)
tar -xzf /tmp/kubeconform-linux-amd64.tar.gz -C /tmp kubeconform
- run: terraform fmt -check -recursive
working-directory: platform/terraform/gcp
- run: terraform init -backend=false
working-directory: platform/terraform/gcp/environments/${{ inputs.environment }}
- run: terraform validate
working-directory: platform/terraform/gcp/environments/${{ inputs.environment }}
- run: |
(
kubectl kustomize "platform/k8s/gcp/overlays/${GCP_ENVIRONMENT}"
printf '\n---\n'
cat "platform/k8s/gcp/overlays/${GCP_ENVIRONMENT}/platform-edge.generated.yaml"
) > /tmp/gcp-platform.yaml
- run: /tmp/kubeconform -strict -summary /tmp/gcp-platform.yaml
# Shared with the PR-tier Lint (k8s schemas) job so a PR is rejected for
# exactly what this deploy gate rejects.
- uses: ./.github/actions/validate-gcp-manifests
with:
environments: ${{ inputs.environment }}

prepare:
# Runs on the requested GCP tenant's same-named runner, provisioned by
Expand Down
8 changes: 8 additions & 0 deletions .github/workflows/_quality.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1157,6 +1157,14 @@ jobs:
-kubernetes-version 1.31.0 \
"${RUNNER_TEMP}/rendered-k8s/"*.yaml

# The roots check above skips schema-less kinds (-ignore-missing-schemas),
# so on its own it passes manifests the GCP deploy gate rejects. Run the
# deploy gate's exact validation (shared action) over every GCP tenant.
- name: Validate GCP tenants exactly as the deploy gate does
uses: ./.github/actions/validate-gcp-manifests
with:
environments: all

# ===========================================================================
# Type Checking (blocking quality gate, #564)
#
Expand Down
Loading