-
-
Notifications
You must be signed in to change notification settings - Fork 0
140 lines (120 loc) · 5.16 KB
/
pipeline.yml
File metadata and controls
140 lines (120 loc) · 5.16 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
name: CI/CD Pipeline
on:
pull_request:
branches: [main]
pull_request_target:
branches: [main]
types: [opened, synchronize, reopened]
push:
branches: [main]
merge_group:
branches: [main]
permissions:
contents: read
jobs:
# This job acts as a prerequisite for the pipeline. It runs on EVERY PR, push, and merge queue (merge_group) run.
# Currently performs repository checkout to prepare for subsequent jobs.
# For formal releases with versioning and signed artifacts, see .github/workflows/release.yml
guard:
name: Build Guard
runs-on: ubuntu-latest
# Security: Only run on version bump PRs from the trusted bot
if: |
github.event_name != 'pull_request_target' ||
(startsWith(github.event.pull_request.head.ref, 'version-bump-') && github.event.pull_request.user.login == 'ghostclass-release-automation[bot]')
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
# SECURITY: This workflow uses pull_request_target but is SAFE because:
# 1. Job-level 'if' condition restricts pull_request_target to ONLY trusted bot PRs
# 2. For pull_request events: checks out PR head to run tests on proposed changes
# 3. For pull_request_target events: checks out base branch (trusted code only)
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
# Auto-tag releases on main branch
# This simplified job creates signed tags from version bumps made in PRs
# The version bump now happens at PR creation time via auto-version-bump.yml
auto-tag:
name: Auto Tag Release
needs: guard
if: |
github.event_name == 'push' &&
github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
- name: Import GPG key
uses: crazy-max/ghaction-import-gpg@01dd5d3ca463c7f10f7f4f7b4f177225ac661ee4 # v6.1.0
with:
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
passphrase: ${{ secrets.GPG_PASSPHRASE }}
git_tag_gpgsign: true
git_user_signingkey: true
- name: Setup Node.js
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
with:
node-version: '20'
- name: Create and push signed tag
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail
VERSION=$(node -p "require('./package.json').version")
VERSION_TAG="v${VERSION}"
echo "Current version: ${VERSION}"
echo "Tag to create: ${VERSION_TAG}"
# Check if tag already exists
if git ls-remote --tags origin | grep -q "refs/tags/${VERSION_TAG}$"; then
echo "Tag ${VERSION_TAG} already exists, skipping"
exit 0
fi
echo "Creating signed tag ${VERSION_TAG}"
# Configure git identity for tagging (GPG action sets signing config)
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
# Create signed annotated tag
git tag -a "${VERSION_TAG}" -m "Release ${VERSION_TAG}"
# Push tag (handle possible concurrent creation)
set +e
git push origin "${VERSION_TAG}"
push_status=$?
set -e
if [ $push_status -ne 0 ]; then
echo "git push for tag ${VERSION_TAG} failed with status ${push_status}, checking if tag exists on remote..."
if git ls-remote --tags origin | grep -q "refs/tags/${VERSION_TAG}$"; then
echo "Tag ${VERSION_TAG} already exists on remote (likely created concurrently); continuing."
else
echo "✗ Failed to push tag ${VERSION_TAG} and tag not found on remote."
exit $push_status
fi
fi
echo "✓ Tag ${VERSION_TAG} created and pushed"
# Trigger release workflow via repository_dispatch
echo "Triggering release workflow via repository_dispatch"
# Add retry logic for transient failures
max_attempts=3
attempt=1
while [ $attempt -le $max_attempts ]; do
if gh api repos/${{ github.repository }}/dispatches \
--method POST \
-H "Accept: application/vnd.github+json" \
-f event_type="release_requested" \
-f client_payload[version_tag]="${VERSION_TAG}" \
-f client_payload[triggered_by]="auto-tag" \
-f client_payload[run_id]="${{ github.run_id }}"; then
echo "✓ Release workflow triggered for ${VERSION_TAG}"
break
fi
if [ $attempt -eq $max_attempts ]; then
echo "✗ Failed to trigger release workflow after ${max_attempts} attempts"
exit 1
fi
echo "Retry attempt ${attempt}/${max_attempts} in 5s..."
sleep 5
attempt=$((attempt + 1))
done