Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ci: release add #20

Open
wants to merge 2 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: Release
on:
pull_request:
types: [opened, edited, synchronize, reopened]
workflow_dispatch:

permissions:
contents: write
pull-requests: write

jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
- uses: actions/setup-node@v4
with:
node-version: 20
- run: |
npm ci
bash bin/github-release.sh --verbose
env:
GH_TOKEN: ${{ github.token }}
142 changes: 142 additions & 0 deletions bin/github-release.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
#!/usr/bin/env bash

set -euo pipefail

usage() {
cat <<EOF
Script for managing the GitHub release process.

It provides functionality for automatically:
• Creating GitHub pull requests for bumping version numbers
• Drafting new GitHub releases
• Publishing GitHub releases once the version lands on NPM

USAGE
bash bin/github-release.sh [-v|--verbose] [-n|--dry-run]

OPTIONS
-v | --verbose Verbose output
-n | --dry-run Dry run; don't create any commits, tags, or draft a new
release GitHub.

EXAMPLES
bash bin/github-release.sh
EOF
}

verbose="n"
dryrun="n"
while [[ $# -gt 0 ]]; do
case "$1" in
-v|--verbose)
verbose="y"
;;
-n|--dry-run)
dryrun="y"
;;
*)
usage
exit 1
;;
esac
shift
done

log() {
if [[ "$verbose" == "y" ]]; then
echo "$@"
fi
}

if [[ -n "$(git status --porcelain)" ]]; then
echo "ERROR: Dirty Git index, please commit all changes before continuing" 1>&2
if [[ "$dryrun" == "n" ]]; then
exit 1
fi
fi
if ! command -v gh &> /dev/null; then
echo "ERROR: Please install the 'gh' GitHub CLI" 1>&2
exit 1
fi

name="$(jq -r '.name' package.json)"
current="$(jq -r '.version' package.json)"
latest="$(npm view "$name" version)"

log "current: v$current"
log "latest: v$latest"

if ! printf "%s\n" "$latest" "$current" | sort -C -V; then
echo "ERROR: Latest NPM version is newer than current version" 1>&2
exit 1
fi

tag="v$current"
commit="$(git rev-parse HEAD)"
draft="$(gh release view "$tag" --json isDraft,targetCommitish --jq 'if(.isDraft) then .targetCommitish else "" end' 2>/dev/null || true)"

log "commit: ${commit}"
log "draft: ${draft:-none}"

if [[ -z "$draft" ]] && [[ "$current" == "$latest" ]]; then
# In this case, we have no existing draft, and the current version is
# the same as the latest release, so we need to create a new PR to bump
# the package version.
log "==> Bumping Version"

git fetch --tags --force --quiet
if [[ -n "$(git tag -l --points-at HEAD | awk '$1 == "'$tag'"')" ]]; then
log "no changes since latest release"
exit 0
fi

newtag="$(npm version patch --no-git-tag-version)"
log "bumping to $newtag"

branch="bump/$newtag"
if git ls-remote --heads origin | grep "refs/heads/$branch\$" >/dev/null; then
log "version bump PR already exists"
exit 0
fi
if [[ "$dryrun" == "n" ]]; then
log "creating PR bumping version"
git checkout -b "$branch"
git commit -am "Bump Version to $newtag"
git push -u origin "$branch"
gh pr create --fill
fi
elif [[ "$current" != "$latest" ]]; then
# In this case, the current version is newer that the latest released
# version on NPM, so we create or update the draft release to ensure it
# includes the latest version.
log "==> Drafting Release"

if [[ "$commit" == "$draft" ]]; then
log "draft is already at latest commit"
exit 0
fi

log "generating NPM package"
npm pack
package="${name#@}-$current.tgz"
package="${package//\//-}"

if [[ "$dryrun" == "n" ]]; then
log "drafting release with NPM tarball"
if [[ -n "$draft" ]]; then
log "cleaning up existing draft"
gh release delete "$tag" --yes
fi
gh release create "$tag" --draft --generate-notes --target "$commit" --title "$tag" "$package"
fi
else # if [[ -n "$draft" ]] && [[ "$current" == "$latest" ]]; then
# In this case, there is an existing draft, and the latest version is
# equal to it. Publish the draft release!
log "==> Publishing Release"

tag="v$current"
if [[ "$dryrun" == "n" ]]; then
log "publishing draft release"
gh release edit "$tag" --draft=false
fi
fi