-
Notifications
You must be signed in to change notification settings - Fork 0
159 lines (146 loc) · 6.26 KB
/
Copy pathpreview-image-build.yml
File metadata and controls
159 lines (146 loc) · 6.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
---
# api/.github/workflows/preview-image-build.yml — Phase 1b companion.
#
# Builds + pushes a `:pr-<N>-<sha>` GHCR tag of the api image on every PR
# open / sync / reopen. The infra repo's preview-create workflow (also
# Phase 1b) pulls this exact tag when it provisions the per-PR namespace.
#
# Why a sibling workflow rather than a tag-add on deploy.yml: deploy.yml
# only fires on push to master. PR builds need a parallel pipeline.
#
# Scope:
# - Mirrors deploy.yml's image-build step (sibling repo checkout for
# common/ + proto/, same Dockerfile, same buildx invocation) but
# SKIPS the test gate (CI's ci.yml already runs the test suite on
# PRs; the preview-image build is purely "package the binary so a
# preview env can pull it"). Faster turnaround, no duplicated load
# on the test runner.
# - Tags ONLY `:pr-<N>-<sha>`. Never touches `:latest` or `:master-*`
# (production tag namespace is reserved for deploy.yml). Per
# IMAGE-RETENTION-POLICY.md the pin-prod-images workflow only
# protects `master-*` + semver tags; `pr-*` tags are free to be
# reaped by GHCR retention.
# - Soft-fails if GHCR_PUSH_TOKEN is unset (matches deploy.yml's
# auth posture — GHCR_PUSH_TOKEN is a classic PAT with write:packages
# for the InstaNode-dev org; per-job GITHUB_TOKEN cannot push to
# the org-owned package, see deploy.yml line 230 comment).
# - Does NOT deploy. The infra repo's preview-create workflow handles
# the `kubectl set image` equivalent (applies a fresh Deployment).
#
# Concurrency: a rapid push that fires this workflow twice for the same
# PR will cancel the older run — the latest SHA is what the preview env
# wants.
name: preview-image-build
on:
pull_request:
types: [opened, synchronize, reopened]
# Same docs-only path skip as deploy.yml: preview images for a
# markdown-only PR are useless and burn CI minutes.
paths-ignore:
- '**.md'
- 'docs/**'
- 'CLAUDE.md'
- '.gitignore'
- 'LICENSE'
- 'BUGBASH-*/**'
permissions:
contents: read
packages: write
concurrency:
group: preview-image-build-${{ github.event.pull_request.number }}
cancel-in-progress: true
env:
IMAGE_REPO: ghcr.io/instanode-dev/instant-api
jobs:
build:
name: Build + push :pr-<N>-<sha> image
runs-on: ubuntu-latest
steps:
- name: Soft-check GHCR_PUSH_TOKEN
id: prereq
env:
GHCR_PUSH_TOKEN: ${{ secrets.GHCR_PUSH_TOKEN }}
run: |
set -euo pipefail
if [ -z "${GHCR_PUSH_TOKEN:-}" ]; then
echo "::warning::GHCR_PUSH_TOKEN not set on api repo — skipping preview image build."
echo "::warning::infra preview-create will soft-fail with 'image not yet pushed' on rollout."
echo "skip=true" >> "$GITHUB_OUTPUT"
else
echo "skip=false" >> "$GITHUB_OUTPUT"
fi
- name: Checkout api (this repo) into ./api
if: steps.prereq.outputs.skip == 'false'
uses: actions/checkout@v6
with:
path: api
ref: ${{ github.event.pull_request.head.sha }}
- name: Checkout common sibling into ./common
if: steps.prereq.outputs.skip == 'false'
uses: actions/checkout@v6
with:
repository: ${{ vars.COMMON_REPO || format('{0}/common', github.repository_owner) }}
token: ${{ secrets.REPO_ACCESS_TOKEN || secrets.GITHUB_TOKEN }}
path: common
- name: Checkout proto sibling into ./proto
if: steps.prereq.outputs.skip == 'false'
uses: actions/checkout@v6
with:
repository: ${{ vars.PROTO_REPO || format('{0}/proto', github.repository_owner) }}
token: ${{ secrets.REPO_ACCESS_TOKEN || secrets.GITHUB_TOKEN }}
path: proto
- name: Compute build metadata
if: steps.prereq.outputs.skip == 'false'
id: meta
env:
PR_NUMBER: ${{ github.event.pull_request.number }}
PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }}
run: |
set -euo pipefail
# Defensive: github.event.pull_request.number is always numeric +
# github-controlled, but match deploy.yml's shape discipline.
case "${PR_NUMBER}" in
[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
*) echo "::error::unexpected PR_NUMBER: ${PR_NUMBER}"; exit 1 ;;
esac
case "${PR_HEAD_SHA}" in
[0-9a-f]*) ;;
*) echo "::error::unexpected SHA shape: ${PR_HEAD_SHA}"; exit 1 ;;
esac
SHORT_SHA="${PR_HEAD_SHA:0:7}"
BUILD_TIME="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
# Tag matches the pattern preview-create expects.
VERSION="pr-${PR_NUMBER}-${SHORT_SHA}"
echo "short_sha=${SHORT_SHA}" >> "$GITHUB_OUTPUT"
echo "build_time=${BUILD_TIME}" >> "$GITHUB_OUTPUT"
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
echo "Building ${VERSION} (${BUILD_TIME})"
- name: Set up Docker Buildx
if: steps.prereq.outputs.skip == 'false'
uses: docker/setup-buildx-action@v4
- name: Log in to GHCR
if: steps.prereq.outputs.skip == 'false'
# Same PAT posture as deploy.yml: GHCR_PUSH_TOKEN is a classic PAT
# with write:packages for the InstaNode-dev org. The per-job
# GITHUB_TOKEN, even with `packages: write`, is scoped to THIS
# repo and cannot push to the org-owned package — see deploy.yml
# for the full rationale.
uses: docker/login-action@v4
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GHCR_PUSH_TOKEN }}
- name: Build and push :pr-<N>-<sha> image
if: steps.prereq.outputs.skip == 'false'
run: |
set -euo pipefail
docker buildx build \
--platform linux/amd64 \
-f api/Dockerfile \
--build-arg GIT_SHA="${{ steps.meta.outputs.short_sha }}" \
--build-arg BUILD_TIME="${{ steps.meta.outputs.build_time }}" \
--build-arg VERSION="${{ steps.meta.outputs.version }}" \
-t "${IMAGE_REPO}:${{ steps.meta.outputs.version }}" \
--push \
.
echo "pushed ${IMAGE_REPO}:${{ steps.meta.outputs.version }}"