Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,15 +65,15 @@ jobs:
! grep -F "syntax error" <<<"$output"

bash-42-logging:
name: Logging smoke (Bash 4.2.53)
name: Compatibility smoke (Bash 4.2.53)
runs-on: ubuntu-24.04
timeout-minutes: 5
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
persist-credentials: false

- name: Run Bash 4.2 logging smoke
- name: Run Bash 4.2 compatibility smokes
run: |
docker run --rm \
--platform linux/amd64 \
Expand All @@ -89,4 +89,8 @@ jobs:
--mount "type=bind,src=$GITHUB_WORKSPACE,dst=/workspace,readonly" \
--workdir /workspace \
docker.io/library/bash@sha256:0931edd3941d0603cb3d5da1cb298cf3eb6a579e09e094c3e34e2d5e9df8cddc \
bash tests/bash-42-logging-smoke.sh 4 2 53
bash -c '
set -e
bash tests/bash-42-logging-smoke.sh 4 2 53
bash tests/bash-42-release-smoke.sh 4 2 53
'
10 changes: 6 additions & 4 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ Read [docs/release-process.md](docs/release-process.md) before doing release
work. Ordinary pull requests must leave `VERSION` unchanged; a release-prep
pull request owns the version, README release row, and changelog transition.

The repository release contract is declared in `base_manifest.yaml`. Use the
guarded `basectl release check|plan|notes|publish` commands after the release
preparation pull request is merged, and complete the Homebrew and Base
downstream handoffs documented in the release process.
The repository release contract is declared in `base_manifest.yaml`, and the
active release-line policy is documented in `docs/versioning-policy.md`. Use
the repository-owned `scripts/release check|plan|notes|publish` guard after the
release preparation pull request is merged. Do not bypass it with direct
`basectl release` calls. Complete the Homebrew and Base downstream handoffs
documented in the release process.

## Shell Changes

Expand Down
11 changes: 10 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,26 @@ and versions are tracked in the repo-root `VERSION` file.

## [Unreleased]

### Added

- Added a repository-owned v2 release guard that permits only the planned
alpha, beta, release-candidate, and GA identifiers while locking publication
until the verified-artifact and pre-GA release-candidate gates are complete.

### Fixed

- Hardened file-section processing, allowed-dirty-path checks, temporary
directory normalization, launcher symlink resolution, and pass-by-name output
handling for the v1.5.0 hardening train.
handling in post-v1.4.0 development.

### Documentation

- Aligned the public Bash API documentation with implementation behavior,
including list removal argument order, TTY detection, assertion semantics,
temporary output arguments, and fatal function assertions.
- Documented the clean-break v2 release line, the withdrawn July 2026 v2 event,
immutable source pins, publication gates, and the canonical release-asset
requirement for Homebrew.

## [1.4.0] - 2026-07-25

Expand Down
4 changes: 3 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ boundary.

For release work, read [docs/release-process.md](docs/release-process.md). The
repository release contract is declared in `base_manifest.yaml`; ordinary pull
requests leave `VERSION` unchanged.
requests leave `VERSION` unchanged. The active release line is documented in
[docs/versioning-policy.md](docs/versioning-policy.md), and every release
operation must enter through the repository-owned `scripts/release` guard.

## Workflow

Expand Down
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,15 @@ You can use a git checkout, tarball extract, or copied source tree without
Homebrew. Keep the repository layout intact so `lib_std.sh` can find the root
`VERSION` file:

Pin the checkout to the full current release commit instead of consuming the
moving default branch:

```bash
git clone https://github.com/basefoundry/base-bash-libs.git vendor/base-bash-libs
git -C vendor/base-bash-libs checkout --detach \
2c5ef2c3a9edfbe2cf68d0645be65b920255abff
test "$(git -C vendor/base-bash-libs rev-parse HEAD)" = \
2c5ef2c3a9edfbe2cf68d0645be65b920255abff
```

Source the stdlib from that checkout:
Expand Down Expand Up @@ -173,6 +180,12 @@ The repo-root `VERSION` file is the source of truth for the package version.
The top strip in this README and the runtime `BASE_BASH_LIBS_VERSION` constant
are validated against that file.

`v1.4.0` remains stable during the clean-break v2 development train. The sole
next stable target is `v2.0.0`; there will be no stable v1.5.0 or version reset
to 0.x. See the [versioning and release-line policy](docs/versioning-policy.md)
for prerelease identifiers, publication gates, the withdrawn July 2026 v2
event, immutable consumption, and the post-GA support contract.

Release preparation and downstream Homebrew/Base handoffs are documented in
[`docs/release-process.md`](docs/release-process.md). The machine-readable
release contract lives in [`base_manifest.yaml`](base_manifest.yaml).
Expand Down
31 changes: 20 additions & 11 deletions docs/release-process.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ This repository declares its release contract in
release commands and is the source of truth for the version file, changelog,
GitHub Release, and Homebrew handoff.

The repository release line and its temporary publication gates are defined in
the [versioning policy](versioning-policy.md). Always enter the release workflow
through [`scripts/release`](../scripts/release); do not invoke
`basectl release` directly. The repository guard validates the candidate before
delegating safe operations to Base's generic release machinery.

## Standard Sequence

1. Create or choose a release issue and set its repository Project metadata.
Expand All @@ -24,17 +30,17 @@ GitHub Release, and Homebrew handoff.
6. Sync local `main`, then inspect the release from the repository root:

```bash
basectl release check --version X.Y.Z --manifest base_manifest.yaml
basectl release plan --version X.Y.Z --manifest base_manifest.yaml
basectl release notes --version X.Y.Z --manifest base_manifest.yaml
basectl release publish --version X.Y.Z --manifest base_manifest.yaml --dry-run
scripts/release check --version X.Y.Z --manifest base_manifest.yaml
scripts/release plan --version X.Y.Z --manifest base_manifest.yaml
scripts/release notes --version X.Y.Z --manifest base_manifest.yaml
scripts/release publish --version X.Y.Z --manifest base_manifest.yaml --dry-run
```

7. Publish only after the readiness checks pass. Use `--yes` only from a
trusted non-interactive release shell:

```bash
basectl release publish --version X.Y.Z --manifest base_manifest.yaml --yes
scripts/release publish --version X.Y.Z --manifest base_manifest.yaml --yes
```

8. Verify the annotated `vX.Y.Z` tag and the GitHub Release for
Expand All @@ -45,10 +51,12 @@ GitHub Release, and Homebrew handoff.
The release contract requires the tap-owned formula
`basefoundry/base/base-bash-libs` in `basefoundry/homebrew-base`.

After the GitHub Release exists:
After the GitHub Release and its verified canonical source asset exist:

1. Create a tap release branch and update `Formula/base-bash-libs.rb` to the
new archive URL, version, SHA256, and version assertions in the formula test.
canonical release-asset URL, version, SHA256, and version assertions in the
formula test. Do not use GitHub's automatic `archive/refs/tags/...` URL for
v2.
2. Validate the formula from the tap checkout:

```bash
Expand All @@ -71,8 +79,9 @@ Base changelog when it is user-visible or release-relevant.

## Finish

Record the library release URL, Homebrew tap pull request, and Base dependency
pull request on the release issue. Remove the release worktree and merged
branches when safe. Do not publish a release while the worktree is dirty, the
version metadata disagrees, the changelog section is missing, or a declared
Record the library release URL, asset checksums and provenance, Homebrew tap
pull request, and Base dependency pull request on the release issue. Remove the
release worktree and merged branches when safe. Do not publish a release while
the worktree is dirty, the version metadata disagrees, the changelog section is
missing, the repository release guard blocks the candidate, or a declared
downstream handoff has not been completed or explicitly deferred.
116 changes: 116 additions & 0 deletions docs/versioning-policy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# Versioning and Release-Line Policy

## Current Release Line

`v1.4.0` remains the stable Base Bash release while the 5/5 initiative in
[#214](https://github.com/basefoundry/base-bash-libs/issues/214) is in progress.
The initiative has one stable target: `v2.0.0`.

The project will not publish a stable `v1.5.0` or reset its version to 0.x.
Those choices would either hide breaking changes inside the current 1.x
compatibility range or move version precedence backward.

The only planned v2 identifiers before GA are:

```text
2.0.0-alpha.N
2.0.0-beta.N
2.0.0-rc.N
2.0.0
```

`N` starts at 1, increases within a phase, and has no leading zeroes. These
identifiers use SemVer syntax, but prereleases may contain breaking changes and
do not receive compatibility shims. The stable SemVer compatibility contract
begins at `v2.0.0` GA.

After GA, v2 is the only supported release line. Versions through `v1.4.0`
remain available as historical releases but no longer receive fixes or support.
Additive features and fixes remain within 2.x; a breaking stable API change
requires v3 or later.

## Release Gates

The repository-owned [`scripts/release`](../scripts/release) command is the
mandatory entry point for every release inspection and publication attempt. It
enforces the permitted v2 identifiers before delegating read-only operations
and dry runs to Base's guarded release command.

Real prerelease publication remains locked until #233 provides deterministic,
verified release assets and provenance. Real `v2.0.0` publication remains
locked until the engineering, policy, documentation, integration, and reference
application gates in #214 are complete and the pre-GA work in #240 has validated
and rehearsed the exact release candidate across Base, Base Demo, Homebrew,
vendored, and bundled paths. The remaining #240 steps then publish compatible
Base and Homebrew updates after the Base Bash GA asset exists.

The lock is code-reviewed policy, not an environment-variable or sentinel-file
override. The PR that satisfies each gate must update the guard and its tests.
Until then, maintainers can inspect a candidate without changing GitHub state:

```bash
scripts/release check --version 2.0.0-rc.1 --manifest base_manifest.yaml
scripts/release plan --version 2.0.0-rc.1 --manifest base_manifest.yaml
scripts/release publish --version 2.0.0-rc.1 --manifest base_manifest.yaml --dry-run
```

The generic `basectl release` command is not a substitute for this guard. Its
current manifest contract does not encode this repository's release line,
artifact, provenance, or GA gates.

## Withdrawn July 2026 Event

On July 2, 2026, [PR #100](https://github.com/basefoundry/base-bash-libs/pull/100)
created commit
[`2d90249`](https://github.com/basefoundry/base-bash-libs/commit/2d90249eec35aa00d04513294ce0fb09042c3f3f)
with `v2.0.0` metadata. A corresponding
[Homebrew PR #66](https://github.com/basefoundry/homebrew-base/pull/66) used
GitHub's automatic tag-archive URL.

The next day, [PR #103](https://github.com/basefoundry/base-bash-libs/pull/103)
and commit
[`6ce8af0`](https://github.com/basefoundry/base-bash-libs/commit/6ce8af02031fad2c0071880b00eb6f526ae2d779)
corrected the release line to `v1.1.0`.
[Homebrew PR #68](https://github.com/basefoundry/homebrew-base/pull/68)
corrected the formula and added `version_scheme 1` so Homebrew would accept the
version-order correction.

The attempted `v2.0.0` remote tag and GitHub Release are no longer present.
The commits and pull requests remain part of the public history, and caches of
the old automatic archive may still exist. The final v2 release therefore uses
a newly verified canonical release asset rather than that automatic archive.
The project will never silently retag or represent the withdrawn artifact as
the final release.

Older local clones can retain the deleted lightweight tag. Inspect both sides
before removing a stale local ref:

```bash
git ls-remote --tags origin refs/tags/v2.0.0
git show-ref --verify refs/tags/v2.0.0
```

If the remote command has no output and the local command finds the withdrawn
ref at `2d90249eec35aa00d04513294ce0fb09042c3f3f`, remove only that local tag:

```bash
git tag -d v2.0.0
```

## Immutable Consumption

Do not install from an unpinned default-branch checkout. Until a verified v2
asset exists, pin the current stable source to the full `v1.4.0` release commit:

```bash
git clone https://github.com/basefoundry/base-bash-libs.git vendor/base-bash-libs
git -C vendor/base-bash-libs checkout --detach \
2c5ef2c3a9edfbe2cf68d0645be65b920255abff
test "$(git -C vendor/base-bash-libs rev-parse HEAD)" = \
2c5ef2c3a9edfbe2cf68d0645be65b920255abff
```

Prerelease validation must likewise use an immutable prerelease tag resolved to
its expected commit, a verified release asset, or a full commit. Release notes,
bug reports, and CI fixtures should record the resolved commit in addition to
the human-readable version.
Loading
Loading