|
1 | 1 | # Contributing |
2 | | -## Release process |
| 2 | + |
| 3 | +This project wraps [adobe/ims-go](https://github.com/adobe/ims-go). |
| 4 | + |
| 5 | +## Development |
| 6 | + |
| 7 | +```bash |
| 8 | +# Build |
| 9 | +go build -o imscli . |
| 10 | + |
| 11 | +# Run all tests |
| 12 | +go test ./... |
| 13 | + |
| 14 | +# Run a single test by name |
| 15 | +go test ./ims/ -run TestValidateURL |
| 16 | + |
| 17 | +# Vet (static analysis) |
| 18 | +go vet ./... |
| 19 | +``` |
| 20 | + |
| 21 | +## CI Pipelines |
| 22 | + |
| 23 | +All pipelines are defined in `.github/workflows/`. |
| 24 | + |
| 25 | +### CI (`ci.yml`) |
| 26 | + |
| 27 | +**Triggers:** Every push to any branch and pull requests targeting `main`. |
| 28 | + |
| 29 | +Runs three parallel jobs: |
| 30 | + |
| 31 | +- **Test** — Runs `go test -race` with coverage and prints a coverage summary to the log. Verifies dependency checksums with `go mod verify`. |
| 32 | +- **Lint** — Runs `go vet` and [golangci-lint](https://golangci-lint.run/) for extended static analysis. |
| 33 | +- **Build** — Verifies the project compiles and validates `.goreleaser.yml` with `goreleaser check`. Cross-platform builds are handled by GoReleaser at release time, so a single-platform check suffices here. |
| 34 | + |
| 35 | +### PR Title (`pr-title.yml`) |
| 36 | + |
| 37 | +**Triggers:** When a pull request is opened, edited, synchronized or reopened. |
| 38 | + |
| 39 | +Validates that the PR title follows the [Conventional Commits](https://www.conventionalcommits.org) format (e.g. `feat: add token refresh`, `fix(auth): handle expired tokens`). This is enforced because the repository is configured for **squash merging only** — the PR title becomes the commit message on `main`, and GoReleaser uses these prefixes to group the release changelog into Features, Bug Fixes, etc. |
| 40 | + |
| 41 | +### Release (`main.yml`) |
| 42 | + |
| 43 | +**Triggers:** Pushing a version tag (e.g. `v1.2.3`) or manual dispatch from the Actions tab. |
| 44 | + |
| 45 | +Runs [GoReleaser](https://goreleaser.com) to build cross-platform binaries (linux/darwin/windows × amd64/arm64), package them as archives and system packages (deb, rpm, apk), generate a changelog grouped by commit type, and publish a GitHub Release with all artifacts. |
| 46 | + |
| 47 | +### CodeQL (`codeql-analysis.yml`) |
| 48 | + |
| 49 | +**Triggers:** Every push, pull requests targeting `main`, and weekly on a cron schedule. |
| 50 | + |
| 51 | +Runs GitHub's CodeQL security analysis to detect vulnerabilities in the Go source code. |
| 52 | + |
| 53 | +### govulncheck (`govulncheck.yml`) |
| 54 | + |
| 55 | +**Triggers:** Every push to `main`, pull requests, and weekly on Monday at 9:00 UTC. |
| 56 | + |
| 57 | +Runs Go's official vulnerability scanner ([govulncheck](https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck)) against all packages. The job fails if any known vulnerabilities in the Go vulnerability database affect the code. Unlike general-purpose scanners, govulncheck traces call graphs — it only reports vulnerabilities in functions your code actually calls. The weekly schedule catches new vulnerabilities even when the code hasn't changed. If the scheduled scan fails, a GitHub issue labeled `security` is created automatically. |
| 58 | + |
| 59 | +## Repository Settings |
| 60 | + |
| 61 | +- **Squash merge only** — Merge commits and rebase merging are disabled. The PR title is used as the squash commit message, ensuring conventional commit messages land on `main`. |
| 62 | +- **Auto-delete branches** — Head branches are automatically deleted after a PR is merged. |
| 63 | +- **Renovate auto-merge** — [Renovate](https://docs.renovatebot.com/) monitors `go.mod` for dependency updates and opens PRs automatically. Patch updates (e.g., `v1.8.0` → `v1.8.1`) are auto-merged after CI passes. Minor and major updates require manual review. Configuration lives in `renovate.json`. |
| 64 | +- **Go version pinning** — All CI workflows use `go-version-file: go.mod` so the Go compiler version is controlled by the `toolchain` directive in `go.mod`. To upgrade Go, update `go.mod` (Renovate opens PRs for this automatically). To downgrade after a bad release, revert the `toolchain` line in `go.mod` — all workflows pick up the change immediately. |
| 65 | + |
| 66 | +## Release Process |
3 | 67 |
|
4 | 68 | In order to standardize the release process, [goreleaser](https://goreleaser.com) has been adopted. |
5 | 69 |
|
6 | 70 | To build and release a new version: |
7 | 71 | ``` |
8 | 72 | git tag vX.X.X && git push --tags |
9 | | -gorelease --rm-dist |
| 73 | +goreleaser release --clean |
10 | 74 | ``` |
11 | 75 |
|
12 | 76 | The binary version is set automatically to the git tag. |
13 | 77 |
|
14 | 78 | Please tag new versions using [semantic versioning](https://semver.org/spec/v2.0.0.html). |
| 79 | + |
| 80 | +## Development Notes |
| 81 | + |
| 82 | +### PersistentPreRunE and subcommands |
| 83 | + |
| 84 | +The root command defines a `PersistentPreRunE` that loads configuration from flags, environment variables, and config files (see `cmd/root.go`). In cobra, if a subcommand defines its own `PersistentPreRunE`, it **overrides** the parent's — the root's `PersistentPreRunE` will not run for that subcommand or its children. If you need to add a `PersistentPreRunE` to a subcommand, you must explicitly call the parent's first. |
| 85 | + |
| 86 | +## Additional Reading |
| 87 | + |
| 88 | +The `docs/` directory contains write-ups on non-obvious problems encountered during development: |
| 89 | + |
| 90 | +- [OAuth Local Server: Unhandled Serve() Error](docs/oauth-serve-error.md) — Why the `Serve` goroutine error is captured via a buffered channel, and why the channel must be buffered. |
| 91 | +- [OAuth Local Server Shutdown Deadlock](docs/oauth-shutdown-deadlock.md) — How an unbuffered channel creates a deadlock between the HTTP handler and `Shutdown()`, and the two-part fix. |
0 commit comments