-
Notifications
You must be signed in to change notification settings - Fork 1.2k
238 lines (198 loc) · 8.82 KB
/
chrome-extension-ci.yml
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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
name: chrome-extension CI
on:
push:
branches: [main]
paths:
- "extensions/chrome/**"
pull_request:
branches: [main]
paths:
- "extensions/chrome/**"
defaults:
run:
working-directory: ./extensions/chrome
jobs:
lint-and-format:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Bun
uses: oven-sh/setup-bun@v1
with:
bun-version: latest
- name: Install dependencies
run: bun install
- name: Run ESLint and format fix
run: bun run fix
- name: Run markdown lint
# DON't TOUCH THIS LINE BELOW #
run: bunx markdownlint-cli2 "./**/*.md" --config .markdownlint-cli2.jsonc
test-and-build:
needs: lint-and-format
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- name: Setup Bun
uses: oven-sh/setup-bun@v1
with:
bun-version: latest
- name: Install dependencies
run: bun install
- name: Run tests
run: bun test
- name: Build extension
run: bun run build
# Automatically increments the patch version (e.g., 1.0.0 -> 1.0.1)
# and creates a release
# Only increment patch version for non-major versions
- name: Check existing tag
id: check_tag
shell: bash
run: |
set -euo pipefail # Exit on error, undefined vars, and pipe failures
# Function to validate semver format
# Supports standard versions (x.y.z) and pre-release versions (x.y.z-beta.n)
validate_version() {
local version="$1"
if ! [[ "$version" =~ ^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(-((0|[1-9][0-9]*|[0-9]*[a-zA-Z-][0-9a-zA-Z-]*)(\.(0|[1-9][0-9]*|[0-9]*[a-zA-Z-][0-9a-zA-Z-]*))*))?(\+([0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*))?$ ]]; then
echo "Error: Invalid version format: $version"
echo "Version must be in format: x.y.z or x.y.z-pre.n"
exit 1
fi
}
# Function to update version in JSON files
update_json_version() {
local file="$1"
local cur_ver="$2"
local new_ver="$3"
if [[ ! -f "$file" ]]; then
echo "Error: File $file not found"
exit 1
fi
# Check if version field exists
if ! grep -q "\"version\":" "$file"; then
echo "Error: No version field found in $file"
exit 1
fi
# Backup file before modification
cp "$file" "${file}.bak"
if ! sed -i "s/\"version\": \"$cur_ver\"/\"version\": \"$new_ver\"/" "$file"; then
echo "Error: Failed to update version in $file"
mv "${file}.bak" "$file" # Restore backup
exit 1
fi
rm "${file}.bak" # Remove backup if successful
}
# Function to compare versions
version_gt() {
test "$(echo "$@" | tr " " "\n" | sort -V | head -n 1)" != "$1"
}
# Get current version with error handling
if [[ ! -f "package.json" ]]; then
echo "Error: package.json not found"
exit 1
fi
if ! current_version=$(node -p "try { require('./package.json').version } catch(e) { console.error(e); process.exit(1) }" 2>/dev/null); then
echo "Error: Failed to read version from package.json"
exit 1
fi
# Validate version format
validate_version "$current_version"
# Get highest existing version with error handling
if ! highest_version=$(git ls-remote --tags origin | grep "refs/tags/chrome-extension-v" | sed 's/.*chrome-extension-v//' | sort -V | tail -n 1); then
echo "Warning: Failed to fetch remote tags, proceeding with caution"
fi
# Prevent version downgrade
# Note: To downgrade versions, you need to manually:
# 1. Delete the higher version tag: git push origin :refs/tags/chrome-extension-v<version>
# 2. Delete the corresponding GitHub release
if [ ! -z "$highest_version" ] && version_gt "$highest_version" "$current_version"; then
echo "Error: Version downgrade not allowed. Current: $current_version, Highest: $highest_version"
exit 1
fi
# Handle pre-release versions
if [[ "$current_version" == *"-"* ]]; then
echo "Pre-release version detected: $current_version"
# Extract base version and pre-release parts
base_version=${current_version%%-*}
pre_release=${current_version#*-}
pre_type=${pre_release%%.*}
pre_num=${pre_release#*.}
# Check if same pre-release version exists
if git ls-remote --tags origin | grep -q "refs/tags/chrome-extension-v$current_version"; then
# Increment pre-release number
new_pre_num=$((pre_num + 1))
new_version="${base_version}-${pre_type}.${new_pre_num}"
echo "Incrementing pre-release: $current_version -> $new_version"
echo "version=$new_version" >> $GITHUB_OUTPUT
echo "version_changed=true" >> $GITHUB_OUTPUT
else
echo "Using current pre-release version: $current_version"
echo "version=$current_version" >> $GITHUB_OUTPUT
echo "version_changed=false" >> $GITHUB_OUTPUT
fi
exit 0
fi
# Handle major versions (x.0.0)
if [[ "$current_version" =~ ^[0-9]+\.0\.0$ ]]; then
echo "Major version detected: $current_version"
# Check if major version tag exists
if git ls-remote --tags origin | grep -q "refs/tags/chrome-extension-v$current_version"; then
# Increment patch version like normal
new_version="${current_version%.*}.1" # x.0.0 -> x.0.1
echo "Major version exists, incrementing patch: $current_version -> $new_version"
echo "version=$new_version" >> $GITHUB_OUTPUT
echo "version_changed=true" >> $GITHUB_OUTPUT
else
echo "Using new major version: $current_version"
echo "version=$current_version" >> $GITHUB_OUTPUT
echo "version_changed=false" >> $GITHUB_OUTPUT
fi
exit 0
fi
# Check if tag exists
if git ls-remote --tags origin | grep -q "refs/tags/chrome-extension-v$current_version"; then
echo "Tag exists, incrementing patch version"
# Split version into components
IFS='.' read -r major minor patch <<< "$current_version"
new_version="$major.$minor.$((patch + 1))"
validate_version "$new_version"
echo "Updating version from $current_version to $new_version"
# Update version in files
update_json_version "package.json" "$current_version" "$new_version"
update_json_version "public/manifest.json" "$current_version" "$new_version"
# Configure git for fork workflow
git config --global user.email "github-actions[bot]@users.noreply.github.com"
git config --global user.name "github-actions[bot]"
# Commit and push changes
git add package.json public/manifest.json
git commit -m "chore: bump version to $new_version [skip ci]"
if ! git push; then
echo "Error: Failed to push changes"
exit 1
fi
echo "version=$new_version" >> $GITHUB_OUTPUT
echo "version_changed=true" >> $GITHUB_OUTPUT
else
echo "Using current version: $current_version"
echo "version=$current_version" >> $GITHUB_OUTPUT
echo "version_changed=false" >> $GITHUB_OUTPUT
fi
- name: Zip Extension
run: zip -r thinking-claude-chrome-extension-v${{ steps.check_tag.outputs.version }}.zip dist/
- name: Create Release
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
uses: softprops/action-gh-release@v1
with:
name: Chrome Extension v${{ steps.check_tag.outputs.version }}
tag_name: chrome-extension-v${{ steps.check_tag.outputs.version }}
files: extensions/chrome/thinking-claude-chrome-extension-v${{ steps.check_tag.outputs.version }}.zip
generate_release_notes: true
token: ${{ secrets.GITHUB_TOKEN }}
fail_on_unmatched_files: true