Repository navigation
232 lines (207 loc) · 9.82 KB
/
Copy pathmirror-slim-image.yml
File metadata and controls
232 lines (207 loc) · 9.82 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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
name: Mirror Slim Image
# Mirrors slim service images published by supabase/slim-services from ghcr.io/supabase/cli to
# public.ecr.aws/supabase/cli. The sender polls the ECR Public destination and fails its release
# unless it resolves to the exact index digest published, so the copy must be digest-preserving
# via `regctl image copy` (byte-for-byte); do not switch to `docker buildx imagetools create`,
# which can rewrite the index and change its digest.
#
# The payload arrives with whatever authority holds the dispatch token, so it is treated as
# untrusted: names are pattern-checked, source/destination are derived in
# `.github/scripts/mirror-slim-image.ts` rather than trusted from the payload, and the source
# must resolve to the claimed digest before anything is copied.
#
# `upload-natives-s3` copies the same native triplets (fetched from GHCR by digest and
# re-verified) to the public-read S3 bucket in the cli-artifacts-prod account, for sandboxes that
# allow `*.amazonaws.com` but block registry blob CDNs. It runs in parallel with the ECR copy so an
# ECR Public outage or missing permission never holds back the S3 mirror, is best-effort like the
# native ECR copy, and uses the PutObject-only `slim-artifacts-publisher` role
# (infra/cli-artifacts/README.md).
#
# Replay locally: `bun .github/scripts/mirror-slim-image.ts --help`
# Full contract: docs/design/ecr-mirror-dispatch.md in supabase/slim-services.
on:
repository_dispatch:
types:
- mirror-slim-image
workflow_dispatch:
inputs:
service:
description: "Service name (e.g. postgrest)"
required: true
type: string
version:
description: "Image tag (e.g. v16.2)"
required: true
type: string
digest:
description: "Expected index digest (sha256:<64 hex chars>)"
required: true
type: string
permissions:
contents: read
concurrency:
group: mirror-slim-image-${{ github.event.client_payload.service || inputs.service }}-${{ github.event.client_payload.version || inputs.version }}
cancel-in-progress: false
jobs:
mirror:
runs-on: ubuntu-latest
# The sender's poll times out after 15 minutes; native copies run after the
# image copy and must still finish inside that window.
timeout-minutes: 13
permissions:
contents: read
packages: read
id-token: write
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version-file: .bun-version
- name: Validate payload
id: validate
env:
EVENT_NAME: ${{ github.event_name }}
SERVICE: ${{ github.event.client_payload.service || inputs.service }}
VERSION: ${{ github.event.client_payload.version || inputs.version }}
DIGEST: ${{ github.event.client_payload.digest || inputs.digest }}
PAYLOAD_SOURCE: ${{ github.event.client_payload.source }}
PAYLOAD_DESTINATION: ${{ github.event.client_payload.destination }}
run: bun .github/scripts/mirror-slim-image.ts validate
- name: Install regctl
# $RUNNER_TEMP is always writable by the job user.
run: |
set -euo pipefail
install -d "${RUNNER_TEMP}/regctl-bin"
curl -fsSLo "${RUNNER_TEMP}/regctl-bin/regctl" \
https://github.com/regclient/regclient/releases/download/v0.11.5/regctl-linux-amd64
echo "c93aa7638749f5aaac1a8e01787321889c78f0101809bb2880343478d0ba0467 ${RUNNER_TEMP}/regctl-bin/regctl" | sha256sum -c -
chmod +x "${RUNNER_TEMP}/regctl-bin/regctl"
echo "${RUNNER_TEMP}/regctl-bin" >> "$GITHUB_PATH"
"${RUNNER_TEMP}/regctl-bin/regctl" version
- name: Log in to ghcr.io
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Verify source digest
env:
REFERENCE: ${{ steps.validate.outputs.source }}
DIGEST: ${{ steps.validate.outputs.digest }}
run: bun .github/scripts/mirror-slim-image.ts verify-digest
- name: Configure aws credentials
uses: aws-actions/configure-aws-credentials@cbe3b392738ccf3f987d68400dafcf4b0624a56c # v6.2.4
with:
role-to-assume: ${{ secrets.PROD_AWS_ROLE }}
aws-region: us-east-1
- name: Log in to ECR Public
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
registry: public.ecr.aws
- name: Ensure ECR Public repository exists
env:
SERVICE: ${{ steps.validate.outputs.service }}
run: bun .github/scripts/mirror-slim-image.ts ensure-repo
- name: Mirror image
env:
SOURCE: ${{ steps.validate.outputs.source }}
DESTINATION: ${{ steps.validate.outputs.destination }}
DIGEST: ${{ steps.validate.outputs.digest }}
# Copies by digest (not tag) so it can't race a tag move on the source, and runs
# unconditionally with no early exit: regctl's copy is incremental, so re-dispatching
# after a complete copy is a cheap no-op, and after a partial failure it finishes the
# copy instead of skipping it.
run: bun .github/scripts/mirror-slim-image.ts copy-image
- name: Verify destination digest
env:
REFERENCE: ${{ steps.validate.outputs.destination }}
DIGEST: ${{ steps.validate.outputs.digest }}
# ECR Public can serve the tag's previous digest (or a 404) for ~30 s after the push;
# 13 reads 10 s apart allow ~2 min.
ATTEMPTS: "13"
run: bun .github/scripts/mirror-slim-image.ts verify-digest
- name: Mirror native artifacts
continue-on-error: true
env:
SERVICE: ${{ steps.validate.outputs.service }}
VERSION: ${{ steps.validate.outputs.version }}
EVENT_NAME: ${{ github.event_name }}
# Native tags are copied without --referrers. Failure must not fail the
# image digest the sender polls; daily audit reports native drift.
run: bun .github/scripts/mirror-slim-image.ts copy-natives
upload-natives-s3:
# Natives only ride in repository_dispatch payloads. Nothing reaches the public bucket from a
# dispatch whose source image digest check fails. The job is skipped until the
# cli-artifacts-prod account exists and its ID is set as a repository variable.
if: ${{ github.event_name == 'repository_dispatch' && vars.CLI_ARTIFACTS_AWS_ACCOUNT_ID != '' }}
runs-on: ubuntu-latest
timeout-minutes: 15
continue-on-error: true
permissions:
contents: read
packages: read
id-token: write
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version-file: .bun-version
- name: Validate payload
id: validate
env:
EVENT_NAME: ${{ github.event_name }}
SERVICE: ${{ github.event.client_payload.service }}
VERSION: ${{ github.event.client_payload.version }}
DIGEST: ${{ github.event.client_payload.digest }}
PAYLOAD_SOURCE: ${{ github.event.client_payload.source }}
PAYLOAD_DESTINATION: ${{ github.event.client_payload.destination }}
run: bun .github/scripts/mirror-slim-image.ts validate
- name: Install regctl
run: |
set -euo pipefail
install -d "${RUNNER_TEMP}/regctl-bin"
curl -fsSLo "${RUNNER_TEMP}/regctl-bin/regctl" \
https://github.com/regclient/regclient/releases/download/v0.11.5/regctl-linux-amd64
echo "c93aa7638749f5aaac1a8e01787321889c78f0101809bb2880343478d0ba0467 ${RUNNER_TEMP}/regctl-bin/regctl" | sha256sum -c -
chmod +x "${RUNNER_TEMP}/regctl-bin/regctl"
echo "${RUNNER_TEMP}/regctl-bin" >> "$GITHUB_PATH"
"${RUNNER_TEMP}/regctl-bin/regctl" version
- name: Log in to ghcr.io
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Verify source digest
env:
REFERENCE: ${{ steps.validate.outputs.source }}
DIGEST: ${{ steps.validate.outputs.digest }}
run: bun .github/scripts/mirror-slim-image.ts verify-digest
- name: Fetch and verify native artifacts
id: fetch
env:
SERVICE: ${{ steps.validate.outputs.service }}
VERSION: ${{ steps.validate.outputs.version }}
EVENT_NAME: ${{ github.event_name }}
OUTPUT_DIR: ${{ runner.temp }}/natives
run: bun .github/scripts/mirror-slim-image.ts fetch-natives
- name: Configure aws credentials
if: steps.fetch.outputs.count != '0'
uses: aws-actions/configure-aws-credentials@cbe3b392738ccf3f987d68400dafcf4b0624a56c # v6.2.4
with:
role-to-assume: arn:aws:iam::${{ vars.CLI_ARTIFACTS_AWS_ACCOUNT_ID }}:role/slim-artifacts-publisher
# Ties every AssumeRole and PutObject entry in CloudTrail back to one workflow run.
role-session-name: mirror-slim-image-${{ github.run_id }}
aws-region: us-east-1
- name: Upload native artifacts to S3
if: steps.fetch.outputs.count != '0'
env:
SERVICE: ${{ steps.validate.outputs.service }}
VERSION: ${{ steps.validate.outputs.version }}
INPUT_DIR: ${{ runner.temp }}/natives
TARGETS: ${{ steps.fetch.outputs.targets }}
run: bun .github/scripts/mirror-slim-image.ts upload-natives-s3