-
Notifications
You must be signed in to change notification settings - Fork 0
161 lines (148 loc) · 6.01 KB
/
Copy pathpublish-main.yml
File metadata and controls
161 lines (148 loc) · 6.01 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
# On push to `main`: promote the latest per-image `X.Y.Z-staging.N` to immutable `X.Y.Z` and `:latest`
# (X.Y from root package.json on the push commit; no separate *-prod.N line like staging).
name: Publish (main)
on:
push:
branches:
- main
workflow_dispatch:
concurrency:
group: publish-main-${{ github.repository }}
cancel-in-progress: false
permissions:
contents: read
packages: read
jobs:
promote-and-release:
runs-on: ubuntu-latest
permissions:
contents: write
packages: write
steps:
- uses: actions/checkout@v7
- name: Install crane
run: |
set -euo pipefail
TAR="go-containerregistry_Linux_x86_64.tar.gz"
curl -fsSL "https://github.com/google/go-containerregistry/releases/download/v0.20.2/${TAR}" -o /tmp/c.tgz
tar -xzf /tmp/c.tgz -C /tmp crane
sudo install -m755 /tmp/crane /usr/local/bin/crane
- name: Read base version from package.json
id: version
run: |
BASE=$(node -p "require('./package.json').version" | sed 's/-.*//')
echo "base_version=$BASE" >> "$GITHUB_OUTPUT"
echo "Base version: $BASE"
- name: Promote images (same staging N for all; min of per-image max N)
id: promote
env:
REPO: ${{ github.repository }}
GITHUB_ACTOR: ${{ github.actor }}
run: |
set -euo pipefail
if [ -n "${{ secrets.GHCR_REGISTRY_TOKEN }}" ]; then
GHCR_TOKEN="${{ secrets.GHCR_REGISTRY_TOKEN }}"
else
GHCR_TOKEN="${{ secrets.GITHUB_TOKEN }}"
echo "Using GITHUB_TOKEN for GHCR (read/write)."
fi
echo "${{ secrets.GITHUB_TOKEN }}" | crane auth login ghcr.io -u "${GITHUB_ACTOR}" --password-stdin
BASE="${{ steps.version.outputs.base_version }}"
PREFIX="${BASE}-staging."
APPS="api management-api web web-sidecar management-web management-web-sidecar"
MINS=""
max_staging_n() {
local app="$1"
local tags_json
tags_json=$(curl -fsS -H "Authorization: Bearer ${GHCR_TOKEN}" "https://ghcr.io/v2/${REPO}/${app}/tags/list")
local best=-1
local t n
while IFS= read -r t; do
case "$t" in
${PREFIX}*) n="${t#${PREFIX}}"
if [[ "$n" =~ ^[0-9]+$ ]]; then
if [ "$n" -gt "$best" ]; then best="$n"; fi
fi
;;
esac
done < <(echo "$tags_json" | jq -r '.tags[]? // empty' | tr -d '\r')
echo "$best"
}
for APP in $APPS; do
m=$(max_staging_n "$APP")
if [ "$m" -lt 0 ]; then
echo "::error::No ${BASE}-staging.N tag for ${REPO}/${APP}"
exit 1
fi
MINS="${MINS} $m"
done
M=$(printf '%s\n' $MINS | sort -n | head -1)
echo "Using staging line ${BASE}-staging.$M (minimum of per-image max N so every image has this tag)."
for APP in $APPS; do
IMAGE="ghcr.io/${REPO}/${APP}"
SRC_TAG="${BASE}-staging.${M}"
echo "Promoting ${IMAGE}:${SRC_TAG} -> :${BASE} and :latest"
crane copy "${IMAGE}:${SRC_TAG}" "${IMAGE}:${BASE}"
crane copy "${IMAGE}:${SRC_TAG}" "${IMAGE}:latest"
done
echo "staging_n=$M" >> "$GITHUB_OUTPUT"
- name: Create Git tag and production release
if: success()
uses: actions/github-script@v9
with:
script: |
const base = "${{ steps.version.outputs.base_version }}";
const sha = context.sha;
const owner = context.repo.owner;
const repo = context.repo.repo;
const body =
"Production release " +
base +
". Add or edit release notes on GitHub if needed.";
try {
await github.rest.git.createRef({
owner, repo, ref: "refs/tags/" + base, sha
});
core.info("Created ref refs/tags/" + base);
} catch (e) {
if (e.status === 422) {
core.info("Ref refs/tags/" + base + " may already exist; continue.");
} else {
throw e;
}
}
const { data: list } = await github.rest.repos.listReleases({ owner, repo, per_page: 100 });
if (list.some((r) => r.tag_name === base)) {
core.info("Release for tag " + base + " already exists; skip.");
} else {
await github.rest.repos.createRelease({
owner, repo, tag_name: base, name: base, body, prerelease: false,
});
}
core.info("Branch-only promotion refs enabled: skipping moving refs/tags/latest.");
- name: Main promotion summary
if: success()
env:
BASE: ${{ steps.version.outputs.base_version }}
STAGING_N: ${{ steps.promote.outputs.staging_n }}
REPO: ${{ github.repository }}
run: |
{
echo "## Production images (promoted from staging line)"
echo ""
echo "Promoted from: \`$BASE-staging.$STAGING_N\` (per-image source in GHCR)."
echo ""
echo "Immutable tag: \`$BASE\` and floating \`latest\` (from latest \`$BASE-staging.N\` in GHCR per image)."
echo ""
echo "| Image | Pinned as |"
echo "|-------|-----------|"
for a in api management-api web web-sidecar management-web management-web-sidecar; do
echo "| \`ghcr.io/${REPO}/${a}\` | \`$BASE\`, \`latest\` |"
done
echo ""
echo "## All published image references"
for a in api management-api web web-sidecar management-web management-web-sidecar; do
echo "- \`ghcr.io/${REPO}/${a}:${BASE}\` (immutable)"
echo "- \`ghcr.io/${REPO}/${a}:latest\` (floating)"
done
} >> "$GITHUB_STEP_SUMMARY"