Skip to content

Commit 9742434

Browse files
committed
ci: test release candidate in pull request when available
1 parent afcb85d commit 9742434

3 files changed

Lines changed: 161 additions & 43 deletions

File tree

.circleci/config.yml

Lines changed: 20 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -272,49 +272,34 @@ jobs:
272272
done
273273
fi
274274
- run:
275-
name: "Update release description and upload assets to GitHub"
275+
name: "Upload assets to GitHub release"
276276
command: |
277-
# Replace double quotes with single quotes
278277
RELEASE_ID=$(curl -H "Accept: application/vnd.github+json" -H "Authorization: token $GITHUB_RELEASE_TOKEN" "https://api.github.com/repos/slackapi/slack-cli/releases/tags/$RELEASE_REF" | jq -r .id);
279-
PRERELEASE="true";
280-
TARGET="${CIRCLE_SHA1}";
281-
if [ "<< parameters.production >>" != "false" ];
282-
then
283-
PRERELEASE="false";
284-
TARGET="main";
285-
fi
286-
BODY="{\"tag_name\":\"${RELEASE_REF}\",\"name\":\"${RELEASE_REF}\",\"target_commitish\":\"${TARGET}\",\"draft\":false,\"prerelease\":${PRERELEASE},"
287278
288279
if [ "$RELEASE_ID" = "null" ]; then
289-
BODY+="\"generate_release_notes\":true}"
290-
echo "Creating a new GitHub release with: ${BODY}"
291-
RELEASE_ID=$(curl -X POST -H "Accept: application/vnd.github+json" -H "Authorization: token $GITHUB_RELEASE_TOKEN" https://api.github.com/repos/slackapi/slack-cli/releases -d "${BODY}" | jq -r .id)
292-
echo "... complete. RELEASE_ID=${RELEASE_ID}"
293-
else
294-
echo "Overwriting existing GitHub Release data; generating pre-release notes ..."
280+
PRERELEASE="true"
281+
TARGET="${CIRCLE_SHA1}"
282+
if [ "<< parameters.production >>" != "false" ]; then
283+
PRERELEASE="false"
284+
TARGET="main"
285+
fi
286+
echo "Creating GitHub release for $RELEASE_REF..."
287+
RELEASE_ID=$(curl -X POST -H "Accept: application/vnd.github+json" -H "Authorization: token $GITHUB_RELEASE_TOKEN" https://api.github.com/repos/slackapi/slack-cli/releases -d "{\"tag_name\":\"${RELEASE_REF}\",\"name\":\"${RELEASE_REF}\",\"target_commitish\":\"${TARGET}\",\"draft\":false,\"prerelease\":${PRERELEASE},\"generate_release_notes\":true}" | jq -r .id)
288+
elif [ "<< parameters.production >>" = "false" ]; then
295289
LAST_SEMVER_TAG=$(git describe --tags --match 'v*.*.*' --abbrev=0 | cut -d"-" -f1)
296-
# When generating release notes, setting the target tag_name property to an existing tag has GitHub ignore the target_commitish property
297-
# So, set the tag name to the target commit to generate release notes from the last semver tag to the target commit
298-
# See https://docs.github.com/en/rest/releases/releases?apiVersion=2022-11-28#generate-release-notes-content-for-a-release--parameters
299-
# Note the following _does not change releases or tags_ - it only creates release notes, just like clicking "Generate Release Notes" on the GitHub Releases page.
300-
CHANGELOG=$(curl -L -X POST -H "Accept: application/vnd.github+json" -H "Authorization: Bearer $GITHUB_RELEASE_TOKEN" -H "X-GitHub-Api-Version: 2022-11-28" https://api.github.com/repos/slackapi/slack-cli/releases/generate-notes -d "{\"tag_name\":\"${TARGET}\",\"target_commitish\":\"${TARGET}\",\"previous_tag_name\":\"${LAST_SEMVER_TAG}\"}" | jq .body)
301-
echo "Will use release notes: ${CHANGELOG}"
302-
BODY+="\"body\":$CHANGELOG}"
303-
echo "Updating existing GitHub pre-release ${RELEASE_ID} with ${BODY}"
304-
curl -X PATCH -H "Accept: application/vnd.github+json" -H "Authorization: token $GITHUB_RELEASE_TOKEN" https://api.github.com/repos/slackapi/slack-cli/releases/$RELEASE_ID -d "${BODY}"
305-
echo "... complete."
290+
CHANGELOG=$(curl -L -X POST -H "Accept: application/vnd.github+json" -H "Authorization: Bearer $GITHUB_RELEASE_TOKEN" -H "X-GitHub-Api-Version: 2022-11-28" https://api.github.com/repos/slackapi/slack-cli/releases/generate-notes -d "{\"tag_name\":\"${CIRCLE_SHA1}\",\"target_commitish\":\"${CIRCLE_SHA1}\",\"previous_tag_name\":\"${LAST_SEMVER_TAG}\"}" | jq .body)
291+
curl -X PATCH -H "Accept: application/vnd.github+json" -H "Authorization: token $GITHUB_RELEASE_TOKEN" https://api.github.com/repos/slackapi/slack-cli/releases/$RELEASE_ID -d "{\"tag_name\":\"${RELEASE_REF}\",\"name\":\"${RELEASE_REF}\",\"target_commitish\":\"${CIRCLE_SHA1}\",\"draft\":false,\"prerelease\":true,\"body\":$CHANGELOG}"
306292
fi
307293
308-
binaries=`find << parameters.artifact_dir >>/slack_* -maxdepth 1 -not -type d`
309-
for binary in $binaries
310-
do
294+
binaries=$(find << parameters.artifact_dir >>/slack_* -maxdepth 1 -not -type d)
295+
for binary in $binaries; do
311296
curl -X POST \
312-
-H "Authorization: token $GITHUB_RELEASE_TOKEN" \
313-
-H "Accept: application/vnd.github.v3+json" \
314-
-H "Content-Type: $(file -b --mime-type ${binary})" \
315-
-H "Content-Length: $(wc -c <${binary} | xargs)" \
316-
-T "${binary}" \
317-
"https://uploads.github.com/repos/slackapi/slack-cli/releases/$RELEASE_ID/assets?name=$(basename ${binary})" | cat
297+
-H "Authorization: token $GITHUB_RELEASE_TOKEN" \
298+
-H "Accept: application/vnd.github.v3+json" \
299+
-H "Content-Type: $(file -b --mime-type ${binary})" \
300+
-H "Content-Length: $(wc -c <${binary} | xargs)" \
301+
-T "${binary}" \
302+
"https://uploads.github.com/repos/slackapi/slack-cli/releases/$RELEASE_ID/assets?name=$(basename ${binary})" | cat
318303
done
319304
- store_artifacts:
320305
path: << parameters.artifact_dir >>

.github/workflows/release.yml

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
workflow_dispatch:
8+
9+
concurrency: ${{ github.workflow }}-${{ github.ref }}
10+
11+
jobs:
12+
rc:
13+
name: RC
14+
runs-on: ubuntu-latest
15+
permissions:
16+
contents: write
17+
pull-requests: write
18+
steps:
19+
- name: Gather credentials
20+
id: credentials
21+
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
22+
with:
23+
app-id: ${{ secrets.GH_APP_ID_RELEASER }}
24+
private-key: ${{ secrets.GH_APP_PRIVATE_KEY_RELEASER }}
25+
26+
- name: Checkout repo
27+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
28+
with:
29+
fetch-depth: 0
30+
persist-credentials: true
31+
token: ${{ steps.credentials.outputs.token }}
32+
33+
- name: Set up Go
34+
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
35+
with:
36+
go-version-file: go.mod
37+
38+
- name: Decide next version
39+
id: version
40+
env:
41+
GH_TOKEN: ${{ steps.credentials.outputs.token }}
42+
run: |
43+
# Get the latest release tag
44+
LATEST_TAG=$(git describe --tags --match 'v*.*.*' --abbrev=0)
45+
46+
# Get PR numbers since latest tag
47+
PR_NUMBERS=$(git log "${LATEST_TAG}..HEAD" --oneline | grep -oP '#\K[0-9]+' || true)
48+
49+
if [ -z "$PR_NUMBERS" ]; then
50+
echo "No new PRs since $LATEST_TAG"
51+
echo "has_changes=false" >> "$GITHUB_OUTPUT"
52+
exit 0
53+
fi
54+
55+
# Search for highest semver label
56+
SEMVER="patch"
57+
for PR in $PR_NUMBERS; do
58+
LABELS=$(gh pr view "$PR" --json labels --jq '.labels[].name' 2>/dev/null || true)
59+
if echo "$LABELS" | grep -q "semver:major"; then
60+
SEMVER="major"
61+
break
62+
elif echo "$LABELS" | grep -q "semver:minor"; then
63+
SEMVER="minor"
64+
fi
65+
done
66+
67+
# Parse current version
68+
VERSION="${LATEST_TAG#v}"
69+
MAJOR=$(echo "$VERSION" | cut -d. -f1)
70+
MINOR=$(echo "$VERSION" | cut -d. -f2)
71+
PATCH=$(echo "$VERSION" | cut -d. -f3)
72+
73+
# Compute next version
74+
case "$SEMVER" in
75+
major)
76+
NEXT_VERSION="$((MAJOR + 1)).0.0"
77+
;;
78+
minor)
79+
NEXT_VERSION="${MAJOR}.$((MINOR + 1)).0"
80+
;;
81+
patch)
82+
NEXT_VERSION="${MAJOR}.${MINOR}.$((PATCH + 1))"
83+
;;
84+
esac
85+
86+
echo "has_changes=true" >> "$GITHUB_OUTPUT"
87+
echo "next=$NEXT_VERSION" >> "$GITHUB_OUTPUT"
88+
echo "semver=$SEMVER" >> "$GITHUB_OUTPUT"
89+
echo "Bumping $LATEST_TAG to v$NEXT_VERSION"
90+
91+
- name: Generate release commit
92+
if: steps.version.outputs.has_changes == 'true'
93+
env:
94+
RELEASE_VERSION: ${{ steps.version.outputs.next }}
95+
run: |
96+
git config user.name "slack-cli-releaser[bot]"
97+
git config user.email "122933866+slack-cli-releaser[bot]@users.noreply.github.com"
98+
make rc RELEASE_VERSION="$RELEASE_VERSION"
99+
git push origin "HEAD:rc" --force
100+
101+
- name: Create or update release PR
102+
if: steps.version.outputs.has_changes == 'true'
103+
env:
104+
GH_TOKEN: ${{ steps.credentials.outputs.token }}
105+
RELEASE_VERSION: ${{ steps.version.outputs.next }}
106+
SEMVER: ${{ steps.version.outputs.semver }}
107+
run: |
108+
PR_TITLE="chore: release slack-cli v${RELEASE_VERSION}"
109+
PR_BODY=$(cat <<EOF
110+
### Summary
111+
112+
Release v${RELEASE_VERSION}. After merging, create a [GitHub Release](https://github.com/${{ github.repository }}/releases/new?tag=v${RELEASE_VERSION}&title=v${RELEASE_VERSION}) to tag and trigger the release pipeline.
113+
114+
### Testing
115+
116+
Install the [dev-build](https://github.com/slackapi/slack-cli/releases/tag/dev-build) and verify changes.
117+
118+
### Requirements
119+
120+
- [x] I've read and understood the [Contributing Guidelines](https://github.com/slackapi/slack-cli/blob/main/.github/CONTRIBUTING.md) and have done my best effort to follow them.
121+
- [x] I've read and agree to the [Code of Conduct](https://slackhq.github.io/code-of-conduct).
122+
EOF
123+
)
124+
125+
# Check if a PR from rc already exists
126+
EXISTING_PR=$(gh pr list --head rc --base main --json number --jq '.[0].number' 2>/dev/null || true)
127+
128+
if [ -n "$EXISTING_PR" ]; then
129+
gh pr edit "$EXISTING_PR" --remove-label "semver:patch" --remove-label "semver:minor" --remove-label "semver:major" 2>/dev/null || true
130+
gh pr edit "$EXISTING_PR" --title "$PR_TITLE" --body "$PR_BODY" --milestone "Next Release" --label "release" --label "semver:${SEMVER}"
131+
echo "Updated PR #$EXISTING_PR"
132+
else
133+
gh pr create --head rc --base main --title "$PR_TITLE" --body "$PR_BODY" --milestone "Next Release" --label "release" --label "semver:${SEMVER}"
134+
echo "Created new release PR"
135+
fi

Makefile

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -73,18 +73,18 @@ build-ci: clean
7373
build-snapshot: clean
7474
BUILD_VERSION="$(BUILD_VERSION)" LDFLAGS="$(LDFLAGS)" go tool goreleaser --snapshot --clean --skip=publish --config .goreleaser.yml
7575

76-
# Update documentation in a commit tagged as the release
77-
# Usage: `make tag RELEASE_VERSION=3.7.0-example`
78-
.PHONY: tag
79-
tag:
76+
# Create a release candidate commit with updated docs
77+
# Usage: `make rc RELEASE_VERSION=3.7.0-example`
78+
.PHONY: rc
79+
rc:
8080
git diff --quiet --cached
8181
git diff --quiet
8282
@if echo "$(RELEASE_VERSION)" | grep -q '^v'; then \
8383
echo "Error: Release version should not begin with a version prefix."; \
8484
exit 1; \
8585
fi
86-
@printf "$(FONT_BOLD)Creating Branch$(FONT_RESET)\n"
87-
git checkout -b "chore-release-$(RELEASE_VERSION)"
86+
@printf "$(FONT_BOLD)Building CLI$(FONT_RESET)\n"
87+
$(MAKE) build-ci LDFLAGS="-X 'github.com/slackapi/slack-cli/internal/version.Version=v$(RELEASE_VERSION)'"
8888
@printf "$(FONT_BOLD)Updating Docs$(FONT_RESET)\n"
8989
rm -rf ./docs/reference/commands ./docs/reference/errors.md
9090
./bin/slack docgen ./docs/reference --skip-update
@@ -103,5 +103,3 @@ tag:
103103
git add docs/guides/installing-the-slack-cli-for-windows.md
104104
@printf "$(FONT_BOLD)Git Commit$(FONT_RESET)\n"
105105
git commit -m "chore: release slack-cli v$(RELEASE_VERSION)"
106-
# @printf "$(FONT_BOLD)Git Tag$(FONT_RESET)\n"
107-
# git tag v$(RELEASE_VERSION)

0 commit comments

Comments
 (0)