Skip to content

Commit fb6b426

Browse files
committed
Add tag-triggered release workflow via GitHub Actions
1 parent 2f4d5ae commit fb6b426

6 files changed

Lines changed: 167 additions & 82 deletions

File tree

File renamed without changes.

.github/workflows/release.yml

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*'
7+
8+
jobs:
9+
release:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- uses: actions/checkout@v4
13+
14+
- uses: actions/setup-node@v4
15+
with:
16+
node-version-file: '.nvmrc'
17+
18+
- name: Get version from tag
19+
id: version
20+
run: |
21+
# Strip 'v' prefix from tag
22+
version="${GITHUB_REF_NAME#v}"
23+
echo "version=$version" >> $GITHUB_OUTPUT
24+
25+
- name: Verify package.json version matches tag
26+
run: |
27+
package_version=$(node -p "require('./package.json').version")
28+
tag_version="${{ steps.version.outputs.version }}"
29+
if [ "$package_version" != "$tag_version" ]; then
30+
echo "::warning::package.json version ($package_version) does not match tag ($tag_version)"
31+
fi
32+
33+
- name: Install dependencies
34+
run: npm ci
35+
36+
- name: Build
37+
run: npm run build
38+
39+
- name: Pack tarballs
40+
run: npx oclif pack tarballs --no-xz
41+
42+
- name: Upload tarballs to S3
43+
run: npx oclif upload tarballs --no-xz
44+
env:
45+
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
46+
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
47+
48+
- name: Promote release
49+
run: |
50+
version="${{ steps.version.outputs.version }}"
51+
hash=$(ls dist | grep "disco-v${version}-" | head -1 | cut -d'-' -f3)
52+
npx oclif promote --sha "$hash" --version "$version" --no-xz
53+
env:
54+
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
55+
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
56+
57+
- name: Invalidate CloudFront cache
58+
run: |
59+
aws cloudfront create-invalidation \
60+
--distribution-id ${{ secrets.AWS_CLOUDFRONT_DISTRIBUTION_ID }} \
61+
--paths "/*"
62+
env:
63+
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
64+
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
65+
66+
- name: Create GitHub Release
67+
uses: ncipollo/release-action@v1
68+
with:
69+
name: v${{ steps.version.outputs.version }}
70+
tag: ${{ github.ref_name }}
71+
token: ${{ secrets.GITHUB_TOKEN }}
72+
generateReleaseNotes: true

RELEASE.md

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,40 @@
1-
### how to release
1+
### How to release
22

3+
**Option 1: Auto-bump patch**
34
```bash
4-
# use node 22!!
5-
nvm use
6-
export $(cat .env | xargs) && ./release.sh
5+
./release.sh
76
```
7+
This will bump the patch version (e.g., v1.2.3 -> v1.2.4) and push the tag.
88

9-
### how to regenerate readme i.e. cli reference
9+
**Option 2: Specify version type**
10+
```bash
11+
./release.sh patch # v1.2.3 -> v1.2.4
12+
./release.sh minor # v1.2.3 -> v1.3.0
13+
./release.sh major # v1.2.3 -> v2.0.0
14+
```
15+
16+
**Option 3: Specify exact version**
17+
```bash
18+
./release.sh v1.5.0
19+
```
20+
21+
**Option 4: Manual tag (for colleagues who prefer)**
22+
```bash
23+
git tag v1.5.0
24+
git push origin v1.5.0
25+
```
26+
27+
All options trigger the same GitHub Action which builds, uploads to S3, and invalidates CloudFront.
28+
29+
Watch progress at: https://github.com/letsdiscodev/cli/actions
30+
31+
### Required GitHub Secrets
32+
33+
- `AWS_ACCESS_KEY_ID`
34+
- `AWS_SECRET_ACCESS_KEY`
35+
- `AWS_CLOUDFRONT_DISTRIBUTION_ID`
36+
37+
### How to regenerate readme (CLI reference)
1038

1139
```bash
1240
# gotta build first!

list

Lines changed: 0 additions & 8 deletions
This file was deleted.

release.sh

Lines changed: 62 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,86 +1,79 @@
11
#!/bin/bash
22

3-
# see RELEASE.md !!
4-
# ---
3+
# Creates and pushes a version tag to trigger the release workflow.
4+
#
5+
# Usage:
6+
# ./release.sh # auto-bump patch (v1.2.3 -> v1.2.4)
7+
# ./release.sh v1.3.0 # use specific version
8+
# ./release.sh minor # bump minor (v1.2.3 -> v1.3.0)
9+
# ./release.sh major # bump major (v1.2.3 -> v2.0.0)
510

6-
# exit on error
711
set -e
8-
# print every command being run
9-
set -x
1012

11-
# curl + jq package.json to get version number from repo
12-
# https://raw.githubusercontent.com/letsdiscodev/cli/main/package.json
13-
# store version number in variable
14-
version_from_repo=$(curl -s https://raw.githubusercontent.com/letsdiscodev/cli/main/package.json | jq -r '.version')
15-
version_from_package=$(cat package.json | jq -r '.version')
16-
# if the versions are the same, fail/exit/quit.
17-
if [ "$version_from_repo" = "$version_from_package" ]; then
18-
echo "The version in package.json is the same as the version in the repo. Please update the version in package.json before running this script"
19-
exit 1
13+
# Get the latest tag
14+
latest_tag=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0")
15+
latest_version="${latest_tag#v}"
16+
17+
# Parse version components
18+
IFS='.' read -r major minor patch <<< "$latest_version"
19+
20+
# Determine the new version
21+
if [ -n "$1" ]; then
22+
case "$1" in
23+
major)
24+
new_version="$((major + 1)).0.0"
25+
;;
26+
minor)
27+
new_version="${major}.$((minor + 1)).0"
28+
;;
29+
patch)
30+
new_version="${major}.${minor}.$((patch + 1))"
31+
;;
32+
v*)
33+
new_version="${1#v}"
34+
;;
35+
*)
36+
new_version="$1"
37+
;;
38+
esac
39+
else
40+
# Default: check package.json, use it if higher, otherwise bump patch
41+
package_version=$(node -p "require('./package.json').version")
42+
43+
# Compare versions (simple string compare works for semver)
44+
if [ "$(printf '%s\n' "$latest_version" "$package_version" | sort -V | tail -n1)" = "$package_version" ] && [ "$package_version" != "$latest_version" ]; then
45+
new_version="$package_version"
46+
echo "Using version from package.json: $new_version"
47+
else
48+
new_version="${major}.${minor}.$((patch + 1))"
49+
echo "Auto-bumping patch: $latest_version -> $new_version"
50+
fi
2051
fi
2152

22-
# fail if git status shows changes not staged for commit
23-
if [[ `git status --porcelain` ]]; then
24-
echo "There are changes not staged for commit. Please commit or stash them before running this script"
25-
exit 1
26-
fi
53+
new_tag="v$new_version"
2754

28-
if [ -z "${AWS_ACCESS_KEY_ID}" ]; then
29-
# fail
30-
echo "AWS_ACCESS_KEY_ID is not set Please set it before running this script"
55+
# Check if tag already exists
56+
if git rev-parse "$new_tag" >/dev/null 2>&1; then
57+
echo "Error: Tag $new_tag already exists"
3158
exit 1
3259
fi
3360

34-
if [ -z "${AWS_SECRET_ACCESS_KEY}" ]; then
35-
# fail
36-
echo "AWS_SECRET_ACCESS_KEY is not set Please set it before running this script"
37-
exit 1
38-
fi
61+
# Confirm with user
62+
echo ""
63+
echo "This will create and push tag: $new_tag"
64+
echo "GitHub Actions will then build and release."
65+
read -p "Continue? [y/N] " -n 1 -r
66+
echo ""
3967

40-
if [ -z "${AWS_CLOUDFRONT_DISTRIBUTION_ID}" ]; then
41-
# fail
42-
echo "AWS_CLOUDFRONT_DISTRIBUTION_ID is not set Please set it before running this script"
68+
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
69+
echo "Aborted."
4370
exit 1
4471
fi
4572

46-
# get the latest release pushed to the repo
47-
# watch out as it has a 'v' at the beginning
48-
# latest_release=$(gh release list --limit 1 --json tagName --jq '.[0].tagName')
49-
50-
# get the version by cat'ing package.json into jq and extracting the version
51-
version=$(cat package.json | jq -r '.version')
52-
53-
# check if the latest release is the same as the version in package.json
54-
# don't use right now as this script is not running as part of the github release workflow
55-
# if [ "$latest_release" = "v$version" ]; then
56-
# echo "The latest release is the same as the version in package.json. Please update the version in package.json before running this script"
57-
# exit 1
58-
# fi
59-
60-
61-
# ---
73+
# Create and push the tag
74+
git tag "$new_tag"
75+
git push origin "$new_tag"
6276

63-
rm -rf dist
64-
rm -rf tmp
65-
66-
npm ci
67-
68-
npm run build
69-
70-
oclif pack tarballs --no-xz
71-
72-
oclif upload tarballs --no-xz
73-
74-
# promote tarballs
75-
76-
# get the hash by calling python
77-
hash=$(export PACKAGE_VERSION=$version && python3 -c "from pathlib import Path; import os; print(str(list(Path('./dist').glob('disco-v' + os.environ['PACKAGE_VERSION'] + '*'))[0]).split('-')[2])")
78-
79-
oclif promote --sha $hash --version $version --no-xz
80-
81-
aws cloudfront create-invalidation --distribution-id $AWS_CLOUDFRONT_DISTRIBUTION_ID --paths "/*"
82-
83-
echo "done"
84-
echo ""
85-
echo "***** * ** * * DONT FORGET TO GIT PUSH * * * ** * ******* *****"
8677
echo ""
78+
echo "Tag $new_tag pushed. GitHub Actions will handle the release."
79+
echo "Watch progress at: https://github.com/letsdiscodev/cli/actions"

0 commit comments

Comments
 (0)