Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
ec334c1
chore: files changed crates/template/examples/basic.rs,examples/basic…
senamakel Aug 21, 2026
911416d
chore(manifest): restructure Cargo.toml as a virtual workspace
senamakel Aug 21, 2026
dfeda40
chore(template-bus): update Cargo.toml with new dependency
senamakel Aug 21, 2026
452ef86
feat(template-bus): add greeting, names, and version modules
senamakel Aug 21, 2026
f919baf
fix(version): correct test assertion for version comparison
senamakel Aug 21, 2026
234ec1e
fix(version): handle missing version field in template parsing
senamakel Aug 21, 2026
69e57dc
chore(template): add missing Cargo.toml for the template crate
senamakel Aug 21, 2026
8a21d3e
fix(template): restore missing tinybus module files
senamakel Aug 21, 2026
bc663b5
chore(template): remove unused example files and simplify greeting mo…
senamakel Aug 21, 2026
e50aff0
fix(example): correct GitHub release verification example
senamakel Aug 21, 2026
8c6d3d9
chore(deps): rename rust-template to template and add template-bus de…
senamakel Aug 21, 2026
30f1afc
fix(template): convert method and interface comparisons to owned strings
senamakel Aug 21, 2026
dba78af
test(greeting): reformat assertions for readability
senamakel Aug 21, 2026
0e9c452
docs(template-bus): add README documentation for the crate
senamakel Aug 21, 2026
e5cf2d4
chore(deps): remove version pin on workspace-internal dependency
senamakel Aug 21, 2026
da89b36
fix(ci): update CI workflow to use latest actions
senamakel Aug 21, 2026
31730d5
chore(ci): pin third-party actions to commit SHAs and switch to works…
senamakel Aug 21, 2026
a609343
ci: switch GitHub Actions pins from commit SHAs to version tags
senamakel Aug 21, 2026
39f3e24
fix(ci): update source root and expand workspace coverage
senamakel Aug 21, 2026
f6af904
chore(docs): rename rust-template references to template
senamakel Aug 21, 2026
928a436
chore: files changed README.md
senamakel Aug 21, 2026
0ab379c
docs(AGENTS.md, tinybus_module/README.md): update project structure a…
senamakel Aug 21, 2026
2bdb476
chore(claude): allow cargo run with a package selector
senamakel Aug 21, 2026
3dc4594
chore(deny): allow wildcard paths for unpublished workspace crates
senamakel Aug 21, 2026
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
2 changes: 1 addition & 1 deletion .claude/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"Bash(cargo check:*)",
"Bash(cargo test:*)",
"Bash(cargo doc:*)",
"Bash(cargo run --example:*)",
"Bash(cargo run:*)",
"Bash(cargo tree:*)",
"Bash(cargo metadata:*)",
"Bash(cargo deny check:*)",
Expand Down
8 changes: 6 additions & 2 deletions .github/scripts/check-file-coverage.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@ set -euo pipefail
minimum="${1:-90}"
report="${2:-coverage.json}"
workspace_root="$(pwd -P)/"
source_root="${workspace_root}src/"
# Every crate lives under `crates/<package>/src/`, so one prefix covers the
# whole workspace. Vendored submodules and `worktrees/` sit outside it and are
# excluded by the same test.
source_root="${workspace_root}crates/"

cargo llvm-cov \
--locked \
--workspace \
--all-targets \
--all-features \
--json \
Expand All @@ -23,7 +27,7 @@ covered_files="$(jq --arg source_root "$source_root" '
' "$report")"

if [[ "$covered_files" -eq 0 ]]; then
echo "coverage report contains no files with executable lines under src/" >&2
echo "coverage report contains no files with executable lines under crates/" >&2
exit 1
fi

Expand Down
54 changes: 44 additions & 10 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ permissions:
contents: read

env:
# Lint levels live in `[lints]` in Cargo.toml so local and CI runs agree;
# don't add a blanket RUSTFLAGS here.
# Lint levels live in `[workspace.lints]` in the root Cargo.toml so local and
# CI runs agree; don't add a blanket RUSTFLAGS here.
CARGO_TERM_COLOR: always

jobs:
Expand All @@ -26,13 +26,15 @@ jobs:
# This job executes repository code (cargo build/test); don't persist
# the token in git config.
persist-credentials: false
submodules: true
submodules: recursive

- uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy

- uses: taiki-e/install-action@cargo-llvm-cov
- uses: taiki-e/install-action@v2

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

priority medium security uncertain

taiki-e/install-action is pinned to v2, which is mutable

A tag or branch can be repointed by whoever owns taiki-e, and the new code runs with this workflow's secrets. Pin to a full commit SHA and let Dependabot bump it.

[RULE] unpinned-action ·

with:
tool: cargo-llvm-cov

- uses: Swatinem/rust-cache@v2

Expand All @@ -51,12 +53,41 @@ jobs:
- name: Test default features
run: cargo test

# `cargo build --all-targets` only *compiles* an example. `AGENTS.md`
# promises `cargo run -p template --example basic` works, and a compiled
# example can still fail on its first line.
- name: Run the bundled example
run: cargo run -p template --example basic

# `crates/template-bus` exists so a host can name the payload types
# without compiling the module. That promise is invisible in a diff,
# because a forbidden dependency arrives transitively through a feature
# someone enabled one crate away — so it is asserted rather than
# documented.
#
# The FORWARD form is required. `cargo tree -i <crate> -p template-bus`
# discards the `-p` scope, prints the whole-workspace inverse tree, and
# exits 0 looking clean even when this crate is the one at fault.
- name: Assert the contract crate stays transport-free
run: |
set -euo pipefail
forbidden="$(cargo tree -p template-bus -e normal,build --prefix none \
| grep -Ei 'tinybus|tokio|reqwest|ureq|hyper|rusqlite|git2' || true)"
if [ -n "$forbidden" ]; then
echo "template-bus pulled in a dependency its manifest forbids:" >&2
echo "$forbidden" >&2
echo >&2
echo "The contract is what a host compiles against. It must stay free" >&2
echo "of transports, async runtimes, HTTP clients and native libraries." >&2
exit 1
fi

- name: Require 90% line coverage in every source file
run: .github/scripts/check-file-coverage.sh 90 coverage.json

- name: Upload coverage report
if: ${{ always() }}
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: coverage-json
path: coverage.json
Expand All @@ -69,7 +100,7 @@ jobs:
- uses: actions/checkout@v7
with:
persist-credentials: false
submodules: true
submodules: recursive

- uses: dtolnay/rust-toolchain@stable

Expand All @@ -87,16 +118,19 @@ jobs:
- uses: actions/checkout@v7
with:
persist-credentials: false
submodules: true
submodules: recursive

# `rust-version` is inherited from `[workspace.package]`, so every member
# reports the same value. Read it off the package the module ships as
# rather than off `packages[0]`, whose order cargo does not promise.
- name: Read rust-version from Cargo.toml
id: msrv
run: |
set -euo pipefail
msrv="$(cargo metadata --format-version 1 --no-deps \
| jq -r '.packages[0].rust_version')"
| jq -r '.packages[] | select(.name == "template") | .rust_version')"
if [[ -z "$msrv" || "$msrv" == "null" ]]; then
echo "package.rust-version is not set in Cargo.toml" >&2
echo "workspace.package.rust-version is not set in Cargo.toml" >&2
exit 1
fi
echo "version=$msrv" >> "$GITHUB_OUTPUT"
Expand All @@ -117,7 +151,7 @@ jobs:
- uses: actions/checkout@v7
with:
persist-credentials: false
submodules: true
submodules: recursive

- name: Check advisories, licenses, bans, and sources
uses: EmbarkStudios/cargo-deny-action@v2
Expand Down
64 changes: 43 additions & 21 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ concurrency:
permissions:
contents: write

env:
# The workspace member that ships as the loadable module. Its package name is
# the artifact name and the library name; `crates/template-bus` rides along on
# the same inherited version and is not packaged separately.
RELEASE_PACKAGE: template

jobs:
prepare:
name: Prepare release
Expand All @@ -33,13 +39,15 @@ jobs:
- uses: actions/checkout@v7
with:
fetch-depth: 0
submodules: true
submodules: recursive

- uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy

- uses: taiki-e/install-action@cargo-llvm-cov
- uses: taiki-e/install-action@v2

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

priority medium security uncertain

taiki-e/install-action is pinned to v2, which is mutable

A tag or branch can be repointed by whoever owns taiki-e, and the new code runs with this workflow's secrets. Pin to a full commit SHA and let Dependabot bump it.

[RULE] unpinned-action ·

with:
tool: cargo-llvm-cov

- uses: Swatinem/rust-cache@v2

Expand Down Expand Up @@ -70,8 +78,10 @@ jobs:
set -euo pipefail

metadata="$(cargo metadata --format-version 1 --no-deps)"
crate_name="$(jq -r '.packages[0].name' <<< "$metadata")"
current_version="$(jq -r '.packages[0].version' <<< "$metadata")"
crate_name="$(jq -r --arg name "$RELEASE_PACKAGE" \
'.packages[] | select(.name == $name) | .name' <<< "$metadata")"
current_version="$(jq -r --arg name "$RELEASE_PACKAGE" \
'.packages[] | select(.name == $name) | .version' <<< "$metadata")"
if [[ -z "$crate_name" || "$crate_name" == "null" ]]; then
echo "Could not resolve the crate name" >&2
exit 1
Expand Down Expand Up @@ -114,7 +124,7 @@ jobs:
fi
tagged_version="$(
git show "${tag}:Cargo.toml" \
| sed -n 's/^version = "\([^"]*\)"/\1/p' \
| sed -n '/^\[workspace\.package\]/,/^\[/ s/^version = "\([^"]*\)"/\1/p' \
| head -n 1
)"
if [[ "$tagged_version" != "$current_version" ]]; then
Expand All @@ -140,8 +150,20 @@ jobs:
NEXT_VERSION: ${{ steps.version.outputs.next_version }}
run: |
set -euo pipefail
perl -0pi -e 's/(\[package\][\s\S]*?\nversion = ")[^"]+(")/$1$ENV{NEXT_VERSION}$2/' Cargo.toml
cargo update -p "$CRATE_NAME" --precise "$NEXT_VERSION"
# One version for the whole workspace: every member inherits it with
# `version.workspace = true`, so this is the only edit needed.
perl -0pi -e 's/(\[workspace\.package\][\s\S]*?\nversion = ")[^"]+(")/$1$ENV{NEXT_VERSION}$2/' Cargo.toml
# `--workspace` re-resolves the local packages only, which is what a
# version bump changes. `-p <name> --precise` cannot express "and the
# other member moved too".
cargo update --workspace
released="$(cargo metadata --format-version 1 --no-deps \
| jq -r --arg name "$CRATE_NAME" \
'.packages[] | select(.name == $name) | .version')"
if [[ "$released" != "$NEXT_VERSION" ]]; then
echo "version bump did not take: expected ${NEXT_VERSION}, got ${released}" >&2
exit 1
fi

- name: Commit version bump and tag
if: ${{ inputs.bump != 'current' }}
Expand Down Expand Up @@ -203,7 +225,7 @@ jobs:
with:
ref: ${{ needs.prepare.outputs.tag }}
persist-credentials: false
submodules: true
submodules: recursive

- uses: dtolnay/rust-toolchain@stable

Expand All @@ -222,7 +244,7 @@ jobs:
fi

- name: Build installable module
run: cargo build --locked --release --lib
run: cargo build --locked --release --lib --package ${{ env.RELEASE_PACKAGE }}

- name: Verify Unix module through TinyBus loader
if: ${{ runner.os != 'Windows' }}
Expand All @@ -237,7 +259,7 @@ jobs:
macOS) module="target/release/lib${library_name}.dylib" ;;
*) echo "unsupported Unix runner: ${RUNNER_OS}" >&2; exit 1 ;;
esac
cargo run --locked --example verify_module -- "$module"
cargo run --locked --package template --example verify_module -- "$module"

- name: Verify Windows module through TinyBus loader
if: ${{ runner.os == 'Windows' }}
Expand All @@ -248,7 +270,7 @@ jobs:
$ErrorActionPreference = 'Stop'
$libraryName = $env:CRATE_NAME.Replace('-', '_')
$module = "target/release/$libraryName.dll"
$verifyRoot = Join-Path $env:RUNNER_TEMP 'rust-template-module-verify'
$verifyRoot = Join-Path $env:RUNNER_TEMP 'template-module-verify'
New-Item -ItemType Directory -Force $verifyRoot | Out-Null

$identity = [System.Security.Principal.WindowsIdentity]::GetCurrent()
Expand Down Expand Up @@ -278,7 +300,7 @@ jobs:

$verifiedModule = Join-Path $verifyRoot "$libraryName.dll"
Copy-Item -LiteralPath $module -Destination $verifiedModule
cargo run --locked --example verify_module -- $verifiedModule
cargo run --locked --package template --example verify_module -- $verifiedModule

- name: Assemble Unix module package
if: ${{ runner.os != 'Windows' }}
Expand Down Expand Up @@ -353,15 +375,15 @@ jobs:

- name: Upload Unix package
if: ${{ runner.os != 'Windows' }}
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: ${{ needs.prepare.outputs.crate_name }}-${{ matrix.id }}
path: ${{ steps.unix_package.outputs.archive }}
if-no-files-found: error

- name: Upload Windows package
if: ${{ runner.os == 'Windows' }}
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: ${{ needs.prepare.outputs.crate_name }}-${{ matrix.id }}
path: ${{ steps.windows_package.outputs.archive }}
Expand Down Expand Up @@ -414,7 +436,7 @@ jobs:
with:
ref: ${{ needs.prepare.outputs.tag }}
persist-credentials: false
submodules: true
submodules: recursive

- uses: dtolnay/rust-toolchain@stable

Expand All @@ -430,7 +452,7 @@ jobs:
fi

- name: Build installable module
run: cargo build --locked --release --lib
run: cargo build --locked --release --lib --package ${{ env.RELEASE_PACKAGE }}

- name: Verify module through TinyBus loader
env:
Expand All @@ -441,7 +463,7 @@ jobs:
verify_root="/opt/${CRATE_NAME}-module-verify"
install -d -m 700 "$verify_root"
install -m 755 "target/release/lib${library_name}.so" "$verify_root/"
cargo run --locked --example verify_module -- \
cargo run --locked --package template --example verify_module -- \
"$verify_root/lib${library_name}.so"

- name: Assemble distribution module package
Expand Down Expand Up @@ -475,7 +497,7 @@ jobs:
echo "archive=dist/${package_name}.tar.gz" >> "$GITHUB_OUTPUT"

- name: Upload distribution package
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: ${{ needs.prepare.outputs.crate_name }}-${{ matrix.id }}
path: ${{ steps.package.outputs.archive }}
Expand All @@ -493,13 +515,13 @@ jobs:
with:
ref: ${{ needs.prepare.outputs.tag }}
persist-credentials: false
submodules: true
submodules: recursive

- uses: dtolnay/rust-toolchain@stable

- uses: Swatinem/rust-cache@v2

- uses: actions/download-artifact@v4
- uses: actions/download-artifact@v8
with:
pattern: '*'
path: release-assets
Expand Down Expand Up @@ -565,5 +587,5 @@ jobs:
cargo run --manifest-path vendor/tinybus/Cargo.toml --locked \
--package tinybus --all-features --example github_module_host -- \
"$release_url" "$archive" "$sha256"
cargo run --locked --example verify_github_release -- \
cargo run --locked --package template --example verify_github_release -- \
"$release_url" "$archive" "$sha256"
Loading