-
Notifications
You must be signed in to change notification settings - Fork 3
153 lines (138 loc) · 6.09 KB
/
publish-docker.yml
File metadata and controls
153 lines (138 loc) · 6.09 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
name: publish-docker
# Builds, tests, and publishes the socket-basics image to GHCR and Docker Hub.
#
# Flow: resolve-version → build-test-push → create-release
#
# Tag convention:
# v2.0.0 — immutable exact release (floating major tags intentionally not published)
# See docs/github-action.md → "Pinning strategies" for the full rationale.
#
# Required repository secrets:
# DOCKERHUB_USERNAME — Docker Hub account name
# DOCKERHUB_TOKEN — Docker Hub access token (read/write)
on:
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+'
workflow_dispatch:
inputs:
tag:
description: "Full git tag to publish (e.g. v2.0.0 for new releases, 1.1.3 for old). Must exist in the repo."
required: true
# Default: deny everything. Each job below grants only what it needs.
permissions:
contents: read
concurrency:
group: publish-docker-${{ github.ref }}
cancel-in-progress: false # never cancel an in-flight publish
jobs:
# ── Job 1: Resolve version ─────────────────────────────────────────────────
# Computes a clean semver string (no v prefix) consumed by downstream jobs.
resolve-version:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.clean }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref }}
- name: 🏷️ Resolve version
id: version
env:
EVENT_NAME: ${{ github.event_name }}
INPUT_TAG: ${{ inputs.tag }}
REF_NAME: ${{ github.ref_name }}
run: |
if [ "$EVENT_NAME" = "workflow_dispatch" ]; then
CLEAN="$INPUT_TAG" # full tag as provided (e.g. 1.1.3 or v2.0.0)
else
CLEAN="$REF_NAME" # e.g. v2.0.0
fi
CLEAN="${CLEAN#v}" # strip leading v if present → 2.0.0 or 1.1.3
echo "clean=$CLEAN" >> "$GITHUB_OUTPUT"
# ── Job 2: Build → test → push ─────────────────────────────────────────────
# Delegates all Docker steps to the reusable _docker-pipeline workflow.
build-test-push:
name: publish (socket-basics)
needs: resolve-version
permissions:
contents: read
packages: write # push images to GHCR
uses: ./.github/workflows/_docker-pipeline.yml
with:
name: socket-basics
dockerfile: Dockerfile
context: .
check_set: main
push: true
tag_push: ${{ github.ref_type == 'tag' }}
version: ${{ needs.resolve-version.outputs.version }}
secrets:
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
# ── Job 3: Create GitHub release + update CHANGELOG ────────────────────────
# Runs once after the image is successfully pushed (not for workflow_dispatch
# re-publishes — those don't create new releases).
# Generates categorised release notes from merged PR labels (.github/release.yml),
# creates the GitHub Release, then commits the CHANGELOG update back to main.
create-release:
needs: [resolve-version, build-test-push]
if: github.ref_type == 'tag'
permissions:
contents: write # create GitHub release + commit CHANGELOG back to main
runs-on: ubuntu-latest
env:
VERSION: ${{ needs.resolve-version.outputs.version }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: main
fetch-depth: 0
- name: 🤖 Generate socket-release-bot token
id: bot
uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf # v2.2.1
with:
app-id: ${{ secrets.GH_BOT_APP_ID }}
private-key: ${{ secrets.GH_BOT_APP_PEM_FILE }}
owner: SocketDev
repositories: socket-basics
- name: 📝 Create GitHub release with auto-generated notes
env:
GH_TOKEN: ${{ steps.bot.outputs.token }}
REF_NAME: ${{ github.ref_name }}
run: |
gh release create "$REF_NAME" \
--title "$REF_NAME" \
--generate-notes \
--verify-tag \
|| echo "Release already exists (re-run scenario) — skipping creation"
- name: 📋 Update CHANGELOG.md
env:
GH_TOKEN: ${{ steps.bot.outputs.token }}
REF_NAME: ${{ github.ref_name }}
run: |
NOTES=$(gh release view "$REF_NAME" --json body --jq .body)
DATE=$(date +%Y-%m-%d)
echo "$NOTES" | python scripts/update_changelog.py \
--version "$VERSION" \
--date "$DATE"
- name: 🔀 Commit CHANGELOG + action.yml back to main
env:
BOT_TOKEN: ${{ steps.bot.outputs.token }}
REF_NAME: ${{ github.ref_name }}
run: |
git config user.name "socket-release-bot[bot]"
git config user.email "socket-release-bot[bot]@users.noreply.github.com"
git remote set-url origin "https://x-access-token:${BOT_TOKEN}@github.com/SocketDev/socket-basics.git"
# Auto-update action.yml image ref to the new version.
# No-op if action.yml still uses `image: "Dockerfile"` (handles the
# chicken-and-egg on the initial v2.0.0 release).
if grep -q 'docker://ghcr.io/socketdev/socket-basics:' action.yml; then
sed -i "s|docker://ghcr.io/socketdev/socket-basics:[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*|docker://ghcr.io/socketdev/socket-basics:${VERSION}|" action.yml
echo "Updated action.yml image ref to ${VERSION}"
else
echo "action.yml not yet using pre-built image — skipping version update"
fi
git add CHANGELOG.md action.yml
git diff --cached --quiet || git commit -m "chore: release ${REF_NAME} — update CHANGELOG and action.yml [skip ci]"
git push origin HEAD:main