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

feat(release): change the prerelease logic #743

Merged
merged 21 commits into from
Apr 24, 2024
Merged
Show file tree
Hide file tree
Changes from 17 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
52 changes: 52 additions & 0 deletions orbs/shared/jobs/pre-release.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
description: Pre-releases a new version of the application
parameters:
node_client:
description: Build and release a Node.JS gRPC client
type: boolean
default: false
dryrun:
description: Don't actually release, just dryrun the release flow
type: boolean
default: true
machine:
description: Denotes that we're using a machine executor. Will need to set executor manually
type: boolean
default: false
resource_class:
description: The resource class to use for the release
type: string
default: "large"
release_failure_slack_channel:
description: The slack channel to notify if the release fails
type: string
default: ""
executor:
description: The executor to use for the release
type: executor
default: "testbed-docker"
resource_class: << parameters.resource_class >>
executor: << parameters.executor >>
steps:
- setup_environment:
machine: << parameters.machine >>
- when:
condition: << parameters.node_client >>
steps:
- with_node_client_cache:
build: true
- with_node_cache:
save: true
- when:
condition: << parameters.dryrun >>
steps:
- run:
name: Pre-elease (dry run)
command: ./scripts/shell-wrapper.sh ci/release/dryrun.sh
- unless:
condition: << parameters.dryrun >>
steps:
- run:
name: Pre-release
environment:
RELEASE_FAILURE_SLACK_CHANNEL: << parameters.release_failure_slack_channel >>
command: ./scripts/shell-wrapper.sh ci/release/pre-release.sh
2 changes: 1 addition & 1 deletion orbs/shared/jobs/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ steps:
condition: << parameters.dryrun >>
steps:
- run:
name: Release (Dry-run)
name: Release (dry run)
command: ./scripts/shell-wrapper.sh ci/release/dryrun.sh
no_output_timeout: << parameters.no_output_timeout >>
- unless:
Expand Down
33 changes: 33 additions & 0 deletions orbs/shared/jobs/trigger_rc_release.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
description: Trigger release a new rc version of the application
yj-yan marked this conversation as resolved.
Show resolved Hide resolved
parameters:
machine:
description: Denotes that we're using a machine executor. Will need to set executor manually
type: boolean
default: false
resource_class:
description: The resource class to use for the release
type: string
# This is to trigger the release job, small should be enough
default: "small"
release_failure_slack_channel:
description: The slack channel to notify if the release fails
type: string
default: ""
executor:
description: The executor to use for the release
type: executor
default: "testbed-docker"

resource_class: << parameters.resource_class >>
executor: << parameters.executor >>
steps:
- setup_environment:
machine: << parameters.machine >>
- with_node_cache:
save: true
- checkout
- run:
name: Trigger RC Release
environment:
RELEASE_FAILURE_SLACK_CHANNEL: << parameters.release_failure_slack_channel >>
command: ./scripts/shell-wrapper.sh ci/release/trigger-rc-release.sh
25 changes: 15 additions & 10 deletions shell/ci/release/dryrun.sh
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,21 @@ git checkout "$CIRCLE_BRANCH"

# Squash our branch onto the HEAD (default) branch to mimic
# what would happen after merge.
git merge --squash "$OLD_CIRCLE_BRANCH"
git commit -m "$COMMIT_MESSAGE"

GH_TOKEN="$(cat "$HOME/.outreach/github.token")"
if [[ -z $GH_TOKEN ]]; then
echo "Failed to read Github personal access token" >&2
if ! git diff --quiet "$OLD_CIRCLE_BRANCH" ; then
git merge --squash "$OLD_CIRCLE_BRANCH"
git commit -m "$COMMIT_MESSAGE"
GH_TOKEN="$(cat "$HOME/.outreach/github.token")"
yj-yan marked this conversation as resolved.
Show resolved Hide resolved
if [[ -z $GH_TOKEN ]]; then
echo "Failed to read Github personal access token" >&2
fi

GH_TOKEN="$GH_TOKEN" yarn --frozen-lockfile semantic-release --dry-run

# Handle prereleases for CLIs, pre-conditions for this exist
# in the script.
"$DIR/pre-release.sh" --dry-run
else
echo "No changes to release"
fi

GH_TOKEN="$GH_TOKEN" yarn --frozen-lockfile semantic-release --dry-run

# Handle unstable releasing for CLIs, pre-conditions for this exist
# in the script.
"$DIR/unstable-release.sh" --dry-run
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/usr/bin/env bash

# This file contains the logic for releasing unstable code on CLI
# containing repositories that have also opted to enablePrereleases
# _and_ not release from the default branch (e.g. main).
Expand Down Expand Up @@ -53,24 +54,17 @@ if [[ "$(yaml_get_field ".arguments.releaseOptions.enablePrereleases" "$(get_ser
exit 0
fi

# If our prereleasesBranch is empty, or equal to the default branch
# skip this. This is to enable prereleases to be created from the `main`
# branch thereby skipping the 'unstable' release process entirely.
# Ensure we are on the prerelease branch. The default is main branch.
prereleasesBranch="$(yaml_get_field '.arguments.releaseOptions.prereleasesBranch' "$(get_service_yaml)")"
defaultBranch="$(git rev-parse --abbrev-ref origin/HEAD | sed 's/^origin\///')"
if [[ -z $prereleasesBranch ]] || [[ $prereleasesBranch == "$defaultBranch" ]]; then
echo "releaseOptions.prereleasesBranch is empty or equal to the default branch, skipping unstable release"
exit 0
fi

# If we're not on the default branch, skip. This is to prevent
# If we're not on the prerelease branch, skip. This is to prevent
# accidentally releasing from a branch that isn't mean to create
# unstable releases that happened to fail releasing for whatever reason.
#
# Special case, skip this check if we're doing a dry-run since we will
# short circuit before we actually create a release.
if [[ $CIRCLE_BRANCH != "$defaultBranch" ]] && [[ $DRYRUN == "false" ]]; then
echo "\$CIRCLE_BRANCH ($CIRCLE_BRANCH) != \$defaultBranch ($defaultBranch), skipping unstable release"
if [[ $CIRCLE_BRANCH != "$prereleasesBranch" ]] && [[ $DRYRUN == "false" ]]; then
echo "\$CIRCLE_BRANCH ($CIRCLE_BRANCH) != \$prereleaseBranch ($prereleasesBranch), skipping prerelease"
exit 0
fi

Expand All @@ -87,22 +81,39 @@ if [[ ! -e "$(get_repo_directory)/.goreleaser.yml" ]]; then
exit 0
fi

app_version="v0.0.0-unstable+$(git rev-parse HEAD)"
echo "Creating unstable release ($app_version)"

make release APP_VERSION="$app_version"

# If we're in dry-run mode, skip creating the release.
if [[ $DRYRUN == "true" ]]; then
exit 0
fi

# delete unstable release+tag if it exists
# Check commit message on current branch
# Prerelease to rc if the latest commit is chore: Release.
COMMIT_MESSAGE=$(git log --format=%B -n 1)
if [[ $COMMIT_MESSAGE =~ "chore: Release" ]]; then
# Pre-release to rc
echo "Creating prerelease to rc channel"

# Retrieve the GH_TOKEN
GH_TOKEN=$(gh auth token)
if [[ -z $GH_TOKEN ]]; then
echo "Failed to read Github personal access token" >&2
fi
# Unset NPM_TOKEN to force it to use the configured ~/.npmrc
NPM_TOKEN='' GH_TOKEN=$GH_TOKEN \
yarn --frozen-lockfile semantic-release
exit 0
fi

# publish unstable release
app_version="v0.0.0-unstable+$(git rev-parse HEAD)"
echo "Creating unstable release ($app_version)"

make release APP_VERSION="$app_version"
# delete unstable release and unstable tag if it exists
gh release delete unstable -y || true
git tag --delete unstable || true
git push --delete origin unstable || true

# create unstable release and upload assets to it
gh release create unstable --prerelease --generate-notes ./dist/*.tar.gz ./dist/checksums.txt
# create release and upload assets to it
gh release create unstable --prerelease=true --generate-notes ./dist/*.tar.gz ./dist/checksums.txt

run_unstable_include
21 changes: 2 additions & 19 deletions shell/ci/release/release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ set -e
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
LIB_DIR="${DIR}/../../lib"

# Read the GH_TOKEN from the file
GH_TOKEN="$(cat "$HOME/.outreach/github.token")"
# Retrieve the GH_TOKEN
GH_TOKEN="$(gh auth token)"
if [[ -z $GH_TOKEN ]]; then
echo "Failed to read Github personal access token" >&2
fi
Expand Down Expand Up @@ -40,23 +40,6 @@ unset CIRCLE_PULL_REQUEST
unset CI_PULL_REQUEST
unset CI_PULL_REQUESTS

ORIGINAL_VERSION=$(git describe --match 'v[0-9]*' --tags --always HEAD)

# Unset NPM_TOKEN to force it to use the configured ~/.npmrc
NPM_TOKEN='' GH_TOKEN=$GH_TOKEN \
yarn --frozen-lockfile semantic-release || send_failure_notification

NEW_VERSION=$(git describe --match 'v[0-9]*' --tags --always HEAD)

# Determine if we updated by checking the original version from git
# vs the new version (potentially) after we ran semantic-release.
UPDATED=false
if [[ $ORIGINAL_VERSION != "$NEW_VERSION" ]]; then
UPDATED=true
fi

# If we didn't update, assume we're on a prerelease branch
# and run the unstable-release code.
if [[ $UPDATED == "false" ]]; then
exec "$DIR/unstable-release.sh"
fi
46 changes: 46 additions & 0 deletions shell/ci/release/trigger-rc-release.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/usr/bin/env bash
# This script is to add chore: Release comit to the default pre-release
# branch to trigger pre-release.
set -eo pipefail
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"

# shellcheck source=./../../lib/yaml.sh
source "$DIR/../../lib/yaml.sh"
# shellcheck source=./../../lib/bootstrap.sh
source "$DIR/../../lib/bootstrap.sh"
# shellcheck source=./../../lib/box.sh
source "$DIR/../../lib/box.sh"

if [[ "$(yaml_get_field ".arguments.releaseOptions.enablePrereleases" "$(get_service_yaml)")" != "true" ]]; then
echo "releaseOptions.enablePrereleases is not true, skipping rc release"
exit 0
fi

# Default it to use main branch, should this be configurable?
prereleaseBranch="main"

if [[ -n "$(yaml_get_field ".arguments.releaseOptions.releaseUser" "$(get_service_yaml)")" ]]; then
releaseUsername="$(yaml_get_field ".arguments.releaseOptions.releaseUser.name" "$(get_service_yaml)")"
releaseUseremail="$(yaml_get_field ".arguments.releaseOptions.releaseUser.email" "$(get_service_yaml)")"
else
releaseUsername=$(get_box_field 'ci.circleci.releaseUser.name')
releaseUseremail=$(get_box_field 'ci.circleci.releaseUser.email')
fi

git config --global user.name "$releaseUsername"
git config --global user.email "$releaseUseremail"
git checkout $prereleaseBranch

# Dryrun the semantic-release on prereleaseBranch to check if there is changes to release.
# If not skip the release.
GH_TOKEN=$(gh auth token)
releaseOutput=$(NPM_TOKEN='' GH_TOKEN=$GH_TOKEN yarn --frozen-lockfile semantic-release -d)
echo "$releaseOutput"

if [[ $releaseOutput != *"Published release"* ]]; then
echo "No release will be created, skipping..."
exit 0
fi

git commit -m "chore: Release" --allow-empty
git push origin $prereleaseBranch