-
Notifications
You must be signed in to change notification settings - Fork 0
150 lines (138 loc) · 6.79 KB
/
Copy pathbuild.yml
File metadata and controls
150 lines (138 loc) · 6.79 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
name: Build and publish
# One multi-platform build on a single runner. Nothing is compiled — each
# platform's stage downloads the matching RustCFML release binary — so the
# arm64 half runs under QEMU only for `rustcfml --version` and the smoke test.
#
# tag vX.Y.Z[-N] -> :vX.Y.Z-N (if N), :vX.Y.Z, :X.Y, :latest
# push to main -> :edge
# pull request -> build only, no push
# manual -> any engine version, pushed as :edge (or :vX.Y.Z when it is a release)
on:
push:
branches: [main]
tags: ["v*"]
pull_request:
workflow_dispatch:
inputs:
rustcfml_version:
description: "RustCFML release tag to package (e.g. v0.653.3). Defaults to the Dockerfile's ARG."
required: false
permissions:
contents: read
packages: write
env:
IMAGE: ghcr.io/${{ github.repository_owner }}/rustcfml
jobs:
build:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v5
- name: Resolve the engine version
id: ver
run: |
DEFAULT=$(sed -nE 's/^ARG RUSTCFML_VERSION=(v[0-9.]+).*/\1/p' Dockerfile | head -1)
VERSION="${{ github.event.inputs.rustcfml_version }}"
VERSION="${VERSION:-$DEFAULT}"
if [ "${{ github.ref_type }}" = "tag" ]; then
# v0.653.3-2 -> engine v0.653.3, image build 2
BASE="${GITHUB_REF_NAME%-*}"
if [ "$BASE" != "$DEFAULT" ]; then
echo "::error::git tag ${GITHUB_REF_NAME} does not match ARG RUSTCFML_VERSION=${DEFAULT} in the Dockerfile"; exit 1
fi
VERSION="$BASE"
fi
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "image=$(echo '${{ env.IMAGE }}' | tr '[:upper:]' '[:lower:]')" >> "$GITHUB_OUTPUT"
echo "Packaging RustCFML $VERSION"
- name: Compute tags
id: tags
run: |
IMAGE='${{ steps.ver.outputs.image }}'
V='${{ steps.ver.outputs.version }}'
if [ "${{ github.ref_type }}" = "tag" ]; then
MINOR="${V#v}"; MINOR="${MINOR%.*}"
TAGS="$IMAGE:$V,$IMAGE:$MINOR,$IMAGE:latest"
[ "$GITHUB_REF_NAME" != "$V" ] && TAGS="$IMAGE:$GITHUB_REF_NAME,$TAGS"
else
TAGS="$IMAGE:edge"
fi
echo "tags=$TAGS" >> "$GITHUB_OUTPUT"
echo "$TAGS"
- uses: docker/setup-qemu-action@v3
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
if: github.event_name != 'pull_request'
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build (and push)
uses: docker/build-push-action@v6
with:
context: .
platforms: linux/amd64,linux/arm64
push: ${{ github.event_name != 'pull_request' }}
build-args: |
RUSTCFML_VERSION=${{ steps.ver.outputs.version }}
tags: ${{ steps.tags.outputs.tags }}
cache-from: type=gha
cache-to: type=gha,mode=max
labels: |
org.opencontainers.image.title=RustCFML
org.opencontainers.image.description=RustCFML ${{ steps.ver.outputs.version }} — a CFML engine written in Rust
org.opencontainers.image.version=${{ steps.ver.outputs.version }}
org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}
org.opencontainers.image.url=https://github.com/RustCFML/RustCFML
org.opencontainers.image.licenses=MIT
- name: Inspect the manifest
if: github.event_name != 'pull_request'
run: docker buildx imagetools inspect "${{ steps.ver.outputs.image }}:${{ github.ref_type == 'tag' && steps.ver.outputs.version || 'edge' }}"
# A published image nobody can pull is not published. GHCR creates a
# container package PRIVATE on first push regardless of how public the
# repository is, and nothing in the push reports that — the build goes
# green, the manifest inspects fine (the runner is authenticated), and the
# `FROM ghcr.io/…` line in our own README fails for every user and for any
# CI that tries to build on it. This step is the check that was missing:
# it asks the registry for an ANONYMOUS pull token and fetches the
# manifest with it, exactly as a stranger would.
- name: Can a stranger pull it?
if: github.event_name != 'pull_request'
run: |
set -uo pipefail
REPO=$(echo "${{ github.repository_owner }}/rustcfml" | tr '[:upper:]' '[:lower:]')
REF='${{ github.ref_type == 'tag' && steps.ver.outputs.version || 'edge' }}'
# A PRIVATE package refuses the anonymous token itself, so a missing
# token is the answer — do not let `set -e` and `curl -f` turn that
# into a bare curl error.
TOKEN=$(curl -sS "https://ghcr.io/token?scope=repository:${REPO}:pull&service=ghcr.io" \
| jq -r '.token // empty' 2>/dev/null || true)
if [ -n "$TOKEN" ]; then
CODE=$(curl -sS -o /dev/null -w '%{http_code}' \
-H "Authorization: Bearer ${TOKEN}" \
-H 'Accept: application/vnd.oci.image.index.v1+json,application/vnd.docker.distribution.manifest.list.v2+json' \
"https://ghcr.io/v2/${REPO}/manifests/${REF}")
else
CODE="401 — the registry would not even issue an anonymous pull token"
fi
if [ "$CODE" = "200" ]; then
echo "ghcr.io/${REPO}:${REF} is publicly pullable."
exit 0
fi
echo "::warning title=Image is not publicly pullable::Anonymous pull of ghcr.io/${REPO}:${REF} gave ${CODE}. The image is published but nobody can use it."
{
echo "### :warning: \`ghcr.io/${REPO}\` is not publicly pullable"
echo
echo "An anonymous pull gave **${CODE}**. The push succeeded, but every"
echo "\`docker pull\`, every \`FROM\` in a downstream Dockerfile and every CI"
echo "builder — including Fly.io's — gets \`unauthorized\`."
echo
echo "GHCR creates a container package **private on first publish**, whatever the"
echo "repository's visibility, and there is no REST API to change it. Fix it once,"
echo "by hand:"
echo
echo "1. <https://github.com/organizations/${{ github.repository_owner }}/settings/packages> → *Package creation* → tick **Public**."
echo " (Until this is on, the option in step 2 is greyed out and does not say why.)"
echo "2. <https://github.com/orgs/${{ github.repository_owner }}/packages/container/rustcfml/settings> → *Danger Zone* → **Change package visibility → Public**."
echo
echo "It stays public for every later push."
} >> "$GITHUB_STEP_SUMMARY"