-
Notifications
You must be signed in to change notification settings - Fork 11
158 lines (135 loc) · 6.79 KB
/
Copy pathdeployRelease.yml
File metadata and controls
158 lines (135 loc) · 6.79 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
# Deploy Release — Publishes a numbered release to npm.
#
# Manually triggered from the master branch. Validates the version input, publishes to npm,
# tags the commit, and creates a GitHub release with auto-generated notes. For snapshot
# builds, see Deploy Snapshot.
name: Deploy Release
on:
workflow_dispatch:
inputs:
xhReleaseVersion:
description: 'Release Version'
required: true
type: string
isHotfix:
description: 'As hotfix. Check when releasing a hotfix to a version other than the latest.'
required: true
default: false
type: boolean
jobs:
build:
# Guards against accidental release from develop. Requires master for standard
# releases and a branch other than master (or develop) when isHotfix is set.
if: github.ref != 'refs/heads/develop' && ((github.ref == 'refs/heads/master') != inputs.isHotfix)
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
fetch-tags: true
- name: Validate release version
env:
VERSION: ${{ inputs.xhReleaseVersion }}
IS_HOTFIX: ${{ inputs.isHotfix }}
run: |
# Must be semver (X.Y.Z) with no leading zeros.
if [[ ! "$VERSION" =~ ^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$ ]]; then
echo "::error::Invalid version '$VERSION'. Must be semver with no leading zeros (e.g. 82.0.0)."
exit 1
fi
# Must not duplicate an existing release
if git tag -l "v$VERSION" | grep -q .; then
echo "::error::Tag v$VERSION already exists. This version has already been released."
exit 1
fi
# Strict version validation — the new version must be exactly one
# increment from the latest relevant tag and hotfix cannot be latest.
LATEST=$(git tag -l 'v*' | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | sed 's/^v//' | sort -t. -k1,1n -k2,2n -k3,3n | tail -1)
if [ -z "$LATEST" ]; then
echo "::error::No existing release tags found. Cannot validate version."
exit 1
fi
LATEST_MAJOR=$(echo "$LATEST" | cut -d. -f1)
LATEST_MINOR=$(echo "$LATEST" | cut -d. -f2)
LATEST_PATCH=$(echo "$LATEST" | cut -d. -f3)
# The three versions that would be valid as a standard (non-hotfix) release.
NEXT_MAJOR="$(( LATEST_MAJOR + 1 )).0.0"
NEXT_MINOR="${LATEST_MAJOR}.$(( LATEST_MINOR + 1 )).0"
NEXT_PATCH="${LATEST_MAJOR}.${LATEST_MINOR}.$(( LATEST_PATCH + 1 ))"
if [ "$IS_HOTFIX" = "true" ]; then
# A hotfix must NOT be a standard next-release version.
if [ "$VERSION" = "$NEXT_MAJOR" ] || [ "$VERSION" = "$NEXT_MINOR" ] || [ "$VERSION" = "$NEXT_PATCH" ]; then
echo "::error::Hotfix version $VERSION matches a standard release increment (latest is v$LATEST). Use a standard release instead."
exit 1
fi
NEW_MAJOR=$(echo "$VERSION" | cut -d. -f1)
NEW_MINOR=$(echo "$VERSION" | cut -d. -f2)
# Validate against the highest tags for this major version.
MAX_MINOR=$(git tag -l "v${NEW_MAJOR}.*" | grep -E "^v${NEW_MAJOR}\.[0-9]+\.[0-9]+$" | sed 's/^v//' | cut -d. -f2 | sort -n | tail -1)
if [ -z "$MAX_MINOR" ]; then
echo "::error::No existing tags found for major version ${NEW_MAJOR}. Cannot validate hotfix."
exit 1
fi
# Allowed: next minor bump for this major.
ALLOWED_MINOR="${NEW_MAJOR}.$(( MAX_MINOR + 1 )).0"
# Only offer a patch bump if tags exist for this specific MAJOR.MINOR.
MAX_PATCH=$(git tag -l "v${NEW_MAJOR}.${NEW_MINOR}.*" | grep -E "^v${NEW_MAJOR}\.${NEW_MINOR}\.[0-9]+$" | sed 's/^v//' | cut -d. -f3 | sort -n | tail -1)
if [ -n "$MAX_PATCH" ]; then
ALLOWED_PATCH="${NEW_MAJOR}.${NEW_MINOR}.$(( MAX_PATCH + 1 ))"
fi
if [ "$VERSION" != "$ALLOWED_MINOR" ] && [ "$VERSION" != "${ALLOWED_PATCH:-}" ]; then
ALLOWED="$ALLOWED_MINOR"
[ -n "${ALLOWED_PATCH:-}" ] && ALLOWED="$ALLOWED or $ALLOWED_PATCH"
echo "::error::Hotfix version $VERSION is not a valid next version. Allowed: $ALLOWED."
exit 1
fi
else
# Standard release: must be exactly one increment from the latest tag.
if [ "$VERSION" != "$NEXT_MAJOR" ] && [ "$VERSION" != "$NEXT_MINOR" ] && [ "$VERSION" != "$NEXT_PATCH" ]; then
echo "::error::Version $VERSION is not a valid next version (latest is v$LATEST). Allowed: $NEXT_MAJOR, $NEXT_MINOR, or $NEXT_PATCH."
exit 1
fi
fi
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version-file: '.nvmrc'
registry-url: 'https://registry.npmjs.org'
- name: Configure Font Awesome registry auth
env:
FONTAWESOME_PACKAGE_TOKEN: ${{ secrets.FONTAWESOME_PACKAGE_TOKEN }}
run: echo "//npm.fontawesome.com/:_authToken=$FONTAWESOME_PACKAGE_TOKEN" >> .npmrc
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Yarn lint
run: yarn lint:all
- name: Set release version in package.json
env:
VERSION: ${{ inputs.xhReleaseVersion }}
run: npm version --no-git-tag-version --new-version "$VERSION"
- name: Publish release to npm
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
run: npm publish
- name: Tag release
env:
VERSION: ${{ inputs.xhReleaseVersion }}
run: |
git tag "v$VERSION"
git push origin "v$VERSION"
- name: Create GitHub release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
VERSION: ${{ inputs.xhReleaseVersion }}
IS_HOTFIX: ${{ inputs.isHotfix }}
run: |
LATEST_FLAG="--latest"
if [ "$IS_HOTFIX" = "true" ]; then
LATEST_FLAG="--latest=false"
fi
gh release create "v$VERSION" \
--title "v$VERSION" \
--generate-notes \
"$LATEST_FLAG"