-
-
Notifications
You must be signed in to change notification settings - Fork 0
157 lines (138 loc) · 6.09 KB
/
Copy pathprerelease-develop.yml
File metadata and controls
157 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
154
155
156
157
name: Pre-release from develop
on:
push:
branches:
- develop
workflow_dispatch:
# @max-health-inc/config is installed from GitHub Packages (see .npmrc), which needs a token
# even though the package is public. Set at workflow level so every `npm ci` below is covered.
# An unset secret expands to an EMPTY string and fails with a 401 identical to a bad token.
# Nothing in this workflow publishes, so a workflow-wide NODE_AUTH_TOKEN is safe here.
env:
NODE_AUTH_TOKEN: ${{ secrets.GH_PACKAGES_TOKEN }}
jobs:
prerelease:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout code
uses: actions/checkout@v7
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Node.js
uses: actions/setup-node@v7
with:
node-version: '22'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Determine pre-release version
id: version
run: |
# Get the version from package.json (strip any existing pre-release suffix)
PKG_VERSION=$(node -p "require('./package.json').version.replace(/-.*/, '')")
# Get the latest stable release tag and increment its patch
LATEST_TAG=$(gh release list --exclude-drafts --exclude-pre-releases --limit 1 --json tagName --jq '.[0].tagName' 2>/dev/null || echo "")
if [ -n "$LATEST_TAG" ]; then
TAG_BASE="${LATEST_TAG#v}"
MAJOR=$(echo "$TAG_BASE" | cut -d. -f1)
MINOR=$(echo "$TAG_BASE" | cut -d. -f2)
PATCH=$(echo "$TAG_BASE" | cut -d. -f3)
TAG_NEXT="${MAJOR}.${MINOR}.$((PATCH + 1))"
else
TAG_NEXT="0.0.0"
fi
# Use whichever is higher: package.json version or tag+1
# This respects manual version bumps (e.g., 1.2.0) over auto-incremented patch (1.1.5)
BASE_VERSION=$(node -e "
const a = '${PKG_VERSION}'.split('.').map(Number);
const b = '${TAG_NEXT}'.split('.').map(Number);
const cmp = a[0]-b[0] || a[1]-b[1] || a[2]-b[2];
console.log(cmp >= 0 ? '${PKG_VERSION}' : '${TAG_NEXT}');
")
SHORT_SHA=$(git rev-parse --short HEAD)
TIMESTAMP=$(date -u +%Y%m%d%H%M%S)
PRE_VERSION="${BASE_VERSION}-dev.${TIMESTAMP}.${SHORT_SHA}"
echo "version=$PRE_VERSION" >> $GITHUB_OUTPUT
echo "Pre-release version: $PRE_VERSION (pkg=${PKG_VERSION}, tag+1=${TAG_NEXT})"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Write version to package.json
run: |
VERSION="${{ steps.version.outputs.version }}"
npm version "$VERSION" --no-git-tag-version
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
git add package.json package-lock.json
git commit -m "chore: bump version to $VERSION [skip ci]"
git push origin develop
- name: Merge main into develop (prevent PR conflicts)
run: |
git fetch origin main
# Merge main into develop; on version-line conflicts keep develop's version
if git merge origin/main -m "chore: merge main into develop [skip ci]" -X ours --no-edit; then
echo "Merged main into develop cleanly"
else
echo "Merge conflict on non-version files — aborting (manual resolution needed)"
git merge --abort
fi
# Push only if there are new commits from the merge
if [ "$(git rev-parse HEAD)" != "$(git rev-parse origin/develop)" ]; then
git push origin develop
fi
- name: Run unit tests
run: npm test
- name: Build project
run: npm run build
- name: Generate changelog from commit messages
id: changelog
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_REPOSITORY: ${{ github.repository }}
VERSION: ${{ steps.version.outputs.version }}
run: |
# Use the last stable release tag (not pre-release) for the commit range
LAST_TAG=$(gh release list --exclude-drafts --exclude-pre-releases --limit 1 --json tagName --jq '.[0].tagName' 2>/dev/null || echo "")
export LAST_TAG
node scripts/generate-changelog.mjs || true
if [ ! -f CHANGELOG.txt ]; then
echo "## Pre-release ${{ steps.version.outputs.version }}" > CHANGELOG.txt
echo "" >> CHANGELOG.txt
git log --oneline --no-merges "${LAST_TAG}..HEAD" 2>/dev/null >> CHANGELOG.txt || \
git log --oneline --no-merges -10 >> CHANGELOG.txt
fi
- name: Create Git tag
run: |
VERSION="${{ steps.version.outputs.version }}"
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
git tag -a "v$VERSION" -m "Pre-release v$VERSION"
git push origin "v$VERSION"
- name: Create GitHub Pre-release
uses: softprops/action-gh-release@v3.0.2
with:
tag_name: v${{ steps.version.outputs.version }}
name: Pre-release v${{ steps.version.outputs.version }}
body_path: CHANGELOG.txt
draft: false
prerelease: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Cleanup old pre-release tags (keep latest 3)
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
echo "Fetching pre-release tags..."
PRE_TAGS=$(git tag -l 'v*-dev.*' --sort=-version:refname)
COUNT=0
for TAG in $PRE_TAGS; do
COUNT=$((COUNT + 1))
if [ $COUNT -gt 3 ]; then
echo "Deleting old pre-release: $TAG"
gh release delete "$TAG" --yes --cleanup-tag 2>/dev/null || true
git push origin --delete "$TAG" 2>/dev/null || true
fi
done
echo "Kept latest 3 pre-releases, deleted $((COUNT > 3 ? COUNT - 3 : 0)) old ones"