Files
bass-foundry/docs/releases.md
T
nvrl 5cc3770737
Check and Windows preview / check (anvil) (push) Successful in 2m1s
Check and Windows preview / check (crucible) (push) Successful in 1m31s
Check and Windows preview / check (knurl) (push) Successful in 2m4s
Check and Windows preview / check (lathe) (push) Successful in 1m27s
Check and Windows preview / check (patina) (push) Successful in 1m54s
Check and Windows preview / check (rivet) (push) Successful in 1m30s
Check and Windows preview / check (temper) (push) Successful in 1m31s
Check and Windows preview / check (weld) (push) Successful in 2m31s
Check and Windows preview / previews (push) Successful in 1m26s
Independent plugin release / plan (push) Successful in 7s
Check and Windows preview / windows (push) Successful in 2m26s
Independent plugin release / build (push) Successful in 3m0s
Independent plugin release / publish (push) Successful in 8s
feat(knurl): add Knurl cycle texture
Knurl follows the played note and treats every cycle of the wave on its
own: a repeating level pattern over 1-16 cycles makes subharmonics in tune
with every note, random level and timing per cycle add rattle, and a noise
burst per cycle, highpassed at a multiple of f0, adds grit. Amounts are
counted in cycles, so the texture is the same on F1 and on C2.

- Cycle clock from the shared note tracker, restarted at each note; the
  audio is delayed by the lookahead plus 4.2 ms of timing-jitter headroom.
- Per-cycle randomness from a hash of the cycle number: Same every note
  or Free.
- Patterns Off, Double, Triple, Fry (default), Gallop, Stutter or drawn;
  grit switchable per step. Pattern persisted as knurl-pattern.
- Editor: last eight cycles overlaid, pattern bars with the playing step.
- Tests match the prototype: Double gives f0/2 at -8.19 dB, Triple f0/3
  at -10.68 dB, equal on F1 and C2, no added clicks, bit-exact when off,
  no allocation on the audio thread.
2026-11-06 08:49:11 +01:00

115 lines
5.6 KiB
Markdown

# Independent plugin releases on Gitea
Every Bass Foundry plugin has its own version and its own release. The
workflows are in `.gitea/workflows/`. A plugin's version is the `version` in
`plugins/<plugin>/plugin/Cargo.toml`, and its release tag is
`<plugin>-v<version>`.
| Plugin | Latest tag | Windows download |
| --- | --- | --- |
| Rivet | `rivet-v0.4.0` | `rivet-windows-x86_64-0.4.0.zip` |
| Patina | `patina-v0.2.0` | `patina-windows-x86_64-0.2.0.zip` |
| Anvil | `anvil-v0.1.0` | `anvil-windows-x86_64-0.1.0.zip` |
| Crucible | `crucible-v0.1.0` | `crucible-windows-x86_64-0.1.0.zip` |
| Lathe | `lathe-v0.1.0` | `lathe-windows-x86_64-0.1.0.zip` |
| Temper | `temper-v0.1.0` | `temper-windows-x86_64-0.1.0.zip` |
| Weld | `weld-v0.1.0` | `weld-windows-x86_64-0.1.0.zip` |
| Knurl | `knurl-v0.1.0` | `knurl-windows-x86_64-0.1.0.zip` |
## Make a release
1. Set the new version in the plugin's wrapper `Cargo.toml` and add a section
with that version to `docs/<plugin>/CHANGELOG.md`. Internal crate versions
can change independently.
2. Refresh the affected lockfiles, run the plugin's check, then commit and push.
3. Tag the commit and push only that plugin's tag.
For example, Temper 0.2.0:
```sh
python3 scripts/check-plugin.py --plugin temper
git tag -a temper-v0.2.0 -m "Temper 0.2.0"
git push origin temper-v0.2.0
```
The tag must match the wrapper version and a changelog section exactly. A wrong
plugin name or version fails in the `plan` job, before anything is built or
published. Cargo prerelease versions such as `temper-v0.2.0-rc.1` are supported
and published as prereleases.
## Workflows
**Check and Windows preview** runs on branch pushes, pull requests, and manual
dispatch. It checks every product in a matrix, renders all editor previews, and
provides the combined `bass-foundry-windows-x86_64.zip` as an Actions artifact.
It never publishes a release.
**Independent plugin release** runs when a `<plugin>-v*` tag is pushed, for any
plugin in the catalog:
1. `plan` validates the product/version/changelog and exposes the selected plugin.
2. `build` checks and cross-compiles only that plugin, then packages its Windows
binary, documentation, licenses, internal checksums, and ZIP SHA256 sidecar.
3. `publish` downloads those exact artifacts and creates a Gitea draft release.
It uploads the ZIP and checksum as release attachments, then publishes the
release only after both attachments are present.
Release attachments are independent of the 30-day Actions artifact retention.
The Gitea release page provides the persistent Windows and checksum downloads.
Private repositories keep their usual download access requirements.
## Runner and authentication
Enable Actions in the repository and provide a Docker-capable Gitea runner with
the `ubuntu-latest` label. Jobs use `node:22-bookworm` so JavaScript actions have a
Node runtime, and a local composite action installs Rust and build dependencies.
Windows binaries are cross-compiled with MinGW; no Windows runner or Linux release
binary is required.
### Build cache
Every Rust job restores two caches through the runner's cache server
(`actions/cache@v4`, run from the setup composite action):
- **Toolchain:** rustup's stable toolchain, Cargo's binaries, and the registry and
git sources, keyed by ISO week, Windows target, and all three `Cargo.lock` files.
- **Build directories:** each job's target directories (check per plugin,
previews, Windows preview, release per plugin), keyed the same way.
A new week or a changed lockfile starts a fresh entry, so stale build output does
not accumulate and the stable toolchain refreshes weekly. Within a week, pushes
reuse compiled dependencies and rebuild only this repository's crates. Release
jobs use their own entries and never reuse branch build output. A cache miss only
costs time. The runner's cache server must be enabled (`cache.enabled` in
`act_runner`'s config, the default) and must support post steps of actions
inside composite actions (current `act_runner` releases do).
The workflows use explicit action URLs and the v3-compatible artifact protocol.
Only the publish job requests `contents: write`. It authenticates against the
same Gitea instance using the automatic `secrets.GITEA_TOKEN`; no personal access
token is required. Repository/owner maximum token
permissions must allow release writes. The runner needs access to the Gitea
instance, action repositories, and build dependencies.
References: [Gitea Actions quick start](https://docs.gitea.com/usage/actions/quickstart/),
[job-token permissions](https://docs.gitea.com/usage/actions/token-permissions/),
[release creation API](https://docs.gitea.com/api/next/operations/repo-create-release/),
and [release attachment API](https://docs.gitea.com/api/next/operations/repo-create-release-attachment/).
## Retries
Publication reuses matching attachments, preserves existing release notes, and
repairs incomplete draft uploads. An existing attachment with different bytes is
never replaced. Retry the publish job with its original build artifacts; changing
the compiler or build environment can change a binary even for identical source.
ZIP metadata is deterministic, but that is not a cross-toolchain guarantee.
The release tag must already exist in Gitea; the publisher does not create tags.
The ZIP must contain exactly the selected plugin. Its sidecar and internal file
checksums are verified before any release write.
Link to a plugin's own release or tag. The repository's "latest release" is
only the most recent release of any plugin. Packaging and API behaviour are tested with
fake transports. Every tag in the table above was published by this workflow on
the project's Gitea instance.