ci: skip tests on PRs without Rust changes (#825) #487
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: Build & Deploy | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| force_staging: | |
| description: 'Force push to staging even during freeze window' | |
| required: false | |
| type: boolean | |
| default: false | |
| push: | |
| branches: | |
| - main | |
| tags: | |
| - 'v*' | |
| env: | |
| REGISTRY: docker.io | |
| IMAGE_REPOSITORY: ${{ vars.DOCKER_REGISTRY_USER }}/cloud-api | |
| jobs: | |
| reproducible-docker-image: | |
| name: Reproducible Docker Image | |
| permissions: | |
| contents: read | |
| packages: write | |
| attestations: write | |
| id-token: write | |
| runs-on: [self-hosted, infra] | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| - name: Log in to Docker registry | |
| uses: docker/login-action@946f94de75ea52995b6aa1e54fd3e0aeed6cc573 | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ vars.DOCKER_REGISTRY_USER }} | |
| password: ${{ secrets.DOCKER_REGISTRY_TOKEN }} | |
| - name: Extract image tags from GitHub ref (branch or tag) | |
| run: | | |
| if [[ "${GITHUB_REF_TYPE}" == 'tag' ]]; then | |
| TAG=${GITHUB_REF_NAME#v} | |
| echo "Using '${TAG}' image tag for ${GITHUB_REF_NAME} tag" | |
| elif [[ "${GITHUB_REF_TYPE}" == 'branch' ]]; then | |
| TAG=$(if [[ "${GITHUB_REF_NAME}" == 'main' ]]; then echo 'latest'; else echo 'dev'; fi) | |
| echo "Using '${TAG}' image tag for ${GITHUB_REF_NAME} branch" | |
| else | |
| echo "Unsupported ref type: ${GITHUB_REF_TYPE}" >&2 | |
| exit 1 | |
| fi | |
| if [ -z "${TAG}" ]; then | |
| echo "Unable to parse image tag from ${GITHUB_REF_TYPE}: ${GITHUB_REF_NAME}" >&2 | |
| exit 1 | |
| fi | |
| echo "IMAGE_REFERENCE=${{ env.REGISTRY }}/${{ env.IMAGE_REPOSITORY }}:${TAG}" >> "$GITHUB_ENV" | |
| # On main branch, also promote to staging for continuous integration | |
| # Skip staging tag on Tuesday (2) and Wednesday (3) — staging is frozen | |
| # for prod-candidate testing until Thursday promotion | |
| if [[ "${GITHUB_REF_NAME}" == 'main' ]]; then | |
| FORCE_STAGING="${{ github.event.inputs.force_staging }}" | |
| DAY_OF_WEEK=$(date -u +%u) | |
| if [[ "$DAY_OF_WEEK" -ge 2 && "$DAY_OF_WEEK" -le 3 ]] && [[ "$FORCE_STAGING" != 'true' ]]; then | |
| echo "Staging frozen (day $DAY_OF_WEEK) — skipping :staging tag (use force_staging to override)" | |
| else | |
| echo "ALSO_TAG_STAGING=true" >> "$GITHUB_ENV" | |
| fi | |
| fi | |
| - name: Install build dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y skopeo jq | |
| - name: Build and push reproducible image | |
| run: | | |
| ./build-image.sh --push "${{ env.IMAGE_REFERENCE }}" | |
| - name: Get image digest | |
| run: | | |
| DIGEST=$(skopeo inspect oci-archive:./oci.tar | jq -r '.Digest') | |
| if [ -z "${DIGEST}" ]; then | |
| echo "Failed to get image digest from OCI archive" >&2 | |
| exit 1 | |
| fi | |
| echo "IMAGE_DIGEST=${DIGEST}" >> "$GITHUB_ENV" | |
| - name: Generate artifact attestation | |
| uses: actions/attest-build-provenance@v4 | |
| with: | |
| subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_REPOSITORY }} | |
| subject-digest: ${{ env.IMAGE_DIGEST }} | |
| push-to-registry: true | |
| - name: Install cosign | |
| uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2 | |
| - name: Sign image with cosign (keyless) | |
| run: | | |
| cosign sign --yes "${{ env.REGISTRY }}/${{ env.IMAGE_REPOSITORY }}@${{ env.IMAGE_DIGEST }}" | |
| - name: Tag staging for continuous integration | |
| if: env.ALSO_TAG_STAGING == 'true' | |
| run: | | |
| STAGING_REF="${{ env.REGISTRY }}/${{ env.IMAGE_REPOSITORY }}:staging" | |
| # Immutable date+sha staging tag for rollback (format: staging-YYYYMMDD-<shortsha>) | |
| SHORT_SHA=$(echo "${GITHUB_SHA}" | cut -c1-7) | |
| STAMP=$(date -u +%Y%m%d) | |
| STAGING_STAMPED_REF="${{ env.REGISTRY }}/${{ env.IMAGE_REPOSITORY }}:staging-${STAMP}-${SHORT_SHA}" | |
| skopeo copy oci-archive:./oci.tar "docker://${STAGING_REF}" | |
| skopeo copy oci-archive:./oci.tar "docker://${STAGING_STAMPED_REF}" | |
| echo "STAGING_REFERENCE=${STAGING_REF}" >> "$GITHUB_ENV" | |
| echo "STAGING_STAMPED_REFERENCE=${STAGING_STAMPED_REF}" >> "$GITHUB_ENV" | |
| - name: Trigger staging deployment | |
| if: env.ALSO_TAG_STAGING == 'true' | |
| uses: peter-evans/repository-dispatch@28959ce8df70de7be546dd1250a005dd32156697 # v4.0.1 | |
| with: | |
| token: ${{ secrets.REPOSITORY_DISPATCH_TOKEN }} | |
| repository: nearai/cvm-ansible-playbooks | |
| event-type: deploy-cloud-api-stg | |
| - name: Generate build summary | |
| run: | | |
| { | |
| echo "## cloud-api docker image" | |
| echo "" | |
| echo "- tag: \`${{ env.IMAGE_REFERENCE }}\`" | |
| echo "- digest: \`${{ env.IMAGE_DIGEST }}\`" | |
| echo "- sigstore: https://search.sigstore.dev/?hash=${{ env.IMAGE_DIGEST }}" | |
| if [[ "${{ env.ALSO_TAG_STAGING }}" == 'true' ]]; then | |
| echo "- staging: \`${{ env.STAGING_REFERENCE }}\`" | |
| echo "- staging (stamped): \`${{ env.STAGING_STAMPED_REFERENCE }}\`" | |
| fi | |
| } >> "$GITHUB_STEP_SUMMARY" |