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
28 changes: 20 additions & 8 deletions .github/workflows/semver.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
id-token: write
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # pin@v4
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
fetch-tags: true
Expand Down Expand Up @@ -54,27 +54,35 @@ jobs:
make deps
make deps-check

- name: Validate release inputs
- name: Validate release inputs and artifact flavors
run: make check test

- name: Build release artifact
run: make checksums VERSION="${{ steps.calculate-version.outputs.version-string }}"
- name: Build release artifacts
run: |
make clean
make build VERSION="${{ steps.calculate-version.outputs.version-string }}"

- name: Verify release artifact is independent of build dependencies
- name: Verify release artifacts are independent of build dependencies
run: |
rm -rf vendor
dist/bootstrap.dev.bash --help >/dev/null
dist/bootstrap.bash --help >/dev/null
dist/bootstrap.min.bash --help >/dev/null

- name: Attest release artifacts
uses: actions/attest@1e69f48acb82d1966a394da916b4c1698aa569d6 # pin@v4.2.2
with:
subject-path: |
dist/bootstrap.dev.bash
dist/bootstrap.bash
dist/bootstrap.bash.sha256
dist/bootstrap.min.bash
dist/bootstrap.dev.bash.256
dist/bootstrap.bash.256
dist/bootstrap.min.bash.256

- name: Create release
id: create-release
uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # pin@v3.0.2
uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2
with:
token: "${{ secrets.GITHUB_TOKEN }}"
name: "v${{ steps.calculate-version.outputs.version-string }}"
Expand All @@ -83,5 +91,9 @@ jobs:
draft: false
prerelease: false
files: |
dist/bootstrap.dev.bash
dist/bootstrap.bash
dist/bootstrap.bash.sha256
dist/bootstrap.min.bash
dist/bootstrap.dev.bash.256
dist/bootstrap.bash.256
dist/bootstrap.min.bash.256
2 changes: 1 addition & 1 deletion .github/workflows/static.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
- name: Install documentation dependencies
run: |
sudo apt-get update
sudo apt-get install --yes curl doxygen
sudo apt-get install --yes curl doxygen graphviz

- name: Synchronize and verify build dependencies
run: |
Expand Down
49 changes: 38 additions & 11 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,18 @@ jobs:
- name: Install test dependencies
run: |
sudo apt-get update
sudo apt-get install -y make bats curl doxygen shellcheck shfmt
sudo apt-get install -y make bats curl doxygen graphviz shellcheck shfmt

- name: Verify build does not acquire dependencies
- name: Verify build does not acquire missing dependencies
run: |
test ! -e vendor
make build
stderr="${RUNNER_TEMP}/bootstrap-build.stderr"
if make build >/dev/null 2>"${stderr}"; then
printf '%s\n' 'make build unexpectedly succeeded without Bash-Minifier' >&2
exit 1
fi
grep -F 'Missing build dependency vendor/bash-minifier.bash' "${stderr}"
test ! -e vendor
dist/bootstrap.bash --help >/dev/null

- name: Synchronize and verify project dependencies
run: |
Expand All @@ -46,9 +50,29 @@ jobs:
make all
make deps-check

- name: Verify six build artifacts and checksums
run: |
for artifact in \
bootstrap.dev.bash \
bootstrap.bash \
bootstrap.min.bash; do
test -x "dist/${artifact}"
test -f "dist/${artifact}.256"
(cd dist && sha256sum -c "${artifact}.256")
done
grep -F '# Generated by make build. Do not edit directly.' dist/bootstrap.dev.bash
if grep -F '# Generated by make build. Do not edit directly.' dist/bootstrap.bash; then
printf '%s\n' 'stripped artifact retained a generated full-line comment' >&2
exit 1
fi
if cmp -s dist/bootstrap.bash dist/bootstrap.min.bash; then
printf '%s\n' 'minified artifact is byte-identical to stripped artifact' >&2
exit 1
fi

- name: Verify dependency convergence and offline detection
run: |
printf '%s\n' 'tampered dependency bytes' >vendor/doxygen-bash.awk
printf '%s\n' 'tampered dependency bytes' >vendor/bash-minifier.bash
if make deps-check; then
printf '%s\n' 'deps-check unexpectedly accepted tampered dependency bytes' >&2
exit 1
Expand All @@ -63,17 +87,12 @@ jobs:
test -f doc/reference/index.html
test -z "$(git status --short)"

- name: Verify consumer artifact is independent of vendor state
run: |
rm -rf vendor
dist/bootstrap.bash --help >/dev/null

- name: Run static checks
run: make check
id: shellcheck
continue-on-error: true

- name: Run Bats tests
- name: Run Bats tests for every artifact flavor
id: bats
continue-on-error: true
run: make test-report
Expand All @@ -88,6 +107,14 @@ jobs:
fail-on-error: false
fail-on-empty: true

- name: Verify all consumer artifacts are independent of vendor state
if: steps.bats.outcome == 'success'
run: |
rm -rf vendor
dist/bootstrap.dev.bash --help >/dev/null
dist/bootstrap.bash --help >/dev/null
dist/bootstrap.min.bash --help >/dev/null

- name: Fail if Bats failed
if: steps.bats.outcome == 'failure'
run: exit 1
60 changes: 47 additions & 13 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ The ADR collection is the canonical source of architectural intent.

Before making significant changes, review the relevant ADRs.
Documentation work shall follow ADR-045. Build/development dependency work
shall preserve the boundaries established by ADR-051.
shall preserve the boundaries established by ADR-051. Generated artifact flavor,
minification, checksum, and release work shall preserve ADR-052.

## Clarify Before Acting

Expand Down Expand Up @@ -64,8 +65,8 @@ A useful guiding principle is:
- Preserve stable public interfaces.
- Prefer explicit, deterministic, inspectable behavior.
- Keep the core engine intentionally small.
- Keep build/development dependency tooling outside the released runtime
artifact.
- Keep build/development dependency tooling outside released runtime
artifacts.

## Technology Stack

Expand All @@ -79,7 +80,9 @@ Runtime and project implementation:
- Plain-text manifests

Development/build orchestration also uses Make and the pinned released
`bashdeps.bash` bootstrap described by ADR-051.
`bashdeps.bash` bootstrap described by ADR-051. Bash-Minifier is a
manifest-managed build dependency used only to derive the minified release flavor
under ADR-052.

## Build and Dependency Boundaries

Expand All @@ -90,22 +93,42 @@ Makefile before executing it.
Ordinary externally acquired build/development artifacts are declared in
`dependencies.txt` and synchronized by bashdeps under ADR-051. Do not add new
one-off download rules to Make for dependencies that fit the released bashdeps
contract.
contract. Current manifest-managed artifacts include the Bash Doxygen filter and
the commit-pinned Bash-Minifier input at `vendor/bash-minifier.bash`.

Preserve these target semantics:

- `make deps` may use the network and converges dependency state.
- `make deps-check` verifies existing dependency state without network access
or repair.
- `make build` does not bootstrap, synchronize, or verify external
dependencies.
dependencies, but it requires already-prepared Bash-Minifier state.
- A fresh checkout uses `make all` or `make deps` followed by `make build`.
- `make all` explicitly synchronizes dependencies before invoking `build`.
- `make docs` consumes already-prepared documentation dependency state and
does not acquire it implicitly.

`make build` produces six distribution files:

```text
dist/bootstrap.dev.bash
dist/bootstrap.bash
dist/bootstrap.min.bash
dist/bootstrap.dev.bash.256
dist/bootstrap.bash.256
dist/bootstrap.min.bash.256
```

The development artifact retains assembled source comments. The ordinary
`bootstrap.bash` artifact removes full-line comments while preserving the
shebang. The minified artifact is derived from that stripped artifact using the
prepared Bash-Minifier dependency. All three executable artifacts represent the
same runtime program and shall remain executable.

`vendor/` and `doc/reference/` are generated state and are excluded from source
control. `dist/bootstrap.bash` must remain functional without bashdeps,
`dependencies.txt`, or the vendor tree.
control. All three `dist/bootstrap*.bash` consumer artifacts must remain
functional without bashdeps, Bash-Minifier, `dependencies.txt`, or the vendor
tree after construction.

Treat `dependencies.txt` as data. Do not source or evaluate it as shell code.
The committed digest, rather than a filename or URL label, is authoritative for
Expand Down Expand Up @@ -172,9 +195,16 @@ When introducing new functionality:
- update examples or documentation when behavior changes.

Build/dependency changes should also exercise the applicable ADR-051 boundaries:
clean build behavior, explicit dependency synchronization, offline verification,
tamper detection, convergence, and runtime independence from generated vendor
state.
network-free build behavior, explicit dependency synchronization, offline
verification, tamper detection, convergence, and runtime independence from
generated vendor state.

Artifact-generation changes shall apply the observable behavior suite to all
three executable flavors under ADR-052. Tests should avoid assuming that release
metadata or executable statements occupy the same physical lines in the minified
artifact. Build-specific tests should verify all six expected files, executable
permissions, checksum validity, transformation lineage, and runtime independence
from `vendor/`.

A change is normally incomplete if the implementation changes but the
corresponding tests do not.
Expand All @@ -193,7 +223,8 @@ When practical:
- review the resulting diff;
- run formatting, linting, and tests;
- run `make deps` and `make deps-check` when dependency state is relevant;
- verify generated consumer artifacts remain functional without `vendor/`;
- verify all generated consumer artifacts remain functional without `vendor/`;
- verify every `.256` file matches its corresponding executable;
- verify documentation-only requests changed only documentation.

## Common Failure Modes
Expand All @@ -206,7 +237,10 @@ Avoid:
- inventing design rationale;
- changing public behavior unintentionally;
- reintroducing direct Makefile acquisition for manifest-managed dependencies;
- making `build`, `deps-check`, or `docs` silently repair dependency state.
- making `build`, `deps-check`, or `docs` silently repair dependency state;
- minifying maintained source files individually rather than the complete
assembled stripped artifact;
- treating the minified artifact as exempt from the ordinary behavior suite.

## Final Principle

Expand Down
Loading
Loading