Dagger
Search

tapesctl

Package main provides reproducible lint, test, and cross-platform release
builds locally and in GitHub Actions.

tapesctl is a pure-Rust CLI (no Apple frameworks, no C deps), so the
Linux→macOS cross-compile uses `cargo-zigbuild` — zig bundles the macOS
libSystem stubs, so no Apple SDK and no osxcross build are needed (unlike a
workspace with Apple-framework code, which forces the heavier osxcross path).

To wire up after first checkout:

cd tapesctl
dagger develop # regenerates go.mod + dagger codegen
dagger call lint # cargo fmt --check + clippy
dagger call test # cargo test --workspace
dagger call build-release export --path ./build

Installation

dagger install github.com/papercomputeco/tapesctl@3288b318cafd67c1b1caa8f7b2f78b28576a3983

Entrypoint

Return Type
Tapesctl !
Arguments
NameTypeDefault ValueDescription
sourceDirectory -Project source directory.
Example
dagger -m github.com/papercomputeco/tapesctl@3288b318cafd67c1b1caa8f7b2f78b28576a3983 call \
func (m *MyModule) Example() *dagger.Tapesctl  {
	return dag.
			Tapesctl()
}
@function
def example() -> dagger.Tapesctl:
	return (
		dag.tapesctl()
	)
@func()
example(): Tapesctl {
	return dag
		.tapesctl()
}

Types

Tapesctl 🔗

Tapesctl is the main module for the tapesctl CI/CD pipeline.

build() 🔗

Build cross-compiles the tapesctl binary for all supported platforms using cargo-zigbuild. Linux targets are static musl builds (curl-and-run, like the old CGO_ENABLED=0 Go binaries); macOS targets link against zig’s bundled libSystem stubs — no Apple SDK required.

The identity arguments are what make a released binary able to name itself. They are optional because this function also serves plain CI builds, which have no release to name: the source arrives here without a .git directory (see the module’s +ignore), so an unstamped build genuinely knows nothing about its own provenance and says so rather than guessing.

Return Type
Directory !
Arguments
NameTypeDefault ValueDescription
versionString ""

Release tag or channel name to stamp into the binaries, for example v1.0.0 or nightly.

commitString ""

Full commit the binaries are built from.

dateString ""

RFC 3339 timestamp of the build.

Example
dagger -m github.com/papercomputeco/tapesctl@3288b318cafd67c1b1caa8f7b2f78b28576a3983 call \
 build
func (m *MyModule) Example() *dagger.Directory  {
	return dag.
			Tapesctl().
			Build()
}
@function
def example() -> dagger.Directory:
	return (
		dag.tapesctl()
		.build()
	)
@func()
example(): Directory {
	return dag
		.tapesctl()
		.build()
}

buildRelease() 🔗

BuildRelease compiles release binaries and adds SHA256 checksums.

Return Type
Directory !
Arguments
NameTypeDefault ValueDescription
versionString ""

Release tag or channel name to stamp into the binaries, for example v1.0.0 or nightly.

commitString ""

Full commit the binaries are built from.

dateString ""

RFC 3339 timestamp of the build.

Example
dagger -m github.com/papercomputeco/tapesctl@3288b318cafd67c1b1caa8f7b2f78b28576a3983 call \
 build-release
func (m *MyModule) Example() *dagger.Directory  {
	return dag.
			Tapesctl().
			Buildrelease()
}
@function
def example() -> dagger.Directory:
	return (
		dag.tapesctl()
		.buildrelease()
	)
@func()
example(): Directory {
	return dag
		.tapesctl()
		.buildRelease()
}

lint() 🔗

Lint runs cargo fmt --all -- --check and cargo clippy --workspace --all-targets -- -D warnings. Both are the same gates make lint runs locally, so a green Dagger lint matches a green local lint.

Return Type
String !
Example
dagger -m github.com/papercomputeco/tapesctl@3288b318cafd67c1b1caa8f7b2f78b28576a3983 call \
 lint
func (m *MyModule) Example(ctx context.Context) string  {
	return dag.
			Tapesctl().
			Lint(ctx)
}
@function
async def example() -> str:
	return await (
		dag.tapesctl()
		.lint()
	)
@func()
async example(): Promise<string> {
	return dag
		.tapesctl()
		.lint()
}

nightly() 🔗

Nightly builds and uploads nightly artifacts.

Return Type
Directory !
Arguments
NameTypeDefault ValueDescription
commitString ""

Full commit the nightly is built from. It is what distinguishes one nightly from the next, since they all carry the same version name.

endpointSecret !-

Bucket endpoint URL.

bucketSecret !-

Bucket name.

accessKeyIdSecret !-

Bucket access key ID.

secretAccessKeySecret !-

Bucket secret access key.

Example
dagger -m github.com/papercomputeco/tapesctl@3288b318cafd67c1b1caa8f7b2f78b28576a3983 call \
 nightly --endpoint env:MYSECRET --bucket env:MYSECRET --access-key-id env:MYSECRET --secret-access-key env:MYSECRET
func (m *MyModule) Example(endpoint *dagger.Secret, bucket *dagger.Secret, accessKeyId *dagger.Secret, secretAccessKey *dagger.Secret) *dagger.Directory  {
	return dag.
			Tapesctl().
			Nightly(endpoint, bucket, accessKeyId, secretAccessKey)
}
@function
def example(endpoint: dagger.Secret, bucket: dagger.Secret, accesskeyid: dagger.Secret, secretaccesskey: dagger.Secret) -> dagger.Directory:
	return (
		dag.tapesctl()
		.nightly(endpoint, bucket, accesskeyid, secretaccesskey)
	)
@func()
example(endpoint: Secret, bucket: Secret, accessKeyId: Secret, secretAccessKey: Secret): Directory {
	return dag
		.tapesctl()
		.nightly(endpoint, bucket, accessKeyId, secretAccessKey)
}

releaseLatest() 🔗

ReleaseLatest builds and uploads versioned and latest release artifacts.

Return Type
Directory !
Arguments
NameTypeDefault ValueDescription
versionString !-

Version string, for example v1.0.0. Names the upload prefix and is stamped into the binaries, so a released tapesctl reports the release it was downloaded from.

Written without backquotes on purpose: the help renderer takes a backquoted word as the flag’s placeholder, so a quoted command name here would be printed where the argument’s type belongs.

commitString ""

Full commit the release is built from.

endpointSecret !-

Bucket endpoint URL.

bucketSecret !-

Bucket name.

accessKeyIdSecret !-

Bucket access key ID.

secretAccessKeySecret !-

Bucket secret access key.

Example
dagger -m github.com/papercomputeco/tapesctl@3288b318cafd67c1b1caa8f7b2f78b28576a3983 call \
 release-latest --version string --endpoint env:MYSECRET --bucket env:MYSECRET --access-key-id env:MYSECRET --secret-access-key env:MYSECRET
func (m *MyModule) Example(version string, endpoint *dagger.Secret, bucket *dagger.Secret, accessKeyId *dagger.Secret, secretAccessKey *dagger.Secret) *dagger.Directory  {
	return dag.
			Tapesctl().
			Releaselatest(version, endpoint, bucket, accessKeyId, secretAccessKey)
}
@function
def example(version: str, endpoint: dagger.Secret, bucket: dagger.Secret, accesskeyid: dagger.Secret, secretaccesskey: dagger.Secret) -> dagger.Directory:
	return (
		dag.tapesctl()
		.releaselatest(version, endpoint, bucket, accesskeyid, secretaccesskey)
	)
@func()
example(version: string, endpoint: Secret, bucket: Secret, accessKeyId: Secret, secretAccessKey: Secret): Directory {
	return dag
		.tapesctl()
		.releaseLatest(version, endpoint, bucket, accessKeyId, secretAccessKey)
}

test() 🔗

Test runs the workspace unit tests. --locked fails if Cargo.lock is stale, which subsumes the go.mod-tidy check the Go pipeline had.

Return Type
String !
Example
dagger -m github.com/papercomputeco/tapesctl@3288b318cafd67c1b1caa8f7b2f78b28576a3983 call \
 test
func (m *MyModule) Example(ctx context.Context) string  {
	return dag.
			Tapesctl().
			Test(ctx)
}
@function
async def example() -> str:
	return await (
		dag.tapesctl()
		.test()
	)
@func()
async example(): Promise<string> {
	return dag
		.tapesctl()
		.test()
}

uploadInstallSh() 🔗

UploadInstallSh uploads the install script under the tapesctl namespace.

Return Type
Void !
Arguments
NameTypeDefault ValueDescription
endpointSecret !-

Bucket endpoint URL.

bucketSecret !-

Bucket name.

accessKeyIdSecret !-

Bucket access key ID.

secretAccessKeySecret !-

Bucket secret access key.

Example
dagger -m github.com/papercomputeco/tapesctl@3288b318cafd67c1b1caa8f7b2f78b28576a3983 call \
 upload-install-sh --endpoint env:MYSECRET --bucket env:MYSECRET --access-key-id env:MYSECRET --secret-access-key env:MYSECRET
func (m *MyModule) Example(ctx context.Context, endpoint *dagger.Secret, bucket *dagger.Secret, accessKeyId *dagger.Secret, secretAccessKey *dagger.Secret)   {
	return dag.
			Tapesctl().
			Uploadinstallsh(ctx, endpoint, bucket, accessKeyId, secretAccessKey)
}
@function
async def example(endpoint: dagger.Secret, bucket: dagger.Secret, accesskeyid: dagger.Secret, secretaccesskey: dagger.Secret) -> None:
	return await (
		dag.tapesctl()
		.uploadinstallsh(endpoint, bucket, accesskeyid, secretaccesskey)
	)
@func()
async example(endpoint: Secret, bucket: Secret, accessKeyId: Secret, secretAccessKey: Secret): Promise<void> {
	return dag
		.tapesctl()
		.uploadInstallSh(endpoint, bucket, accessKeyId, secretAccessKey)
}