Skip to content

Commit cd86717

Browse files
committed
Merge remote-tracking branch 'origin/main' into mwbrooks-2-way-manifest-sync
2 parents 58e107c + 6dc5f98 commit cd86717

159 files changed

Lines changed: 2323 additions & 708 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.circleci/config.yml

Lines changed: 22 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ jobs:
109109
default: "dev-build"
110110
docker: # run the steps with Docker
111111
# CircleCI Go images available at: https://hub.docker.com/r/circleci/golang/
112-
- image: cimg/go:1.26.3
112+
- image: cimg/go:1.26.4
113113
steps: # steps that comprise the `build` job
114114
- checkout # check out source code to working directory
115115
- restore_cache: # restores saved cache if no changes are detected since last run
@@ -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 >>
@@ -448,7 +433,7 @@ workflows:
448433
<<: *filters-tag-triggered-workflow-job
449434
name: upload-to-s3-for-install-linux-feature-build
450435
s3-target-path: slack-cli
451-
file-name: "slack_cli_*feature_linux_64-bit.tar.gz"
436+
file-name: "slack_cli_*feature_linux_*.tar.gz"
452437
requires:
453438
- create-github-release-and-artifacts
454439
context: slack-cli-release

.claude/CLAUDE.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ See [`.github/STYLE_GUIDE.md`](../.github/STYLE_GUIDE.md) for conventions on com
207207
- `go.mod` - Go module dependencies and minimum Go version (see `go.mod` for current version)
208208
- `.circleci/config.yml` - CircleCI workflows for CI/CD pipeline
209209
- `.github/workflows/` - GitHub Actions for automated testing and releases
210+
- `.githooks/` - Opt-in Git hooks (enable with `git config core.hooksPath .githooks`)
210211

211212
## Commit Message Format
212213

@@ -229,6 +230,10 @@ Use conventional commit format (feat:, fix:, chore:, etc.) for commit titles.
229230
5. Run `slack docgen ./docs/reference` to generate docs
230231
6. Consider adding command alias in `AliasMap` if appropriate
231232

233+
### Command Descriptions and Documentation
234+
235+
Command `Long` descriptions are parsed as Go `text/template` by `docgen` and rendered as MDX for the documentation site. Escape `{` and `[` as `\{` and `\[` in description text to prevent build errors on the docs site. Available template functions: `{{Emoji "name"}}`, `{{LinkText "url"}}`, `{{ToBold "text"}}`.
236+
232237
### Adding New Dependencies
233238

234239
1. Update `go.mod` with the new module version

.githooks/pre-commit

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#!/usr/bin/env bash
2+
# Copyright 2022-2026 Salesforce, Inc.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
set -e
17+
18+
# Guard against committing directly to main
19+
branch="$(git rev-parse --abbrev-ref HEAD)"
20+
if [ "$branch" = "main" ]; then
21+
echo "error: commits directly to main are not allowed. Use a development branch."
22+
exit 1
23+
fi
24+
25+
# Run linter on staged changes
26+
cd "$(git rev-parse --show-toplevel)" || exit 1
27+
go tool golangci-lint run

.github/MAINTAINERS_GUIDE.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ Certain things are common during development and require a few commands.
207207
**Task outline:**
208208

209209
- [Cloning the project](#cloning-the-project)
210+
- [Git hooks](#git-hooks)
210211
- [Initializing the project](#initializing-the-project)
211212
- [Testing](#testing)
212213
- [Module and unit tests](#module-and-unit-tests)
@@ -233,6 +234,19 @@ git clone https://github.com/slackapi/slack-cli.git
233234
cd slack-cli/
234235
```
235236

237+
#### Git hooks
238+
239+
Opt-in Git hooks are available in the `.githooks/` directory. To enable them:
240+
241+
```zsh
242+
git config core.hooksPath .githooks
243+
```
244+
245+
The pre-commit hook will:
246+
247+
- Block commits directly to the `main` branch
248+
- Run `go tool golangci-lint run` to lint before committing
249+
236250
### Initializing the project
237251

238252
When you first clone the project or after you major updates to the project, it's

.github/workflows/dependencies.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ jobs:
5050
app-id: ${{ secrets.GH_APP_ID_RELEASER }}
5151
private-key: ${{ secrets.GH_APP_PRIVATE_KEY_RELEASER }}
5252
- name: Checkout the repo
53-
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
53+
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
5454
with:
5555
persist-credentials: true
5656
ref: main

.github/workflows/license_check.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ jobs:
1313
permissions:
1414
contents: read
1515
steps:
16-
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
16+
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
1717
with:
1818
persist-credentials: false
1919
- name: Check license headers

.github/workflows/release.yml

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
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@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
28+
with:
29+
fetch-depth: 0
30+
persist-credentials: true
31+
ref: main
32+
token: ${{ steps.credentials.outputs.token }}
33+
34+
- name: Set up Go
35+
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
36+
with:
37+
go-version-file: go.mod
38+
39+
- name: Decide next version
40+
id: version
41+
env:
42+
GH_TOKEN: ${{ steps.credentials.outputs.token }}
43+
run: |
44+
# Get the latest release tag
45+
LATEST_TAG=$(git describe --tags --match 'v*.*.*' --abbrev=0)
46+
47+
# Get PR numbers since latest tag
48+
PR_NUMBERS=$(git log "${LATEST_TAG}..HEAD" --oneline | grep -oP '#\K[0-9]+' || true)
49+
50+
if [ -z "$PR_NUMBERS" ]; then
51+
echo "No new PRs since $LATEST_TAG"
52+
echo "has_changes=false" >> "$GITHUB_OUTPUT"
53+
exit 0
54+
fi
55+
56+
# Search for highest semver label
57+
SEMVER="patch"
58+
for PR in $PR_NUMBERS; do
59+
LABELS=$(gh pr view "$PR" --json labels --jq '.labels[].name' 2>/dev/null || true)
60+
if echo "$LABELS" | grep -q "semver:major"; then
61+
SEMVER="major"
62+
break
63+
elif echo "$LABELS" | grep -q "semver:minor"; then
64+
SEMVER="minor"
65+
fi
66+
done
67+
68+
# Parse current version
69+
VERSION="${LATEST_TAG#v}"
70+
MAJOR=$(echo "$VERSION" | cut -d. -f1)
71+
MINOR=$(echo "$VERSION" | cut -d. -f2)
72+
PATCH=$(echo "$VERSION" | cut -d. -f3)
73+
74+
# Compute next version
75+
case "$SEMVER" in
76+
major)
77+
NEXT_VERSION="$((MAJOR + 1)).0.0"
78+
;;
79+
minor)
80+
NEXT_VERSION="${MAJOR}.$((MINOR + 1)).0"
81+
;;
82+
patch)
83+
NEXT_VERSION="${MAJOR}.${MINOR}.$((PATCH + 1))"
84+
;;
85+
esac
86+
87+
echo "has_changes=true" >> "$GITHUB_OUTPUT"
88+
echo "next=$NEXT_VERSION" >> "$GITHUB_OUTPUT"
89+
echo "semver=$SEMVER" >> "$GITHUB_OUTPUT"
90+
echo "Bumping $LATEST_TAG to v$NEXT_VERSION"
91+
92+
- name: Generate release commit
93+
if: steps.version.outputs.has_changes == 'true'
94+
env:
95+
RELEASE_VERSION: ${{ steps.version.outputs.next }}
96+
run: |
97+
git config user.name "slack-cli-releaser[bot]"
98+
git config user.email "122933866+slack-cli-releaser[bot]@users.noreply.github.com"
99+
make rc RELEASE_VERSION="$RELEASE_VERSION"
100+
git push origin "HEAD:refs/heads/rc" --force
101+
102+
- name: Create or update release PR
103+
if: steps.version.outputs.has_changes == 'true'
104+
env:
105+
GH_TOKEN: ${{ steps.credentials.outputs.token }}
106+
RELEASE_VERSION: ${{ steps.version.outputs.next }}
107+
SEMVER: ${{ steps.version.outputs.semver }}
108+
run: |
109+
PR_TITLE="chore: release slack-cli v${RELEASE_VERSION}"
110+
PR_BODY=$(cat <<EOF
111+
### Summary
112+
113+
Release v${RELEASE_VERSION}.
114+
115+
### Testing
116+
117+
- [ ] Confirm unit tests and E2E tests are passing on the [`main`](https://github.com/slackapi/slack-cli/commits/main) branch.
118+
- [ ] Confirm unit tests and E2E tests are passing on this PR.
119+
- [ ] Confirm the [dev-build](https://github.com/slackapi/slack-cli/releases/tag/dev-build) includes all commits since last release.
120+
- [ ] Review open issues or PRs on the "[Next Release](https://github.com/slackapi/slack-cli/milestones)" milestone.
121+
- [ ] Confirm the new version matches the expected next version.
122+
123+
### Reviewers
124+
125+
After merging, create a [GitHub Release](https://github.com/${{ github.repository }}/releases/new?tag=v${RELEASE_VERSION}&title=v${RELEASE_VERSION}) to tag the new version.
126+
127+
### Requirements
128+
129+
- [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.
130+
- [x] I've read and agree to the [Code of Conduct](https://slackhq.github.io/code-of-conduct).
131+
EOF
132+
)
133+
134+
# Check if a PR from rc already exists
135+
EXISTING_PR=$(gh pr list --head rc --base main --json number --jq '.[0].number' 2>/dev/null || true)
136+
137+
if [ -n "$EXISTING_PR" ]; then
138+
gh pr edit "$EXISTING_PR" --remove-label "semver:patch" --remove-label "semver:minor" --remove-label "semver:major" 2>/dev/null || true
139+
gh pr edit "$EXISTING_PR" --title "$PR_TITLE" --body "$PR_BODY" --milestone "Next Release" --add-label "release" --add-label "semver:${SEMVER}"
140+
echo "Updated PR #$EXISTING_PR"
141+
else
142+
gh pr create --draft --head rc --base main --title "$PR_TITLE" --body "$PR_BODY" --milestone "Next Release" --label "release" --label "semver:${SEMVER}"
143+
echo "Created new release PR"
144+
fi

.github/workflows/tests.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,22 @@ jobs:
1313
permissions:
1414
contents: read
1515
steps:
16-
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
16+
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
1717
with:
1818
fetch-depth: 0
1919
persist-credentials: false
2020
- name: Set up Go
2121
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
2222
with:
23-
go-version: "1.26.3"
23+
go-version: "1.26.4"
2424
- name: Lint
2525
run: go tool golangci-lint run --timeout=5m
2626
- name: Unit Tests
2727
run: make test
2828
- name: Install Tests
2929
run: make test-install
3030
- name: Upload coverage to Codecov
31-
uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v6.0.0
31+
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
3232
with:
3333
token: ${{ secrets.CODECOV_TOKEN }}
3434
files: ./coverage.out
@@ -43,13 +43,13 @@ jobs:
4343
checks: write
4444
contents: read
4545
steps:
46-
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
46+
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
4747
with:
4848
persist-credentials: false
4949
- name: Set up Go
5050
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
5151
with:
52-
go-version: "1.26.3"
52+
go-version: "1.26.4"
5353
- name: Report health score
5454
uses: slackapi/slack-health-score@d58a419f15cdaff97e9aa7f09f95772830ab66f7 # v0.1.1
5555
with:

.goreleaser.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ builds:
3232
- windows
3333
goarch:
3434
- amd64
35+
- arm64
36+
ignore:
37+
- goos: windows
38+
goarch: arm64
3539

3640
- id: slack-macos
3741
binary: bin/slack
@@ -74,6 +78,8 @@ archives:
7478
{{- .Env.BUILD_VERSION }}_
7579
{{- if eq .Os "darwin" -}}
7680
macOS_{{ if eq .Arch "all" }}64-bit{{ else }}{{ .Arch }}{{ end }}
81+
{{- else if eq .Os "linux" -}}
82+
linux_{{ .Arch }}
7783
{{- else -}}
7884
{{ .Os }}_{{ if eq .Arch "amd64" }}64-bit{{ else }}{{ .Arch }}{{ end }}
7985
{{- end }}

0 commit comments

Comments
 (0)