-
Notifications
You must be signed in to change notification settings - Fork 1
180 lines (163 loc) · 7.36 KB
/
Copy pathrelease.yml
File metadata and controls
180 lines (163 loc) · 7.36 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
name: release
# Conventional-commit release pipeline. On push to the default branch (or manual
# dispatch), semantic-release computes the next version from commits, then via the
# plugins in .releaserc.json: builds cross-platform binaries (goreleaser), publishes
# the npm launcher + per-platform packages, pushes the Homebrew cask, and creates the
# GitHub release with the binary archives attached.
on:
workflow_dispatch:
inputs:
dry-run:
description: "Run semantic-release in --dry-run mode (no publish)"
required: false
type: boolean
default: false
push:
branches: [main, master]
# Never cancel an in-flight release — interrupting between npm publish and the
# git tag / GitHub release leaves the registry inconsistent. Queue instead.
concurrency:
group: release-${{ github.ref }}
cancel-in-progress: false
permissions:
contents: read
env:
# GitHub forbids secrets.* in some if: expressions — surface presence flags once.
HAS_SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL != '' }}
HAS_DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL != '' }}
jobs:
release:
name: Publish
runs-on: ubuntu-latest
timeout-minutes: 20
permissions:
contents: write # semantic-release pushes tags + GitHub release
issues: write # release comments on released issues
pull-requests: write # release comments on released PRs
steps:
- name: Check release secrets
id: gate
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
run: |
if [ -z "$NPM_TOKEN" ]; then
echo "NPM_TOKEN is not set — skipping release. Add the secret to enable publishing."
echo "enabled=false" >> "$GITHUB_OUTPUT"
else
echo "enabled=true" >> "$GITHUB_OUTPUT"
fi
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
if: steps.gate.outputs.enabled == 'true'
with:
fetch-depth: 0
persist-credentials: false
- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6
if: steps.gate.outputs.enabled == 'true'
with:
go-version-file: go.mod
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
if: steps.gate.outputs.enabled == 'true'
with:
node-version: "22"
registry-url: "https://registry.npmjs.org"
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
if: steps.gate.outputs.enabled == 'true'
with:
bun-version: "1.3"
- name: Install goreleaser
if: steps.gate.outputs.enabled == 'true'
uses: goreleaser/goreleaser-action@5daf1e915a5f0af01ddbcd89a43b8061ff4f1a89 # v7
with:
version: "~> v2"
install-only: true
- name: Install dependencies
if: steps.gate.outputs.enabled == 'true'
run: bun install
- name: Verify
if: steps.gate.outputs.enabled == 'true'
run: |
test -z "$(gofmt -l .)" || { echo "gofmt needed:"; gofmt -l .; exit 1; }
go vet ./...
go test -race -count=1 ./...
- name: Semantic release
if: steps.gate.outputs.enabled == 'true'
run: |
if [ "$DRY_RUN" = "true" ]; then
bunx semantic-release --dry-run
else
bunx semantic-release
fi
env:
DRY_RUN: ${{ inputs.dry-run }}
# Prefer GH_PAT so the GitHub release semantic-release creates triggers
# downstream workflows (docker.yml). Releases made with the built-in
# GITHUB_TOKEN are suppressed by GitHub's recursion guard and won't fire
# the docker build. Falls back to GITHUB_TOKEN when no PAT is set.
GITHUB_TOKEN: ${{ secrets.GH_PAT || secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
HOMEBREW_TAP_GITHUB_TOKEN: ${{ secrets.GH_PAT }}
- name: Release summary
if: always() && steps.gate.outputs.enabled == 'true'
env:
REPO: ${{ github.repository }}
DRY: ${{ inputs.dry-run }}
run: |
# semantic-release stamps package.json to the released version during the
# run; 0.0.0 means nothing was released.
VER=$(node -p "require('./package.json').version" 2>/dev/null || echo "")
{
echo "## 📦 tunnel release"
echo
if [ "$DRY" = "true" ]; then
echo "🟡 **Dry run** — nothing was published."
elif [ -n "$VER" ] && [ "$VER" != "0.0.0" ]; then
echo "✅ **Published \`v$VER\`**"
echo
echo "| | |"
echo "|---|---|"
echo "| npm | \`npx @urlink/tunnel@$VER\` · [package](https://www.npmjs.com/package/@urlink/tunnel/v/$VER) |"
echo "| GitHub release | [v$VER](https://github.com/$REPO/releases/tag/v$VER) |"
echo "| Homebrew | \`brew install ur-link/tap/tunnel\` |"
echo "| Docker | \`ghcr.io/$REPO:$VER\` |"
echo
echo "Platforms: darwin/linux/windows × amd64/arm64."
else
echo "ℹ️ **No release** — no \`feat\`/\`fix\`/\`perf\` commits since the last tag."
fi
} >> "$GITHUB_STEP_SUMMARY"
- name: Notify Slack
# !cancelled() → notify on success and failure, but skip superseded (cancelled) builds.
if: ${{ !cancelled() && env.HAS_SLACK_WEBHOOK_URL == 'true' }}
# Official, Slack-maintained action (replaces the now-archived 8398a7/action-slack).
uses: slackapi/slack-github-action@45a88b9581bfab2566dc881e2cd66d334e621e2c # v3.0.3
with:
webhook: ${{ secrets.SLACK_WEBHOOK_URL }}
webhook-type: incoming-webhook
# Status-aware. Only trusted GitHub context fields are interpolated (injection-safe).
payload: |
text: "${{ job.status == 'success' && ':white_check_mark:' || ':x:' }} ${{ github.repository }} build ${{ job.status }} on ${{ github.ref_name }}"
blocks:
- type: "section"
text:
type: "mrkdwn"
text: "${{ job.status == 'success' && ':white_check_mark:' || ':x:' }} *${{ github.repository }}* build *${{ job.status }}* on `${{ github.ref_name }}`\n*Workflow:* ${{ github.workflow }} • *By:* ${{ github.actor }} • *Commit:* `${{ github.sha }}`"
- type: "actions"
elements:
- type: "button"
text:
type: "plain_text"
text: "View run"
url: "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
- name: Notify Discord
# !cancelled() → notify on success and failure; sarisia colors the embed by status.
if: ${{ !cancelled() && env.HAS_DISCORD_WEBHOOK_URL == 'true' }}
uses: sarisia/actions-status-discord@eb045afee445dc055c18d3d90bd0f244fd062708 # v1
with:
webhook: ${{ secrets.DISCORD_WEBHOOK_URL }}
status: ${{ job.status }}
title: ${{ github.repository }}
# Ping @here only when it needs attention (failure/cancelled); quiet on success.
content: "${{ job.status != 'success' && '@here' || '' }}"
username: GitHub Actions
nofail: true