diff --git a/tools/monorel/README.md b/tools/monorel/README.md new file mode 100644 index 0000000..01f1ea7 --- /dev/null +++ b/tools/monorel/README.md @@ -0,0 +1,205 @@ +# [monorel](https://github.com/therootcompany/tree/main/tools/monorel/) + +Manage independently-versioned modules and releases in a single repository. + +- initializes monorepo-compatible `.goreleaser.yaml` +- bumps versions _correctly_ with `git` (tags by commit _to_ amodule) +- releases with `goreleaser` and `gh` (multi-arch, cross-compiled) +- single or multiple binaries per release + +```sh +monorel release --recursive ./tools/monorel/ +``` + +Use git tags like this: + +`git tag`: + +```sh +v0.1.0 +v0.1.1 +cmd/sql-migrate/v1.0.2 +cmd/sql-migrate/v2.0.3 +io/transform/gsheet2csv/v1.0.4 +io/transform/gsheet2csv/v1.0.5 +tools/monorel/v0.6.5 +tools/monorel/v1.0.0 +``` + +to manage packaged releases for a project like this: + +```sh +./ # v0.1.1 +├── go.mod # (module-only) +├── cmd/ +│ └── sql-migrate/ # cmd/sql-migrate/v2.0.3 +│ ├── .goreleaser.yaml # (module for binary) +│ └── go.mod +├── io/ +│ └── transform/ +│ └── gsheet2csv/ # io/transform/gsheet2csv/v1.0.5 +│ ├── .goreleaser.yaml # (module with 3 binaries) +│ ├── go.mod +│ └── cmd/ +│ ├── gsheet2csv/ +│ ├── gsheet2env/ +│ └── gsheet2tsv/ +└── tools/ + └── monorel/ # tools/monorel/v1.0.0 + ├── .goreleaser.yaml # (module for binaries) + └── go.mod +``` + +# Install + +`monorel` also uses + +## Linux & macOS + +```sh +webi monorel +source ~/.config/envman/PATH.env +``` + +## Go + +```sh +webi go goreleaser gh +source ~/.config/envman/PATH.env +``` + +```sh +go install github.com/therootcompany/golib/tools/monorel@latest +``` + +# Usage + +1. `init` + ```sh + monorel init --recursive ./ + ``` + Generates a `.goreleaser.yaml` in every module directory (next to each `go.mod`) that contains at least one command package (`package main`), configured to build and release all discovered binaries together (per each target build release package). Also tags an initial v0.1.0 if none is present. + Uses a hard-coded command name with the `{{ .Env.VERSION }}` placeholder to sidestep monorepo config issues. +2. `bump` + ```sh + monorel bump --recursive ./ + ``` + Uses `git log -- ` and `git tag` to tag NOT the latest commit of the repo, but the most recent commit changing _in the module_, with the next semver version. +3. `release` + ```sh + monorel release --recursive ./ + ``` + Uses `goreleaser` to cross-compile a wide range of binaries and then creates a release with `gh` (the GitHub CLI) - first as a draft, then uploading the assets, then finalizing the release as public (non-draft). + +## Init + +Creates a `.goreleaser.yaml` for the `go.mod` of each `package main`. + +```sh +monorel init --recursive ./ +``` + +| Flag | Default | Description | +| --------------- | ------- | ----------------------------------------------------------------------------------------------- | +| `--almost-all` | off | Widen build matrix to include esoteric platforms (see [Build matrix](#build-matrix)) | +| `--android-ndk` | off | Adds _additional_ Android build entries (ones that require `CGO_ENABLED=1` and the Android NDK) | +| `--dry-run` | off | Print what would happen without writing or tagging | +| `--ios` | off | Add an iOS build entry (requires `CGO_ENABLED=1` and Xcode) | +| `--recursive` | off | Find all main packages recursively under each path | + +## Bump + +Maths out the previous and proper next semver release. + +```sh +monorel bump --recursive ./ +``` + +| Flag | Default | Description | +| ------------- | ------- | --------------------------------------------------------- | +| `--dry-run` | off | Print the tag that would be created without creating it | +| `--force` | off | If no new commits, create an empty bump commit and tag it | +| `--recursive` | off | Find all main packages recursively | + +## Release + +Build all binaries, puts them in common package formats (`.tar.gz`, `.tar.zst`, `.zip`), creates a GitHub Release, uploads the packages, and makes the release public. + +```sh +monorel release --recursive ./ +``` + +| Flag | Default | Description | +| -------------- | ------- | ----------------------------------------------------------------- | +| `--draft` | off | Keep the GitHub release in draft state after uploading | +| `--dry-run` | off | Show each step without running it | +| `--prerelease` | off | Keep the GitHub release marked as pre-release even for clean tags | +| `--recursive` | off | Find all main packages recursively | +| `--yes` | off | Run all steps without prompting | + +### Interactive Prompts + +1. **Create git tag** — skipped when a tag for this version already exists. +2. **Push commits and tags** — `git push && git push --tags`. +3. **Build with goreleaser** — `goreleaser release --clean --skip=validate,announce` + with `VERSION=` set in the environment. +4. **Create GitHub release** — always created as `--draft --prerelease` so + artifacts can be uploaded before the release goes public. +5. **Upload artifacts** — `gh release upload` with all `.tar.gz`, `.tar.zst`, + `.zip`, and checksum files from `dist/`. +6. **Finalize release visibility** — removes `--draft` and/or `--prerelease` + flags as appropriate (see `--draft` / `--prerelease` below). + +# Build matrix + +The generated `.goreleaser.yaml` targets `CGO_ENABLED=0` for by default. +Platforms that require CGO or a special toolchain are only included when the +corresponding flag is given. + +The default matrix contains: + +| | Values | +| --------- | --------------------------------------------------------------------- | +| `goos` | `darwin` `freebsd` `js` `linux` `netbsd` `openbsd` `wasip1` `windows` | +| `goarch` | `amd64` `arm` `arm64` `mips64le` `mipsle` `ppc64le` `riscv64` `wasm` | +| `goamd64` | `v1` `v2` | +| `goamd64` | `v3` `v4` | +| `goarm` | `6` `7` | + +`--almost-all` adds less-commonly-targeted platforms: + +| | Added values | +| --------- | ----------------------------------------------- | +| `goos` | `aix` `dragonfly` `illumos` `plan9` `solaris` | +| `goarch` | `386` `loong64` `mips` `mips64` `ppc64` `s390x` | +| `goamd64` | `v1` `v2` `v3` `v4` | + +`--ios` adds an ios build entry, which requires the Xcode toolchain: + +```yaml +- id: -ios + env: + - CGO_ENABLED=1 + goos: + - ios + goarch: + - arm64 +``` + +`--android-ndk` adds a build entry for Android/arm64, which requires the [Android NDK](https://developer.android.com/ndk): + +```yaml +- id: -android + env: + - CGO_ENABLED=1 + goos: + - android + goarch: + - arm64 +``` + +# vs GoReleaser Pro + +This isn't a replacement for [GoRoleaser Pro](https://goreleaser.com/pro/). + +Although I wouldn't have created it if multi-module version management were available in a (free or paid) version of GoReleaser without a subscription, this handles _initialization_, _versioning_, and _releasing_ in the way that I've wanted for my workflow (and this repository).