Skip to content

Commit caddd90

Browse files
committed
chore: merge w main
2 parents f32fa48 + 1059ec2 commit caddd90

507 files changed

Lines changed: 7061 additions & 5148 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: 23 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ jobs:
113113
default: "dev-build"
114114
docker: # run the steps with Docker
115115
# CircleCI Go images available at: https://hub.docker.com/r/circleci/golang/
116-
- image: cimg/go:1.25.0
116+
- image: cimg/go:1.26.0
117117
steps: # steps that comprise the `build` job
118118
- checkout # check out source code to working directory
119119
- restore_cache: # restores saved cache if no changes are detected since last run
@@ -128,6 +128,10 @@ jobs:
128128
name: Run Unit Tests
129129
command: |
130130
make test
131+
- run:
132+
name: Run Install Tests
133+
command: |
134+
make test-install
131135
- run:
132136
name: Sync Tests Results
133137
command: |
@@ -550,6 +554,15 @@ workflows:
550554
context: slack-cli-release
551555
release_ref: dev-build
552556
- e2e-test:
557+
name: e2e-test-unix
558+
manual_trigger_windows: false
559+
requires:
560+
- create-github-release-and-artifacts
561+
context: slack-cli-e2e
562+
release_ref: dev-build
563+
- e2e-test:
564+
name: e2e-test-windows
565+
manual_trigger_windows: true
553566
requires:
554567
- create-github-release-and-artifacts
555568
context: slack-cli-e2e
@@ -576,6 +589,15 @@ workflows:
576589
context: slack-cli-release
577590
release_ref: dev-build
578591
- e2e-test:
592+
name: e2e-test-unix
593+
manual_trigger_windows: false
594+
requires:
595+
- create-github-release-and-artifacts
596+
context: slack-cli-e2e
597+
release_ref: dev-build
598+
- e2e-test:
599+
name: e2e-test-windows
600+
manual_trigger_windows: true
579601
requires:
580602
- create-github-release-and-artifacts
581603
context: slack-cli-e2e
@@ -691,34 +713,3 @@ workflows:
691713
requires:
692714
- create-github-release-and-artifacts
693715
context: slack-cli-release
694-
695-
# production tests are run separate from deployment to avoid errors with tags.
696-
prod-build-test-e2e-test:
697-
when:
698-
matches:
699-
pattern: "^v(\\d+\\.)?(\\d+\\.)?(\\d+)$"
700-
value: << pipeline.git.tag >>
701-
jobs:
702-
- build:
703-
<<: *filters-tag-triggered-workflow-job
704-
context: slack-cli-release
705-
release_ref: << pipeline.git.tag >>
706-
- create-github-release-and-artifacts:
707-
requires:
708-
- build
709-
context: slack-cli-release
710-
release_ref: << pipeline.git.branch >>
711-
- e2e-test:
712-
name: e2e-test-unix
713-
e2e_target_branch: "main"
714-
manual_trigger_windows: false
715-
requires:
716-
- create-github-release-and-artifacts
717-
context: slack-cli-e2e
718-
- e2e-test:
719-
name: e2e-test-windows
720-
e2e_target_branch: "main"
721-
manual_trigger_windows: true
722-
requires:
723-
- create-github-release-and-artifacts
724-
context: slack-cli-e2e

.circleci/runner/src/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2022-2025 Salesforce, Inc.
1+
# Copyright 2022-2026 Salesforce, Inc.
22
#
33
# Licensed under the Apache License, Version 2.0 (the "License");
44
# you may not use this file except in compliance with the License.

.circleci/runner/src/circlerunner.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#!/usr/bin/python3
2-
# Copyright 2022-2025 Salesforce, Inc.
2+
# Copyright 2022-2026 Salesforce, Inc.
33
#
44
# Licensed under the Apache License, Version 2.0 (the "License");
55
# you may not use this file except in compliance with the License.

.circleci/runner/src/macrunner.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#!/usr/bin/python3
2-
# Copyright 2022-2025 Salesforce, Inc.
2+
# Copyright 2022-2026 Salesforce, Inc.
33
#
44
# Licensed under the Apache License, Version 2.0 (the "License");
55
# you may not use this file except in compliance with the License.

.circleci/runner/src/scripts/mac/code-sign.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#!/usr/bin/env bash
2-
# Copyright 2022-2025 Salesforce, Inc.
2+
# Copyright 2022-2026 Salesforce, Inc.
33
#
44
# Licensed under the Apache License, Version 2.0 (the "License");
55
# you may not use this file except in compliance with the License.

.circleci/runner/src/scripts/mac/setup-keychain.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#!/bin/bash
2-
# Copyright 2022-2025 Salesforce, Inc.
2+
# Copyright 2022-2026 Salesforce, Inc.
33
#
44
# Licensed under the Apache License, Version 2.0 (the "License");
55
# you may not use this file except in compliance with the License.

.circleci/runner/src/scripts/mac/teardown.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#!/bin/bash
2-
# Copyright 2022-2025 Salesforce, Inc.
2+
# Copyright 2022-2026 Salesforce, Inc.
33
#
44
# Licensed under the Apache License, Version 2.0 (the "License");
55
# you may not use this file except in compliance with the License.

.claude/CLAUDE.md

Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Project Overview
6+
7+
The Slack CLI is a command-line interface for building apps on the Slack Platform. Written in Go, it provides developers with tools to create, run, deploy, and manage Slack apps locally and remotely.
8+
9+
## Development Commands
10+
11+
### Building
12+
13+
```bash
14+
make build # Build the CLI (includes linting and cleaning)
15+
make build-ci # Build for CI (skips lint and tests)
16+
./bin/slack --version # Run the compiled binary
17+
```
18+
19+
### Testing
20+
21+
```bash
22+
make test # Run all unit tests
23+
make test testdir=cmd/auth testname=TestLoginCommand # Run specific test
24+
make coverage # View test coverage report
25+
```
26+
27+
### Linting
28+
29+
```bash
30+
make lint # Run golangci-lint
31+
golangci-lint --version # Verify linter version
32+
```
33+
34+
### Other Commands
35+
36+
```bash
37+
make init # Initialize project (fetch tags, dependencies)
38+
make clean # Remove build artifacts (bin/, dist/)
39+
slack docgen ./docs/reference # Generate command documentation
40+
```
41+
42+
## Architecture
43+
44+
### Project Structure
45+
46+
```
47+
cmd/ Commands (user interface layer)
48+
├── auth/ Authentication commands
49+
├── app/ App management commands
50+
├── platform/ Platform commands (deploy, run, activity)
51+
├── project/ Project commands (create, init, samples)
52+
└── root.go Root command initialization and alias mapping
53+
54+
internal/ Private packages (implementation details)
55+
├── api/ Slack API client and HTTP communication
56+
├── app/ App manifest and client logic
57+
├── auth/ Authentication handling
58+
├── config/ Configuration management
59+
├── hooks/ Hook system for lifecycle events
60+
├── iostreams/ I/O handling (stdin, stdout, stderr)
61+
├── shared/ Shared client factory pattern
62+
└── experiment/ Feature flag system
63+
64+
main.go Entry point with tracing and context setup
65+
```
66+
67+
### Key Architectural Patterns
68+
69+
**Command Aliases**: Many commands have shortcut aliases defined in `cmd/root.go`'s `AliasMap`:
70+
71+
- `slack login``slack auth login`
72+
- `slack deploy``slack platform deploy`
73+
- `slack create``slack project create`
74+
75+
**Client Factory Pattern**: `internal/shared/clients.go` provides a `ClientFactory` that manages shared clients and configurations across commands:
76+
77+
- `API()` - Slack API client
78+
- `Auth()` - Authentication client
79+
- `AppClient()` - App management client
80+
- `Config` - Configuration state
81+
- `IO` - I/O streams
82+
- `Fs` - File system (afero)
83+
84+
Commands receive the `ClientFactory` and use it to access functionality.
85+
86+
**Context-Based State**: The codebase uses `context.Context` extensively to pass runtime state (session IDs, trace IDs, versions) through the call stack via `internal/slackcontext`.
87+
88+
**Tracing**: OpenTracing (Jaeger) is initialized in `main.go` for observability.
89+
90+
**Hook System**: `internal/hooks/` implements a lifecycle hook system that allows SDK projects to inject custom behavior at key points. The specification exists in `docs/reference/hooks` files.
91+
92+
**Experiment System**: Features can be gated behind experiments defined in `internal/experiment/experiment.go`:
93+
94+
- Add new experiments as constants
95+
- Register in `AllExperiments` slice
96+
- Enable permanently via `EnabledExperiments`
97+
- Use `--experiment` flag to toggle
98+
99+
### Command Structure
100+
101+
Commands follow this pattern:
102+
103+
1. Define in `cmd/<category>/<command>.go`
104+
2. Create a Cobra command with use/short/long descriptions
105+
3. Add flags specific to that command
106+
4. Implement `RunE` function that receives clients
107+
5. Add unit tests in `*_test.go` alongside
108+
109+
Example command structure:
110+
111+
```go
112+
func NewExampleCommand(clients *shared.ClientFactory) *cobra.Command {
113+
return &cobra.Command{
114+
Use: "example",
115+
Short: "Brief description",
116+
RunE: func(cmd *cobra.Command, args []string) error {
117+
ctx := cmd.Context()
118+
// Command implementation using clients
119+
return nil
120+
},
121+
}
122+
}
123+
```
124+
125+
### Testing Philosophy
126+
127+
- Unit tests live alongside code with `_test.go` suffix
128+
- Mock implementations use `_mock.go` suffix
129+
- Test code uses syntax compatible with the minimum supported Go version (see `go.mod`)
130+
- The codebase uses `testify` for assertions and `testify/mock` for mocking
131+
- Mock the `ClientFactory` and its dependencies for testing
132+
- Always mock file system operations using `afero.Fs` to enable testability
133+
134+
### Table-Driven Test Conventions
135+
136+
**Preferred: Map pattern** - uses `tc` for test case variable:
137+
138+
```go
139+
tests := map[string]struct {
140+
input string
141+
expected string
142+
}{...}
143+
for name, tc := range tests {
144+
t.Run(name, func(t *testing.T) {
145+
// use tc.field
146+
})
147+
}
148+
```
149+
150+
## Version Management
151+
152+
Versions use semantic versioning with git tags (format: `v*.*.*`).
153+
154+
Version is generated dynamically using `git describe` and injected at build time:
155+
156+
```bash
157+
LDFLAGS=-X 'github.com/slackapi/slack-cli/internal/pkg/version.Version=`git describe --tags --match 'v*.*.*'`'
158+
```
159+
160+
**Versioning Rules**:
161+
162+
- `semver:patch` - Bug fixes and changes behind experiment flags
163+
- `semver:minor` - New features (once experiments are removed)
164+
- `semver:major` - Breaking changes
165+
166+
## Deprecation Process
167+
168+
When deprecating features, commands, or flags:
169+
170+
1. **Commands**: Add `Deprecated` attribute, optionally set `Hidden: true`
171+
2. **Flags**: Print deprecation warning on use, hide with `.Hidden` attribute
172+
3. **Public functionality**: Add comment `// DEPRECATED(semver:major): <description and migration path>`
173+
4. **Internal functionality**: Add comment `// DEPRECATED: <description>`
174+
175+
## Important Configuration Files
176+
177+
- `.golangci.yml` - Linter configuration with custom initialisms (CLI, API, SDK, etc.) and staticcheck rules
178+
- `.goreleaser.yml` - Release build configuration for multi-platform binaries
179+
- `Makefile` - Common development tasks and build scripts
180+
- `go.mod` - Go module dependencies and minimum Go version (see `go.mod` for current version)
181+
- `.circleci/config.yml` - CircleCI workflows for CI/CD pipeline
182+
- `.github/workflows/` - GitHub Actions for automated testing and releases
183+
184+
## Commit Message Format
185+
186+
When creating commits and PRs, append to the end of the commit message:
187+
188+
```
189+
Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
190+
```
191+
192+
Use conventional commit format (feat:, fix:, chore:, etc.) for commit titles.
193+
194+
## Working with the Codebase
195+
196+
### Adding a New Command
197+
198+
1. Create `cmd/<category>/<command>.go`
199+
2. Implement command using `NewXCommand(clients *shared.ClientFactory) *cobra.Command`
200+
3. Register in `cmd/root.go` `Init()` function
201+
4. Add tests in `cmd/<category>/<command>_test.go`
202+
5. Run `slack docgen ./docs/reference` to generate docs
203+
6. Consider adding command alias in `AliasMap` if appropriate
204+
205+
### Adding New Dependencies
206+
207+
1. Update `go.mod` with the new module version
208+
2. Run `go mod tidy` to update `go.sum`
209+
3. Use `go mod graph | grep <module>` to inspect dependency tree
210+
211+
### Understanding API Calls
212+
213+
All Slack API interactions go through `internal/api/`:
214+
215+
- `client.go` - HTTP client setup
216+
- `app.go` - App management API calls
217+
- `auth.go` - Authentication API calls
218+
- `datastore.go` - Datastore API calls
219+
- Each file has corresponding `*_test.go` with mocks
220+
221+
### File System Operations
222+
223+
Always use `clients.Fs` (afero.Fs) instead of direct `os` calls to enable testing and mocking.
224+
225+
## Development Notes
226+
227+
- The CLI binary in development builds is at `./bin/slack`
228+
- Official releases use `/usr/local/bin/slack`
229+
- Set `SLACK_DISABLE_TELEMETRY="true"` to disable telemetry during development
230+
- View experiments with `slack --help --verbose`
231+
- Build artifacts are in `bin/` (local builds) and `dist/` (release builds)
232+
- The `make build` command runs linting automatically before building
233+
- When testing locally, always use `./bin/slack` to avoid conflicts with globally installed versions

.claude/settings.json

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
{
2+
"permissions": {
3+
"allow": [
4+
"Bash(go mod tidy:*)",
5+
"Bash(gofmt:*)",
6+
"Bash(gh issue view:*)",
7+
"Bash(gh label list:*)",
8+
"Bash(gh pr checks:*)",
9+
"Bash(gh pr diff:*)",
10+
"Bash(gh pr list:*)",
11+
"Bash(gh pr status:*)",
12+
"Bash(gh pr update-branch:*)",
13+
"Bash(gh pr view:*)",
14+
"Bash(gh search code:*)",
15+
"Bash(git diff:*)",
16+
"Bash(git grep:*)",
17+
"Bash(git log:*)",
18+
"Bash(git status:*)",
19+
"Bash(go mod graph:*)",
20+
"Bash(go mod tidy:*)",
21+
"Bash(grep:*)",
22+
"Bash(ls:*)",
23+
"Bash(make build:*)",
24+
"Bash(make build-ci:*)",
25+
"Bash(make lint:*)",
26+
"Bash(make test:*)",
27+
"Bash(tree:*)",
28+
"WebFetch(domain:github.com)",
29+
"WebFetch(domain:docs.slack.dev)"
30+
]
31+
}
32+
}

0 commit comments

Comments
 (0)