tapes
Package main provides reproducible builds and tests locally and in GitHub actions.It is the main harness for handling nearly all dev operations.
Installation
dagger install github.com/papercomputeco/tapes@e4ebc5a5044378b2ce173841c14b1778229e9f5fEntrypoint
Return Type
Tapes !Arguments
| Name | Type | Default Value | Description |
|---|---|---|---|
| source | Directory | - | Project source directory. |
Example
dagger -m github.com/papercomputeco/tapes@e4ebc5a5044378b2ce173841c14b1778229e9f5f call \
func (m *MyModule) Example() *dagger.Tapes {
return dag.
Tapes()
}@function
def example() -> dagger.Tapes:
return (
dag.tapes()
)@func()
example(): Tapes {
return dag
.tapes()
}Types
Tapes 🔗
Tapes is the main module for the Tapes CI/CD pipeline
build() 🔗
Build and return directory of go binaries for all platforms. Linux targets are cross-compiled using Zig as the C toolchain. Darwin targets are cross-compiled using osxcross (macOS SDK
Return Type
Directory !Arguments
| Name | Type | Default Value | Description |
|---|---|---|---|
| ldflags | String | "-s -w" | Linker flags for go build |
Example
dagger -m github.com/papercomputeco/tapes@e4ebc5a5044378b2ce173841c14b1778229e9f5f call \
buildfunc (m *MyModule) Example() *dagger.Directory {
return dag.
Tapes().
Build()
}@function
def example() -> dagger.Directory:
return (
dag.tapes()
.build()
)@func()
example(): Directory {
return dag
.tapes()
.build()
}buildRelease() 🔗
BuildRelease compiles versioned release binaries with embedded version info
Return Type
Directory !Arguments
| Name | Type | Default Value | Description |
|---|---|---|---|
| version | String ! | - | Version string of build |
| commit | String ! | - | Git commit SHA of build |
Example
dagger -m github.com/papercomputeco/tapes@e4ebc5a5044378b2ce173841c14b1778229e9f5f call \
build-release --version string --commit stringfunc (m *MyModule) Example(version string, commit string) *dagger.Directory {
return dag.
Tapes().
BuildRelease(version, commit)
}@function
def example(version: str, commit: str) -> dagger.Directory:
return (
dag.tapes()
.build_release(version, commit)
)@func()
example(version: string, commit: string): Directory {
return dag
.tapes()
.buildRelease(version, commit)
}checkGenerate() 🔗
CheckGenerate verifies that generated code (e.g. ent) is up to date by running go generate and diffing the result against the committed files.
Return Type
String ! Example
dagger -m github.com/papercomputeco/tapes@e4ebc5a5044378b2ce173841c14b1778229e9f5f call \
check-generatefunc (m *MyModule) Example(ctx context.Context) string {
return dag.
Tapes().
CheckGenerate(ctx)
}@function
async def example() -> str:
return await (
dag.tapes()
.check_generate()
)@func()
async example(): Promise<string> {
return dag
.tapes()
.checkGenerate()
}checkGoModTidy() 🔗
CheckGoModTidy runs “go mod tidy” and fails if it produces any changes to go.mod or go.sum, indicating that the caller forgot to tidy before committing.
Return Type
String ! Example
dagger -m github.com/papercomputeco/tapes@e4ebc5a5044378b2ce173841c14b1778229e9f5f call \
check-go-mod-tidyfunc (m *MyModule) Example(ctx context.Context) string {
return dag.
Tapes().
CheckGoModTidy(ctx)
}@function
async def example() -> str:
return await (
dag.tapes()
.check_go_mod_tidy()
)@func()
async example(): Promise<string> {
return dag
.tapes()
.checkGoModTidy()
}checkLint() 🔗
CheckLint runs golangci-lint against the tapes source code without applying fixes.
Return Type
String ! Example
dagger -m github.com/papercomputeco/tapes@e4ebc5a5044378b2ce173841c14b1778229e9f5f call \
check-lintfunc (m *MyModule) Example(ctx context.Context) string {
return dag.
Tapes().
CheckLint(ctx)
}@function
async def example() -> str:
return await (
dag.tapes()
.check_lint()
)@func()
async example(): Promise<string> {
return dag
.tapes()
.checkLint()
}fixLint() 🔗
FixLint runs golangci-lint against the tapes source code with –fix, applying automatic fixes where possible, and returns the modified source directory.
Return Type
Directory ! Example
dagger -m github.com/papercomputeco/tapes@e4ebc5a5044378b2ce173841c14b1778229e9f5f call \
fix-lintfunc (m *MyModule) Example() *dagger.Directory {
return dag.
Tapes().
FixLint()
}@function
def example() -> dagger.Directory:
return (
dag.tapes()
.fix_lint()
)@func()
example(): Directory {
return dag
.tapes()
.fixLint()
}kafkaStack() 🔗
KafkaStack starts Kafka, creates the e2e topic, and returns the Kafka UI dashboard service. Use “dagger call kafka-stack up” to bring up the full stack.
Return Type
Service ! Example
dagger -m github.com/papercomputeco/tapes@e4ebc5a5044378b2ce173841c14b1778229e9f5f call \
kafka-stackfunc (m *MyModule) Example() *dagger.Service {
return dag.
Tapes().
KafkaStack()
}@function
def example() -> dagger.Service:
return (
dag.tapes()
.kafka_stack()
)@func()
example(): Service {
return dag
.tapes()
.kafkaStack()
}nightly() 🔗
Nightly builds and uploads nightly artifacts. If container registry credentials are provided, it also builds and publishes multi-arch container images tagged with “nightly” and “nightly-YYYY-MM-DD”.
Return Type
Directory !Arguments
| Name | Type | Default Value | Description |
|---|---|---|---|
| commit | String ! | - | Git commit SHA |
| endpoint | Secret ! | - | Bucket endpoint URL |
| bucket | Secret ! | - | Bucket name |
| accessKeyId | Secret ! | - | Bucket access key ID |
| secretAccessKey | Secret ! | - | Bucket secret access key |
| registry | String ! | - | Container registry address (e.g., "ghcr.io") |
| registryUsername | String ! | - | Container registry username / namespace |
| registryPassword | Secret ! | - | Container registry password or token |
Example
dagger -m github.com/papercomputeco/tapes@e4ebc5a5044378b2ce173841c14b1778229e9f5f call \
nightly --commit string --endpoint env:MYSECRET --bucket env:MYSECRET --access-key-id env:MYSECRET --secret-access-key env:MYSECRET --registry string --registry-username string --registry-password env:MYSECRETfunc (m *MyModule) Example(commit string, endpoint *dagger.Secret, bucket *dagger.Secret, accessKeyId *dagger.Secret, secretAccessKey *dagger.Secret, registry string, registryUsername string, registryPassword *dagger.Secret) *dagger.Directory {
return dag.
Tapes().
Nightly(commit, endpoint, bucket, accessKeyId, secretAccessKey, registry, registryUsername, registryPassword)
}@function
def example(commit: str, endpoint: dagger.Secret, bucket: dagger.Secret, access_key_id: dagger.Secret, secret_access_key: dagger.Secret, registry: str, registry_username: str, registry_password: dagger.Secret) -> dagger.Directory:
return (
dag.tapes()
.nightly(commit, endpoint, bucket, access_key_id, secret_access_key, registry, registry_username, registry_password)
)@func()
example(commit: string, endpoint: Secret, bucket: Secret, accessKeyId: Secret, secretAccessKey: Secret, registry: string, registryUsername: string, registryPassword: Secret): Directory {
return dag
.tapes()
.nightly(commit, endpoint, bucket, accessKeyId, secretAccessKey, registry, registryUsername, registryPassword)
}ollamaPullModel() 🔗
ollamaPullModel pulls a given Ollama model in a sidecare container.
Return Type
String !Arguments
| Name | Type | Default Value | Description |
|---|---|---|---|
| model | String ! | - | No description provided |
| ollamaSvc | Service ! | - | No description provided |
Example
dagger -m github.com/papercomputeco/tapes@e4ebc5a5044378b2ce173841c14b1778229e9f5f call \
ollama-pull-model --model string --ollama-svc PROTOCOL://HOST:PORTfunc (m *MyModule) Example(ctx context.Context, model string, ollamaSvc *dagger.Service) string {
return dag.
Tapes().
OllamaPullModel(ctx, model, ollamaSvc)
}@function
async def example(model: str, ollama_svc: dagger.Service) -> str:
return await (
dag.tapes()
.ollama_pull_model(model, ollama_svc)
)@func()
async example(model: string, ollamaSvc: Service): Promise<string> {
return dag
.tapes()
.ollamaPullModel(model, ollamaSvc)
}ollamaService() 🔗
OllamaService provides an Ollama ready to run service. This service uses a cache volume so models are only pulled once across runs. Pre-create the models/manifests directory tree so Ollama’s serve command doesn’t crash on a fresh (empty) cache volume.
Return Type
Service ! Example
dagger -m github.com/papercomputeco/tapes@e4ebc5a5044378b2ce173841c14b1778229e9f5f call \
ollama-servicefunc (m *MyModule) Example() *dagger.Service {
return dag.
Tapes().
OllamaService()
}@function
def example() -> dagger.Service:
return (
dag.tapes()
.ollama_service()
)@func()
example(): Service {
return dag
.tapes()
.ollamaService()
}ollamaStack() 🔗
Return Type
Service ! Example
dagger -m github.com/papercomputeco/tapes@e4ebc5a5044378b2ce173841c14b1778229e9f5f call \
ollama-stackfunc (m *MyModule) Example() *dagger.Service {
return dag.
Tapes().
OllamaStack()
}@function
def example() -> dagger.Service:
return (
dag.tapes()
.ollama_stack()
)@func()
example(): Service {
return dag
.tapes()
.ollamaStack()
}postgresService() 🔗
PostgresService provides a ready to run postgres service with “tapes” user, password, and db
Return Type
Service ! Example
dagger -m github.com/papercomputeco/tapes@e4ebc5a5044378b2ce173841c14b1778229e9f5f call \
postgres-servicefunc (m *MyModule) Example() *dagger.Service {
return dag.
Tapes().
PostgresService()
}@function
def example() -> dagger.Service:
return (
dag.tapes()
.postgres_service()
)@func()
example(): Service {
return dag
.tapes()
.postgresService()
}publishContainers() 🔗
PublishContainers builds multi-arch container images for all tapes binaries and publishes them to the specified container registry.
Each binary produces a multi-arch image (linux/amd64 + linux/arm64) tagged with all provided tags.
Image naming convention: //: For example: ghcr.io/papercomputeco/tapes:v1.0.0
Return Type
[String ! ] !Arguments
| Name | Type | Default Value | Description |
|---|---|---|---|
| registry | String ! | - | Container registry address (e.g., "ghcr.io", "docker.io") |
| username | String ! | - | Registry username / namespace (e.g., "papercomputeco") |
| password | Secret ! | - | Registry password or token |
| tags | [String ! ] ! | - | Image tags to apply (e.g., ["v1.0.0", "latest"]) |
| version | String ! | - | Version string for ldflags |
| commit | String ! | - | Git commit SHA for ldflags |
Example
dagger -m github.com/papercomputeco/tapes@e4ebc5a5044378b2ce173841c14b1778229e9f5f call \
publish-containers --registry string --username string --password env:MYSECRET --tags string1 --tags string2 --version string --commit stringfunc (m *MyModule) Example(ctx context.Context, registry string, username string, password *dagger.Secret, tags []string, version string, commit string) []string {
return dag.
Tapes().
PublishContainers(ctx, registry, username, password, tags, version, commit)
}@function
async def example(registry: str, username: str, password: dagger.Secret, tags: List[str], version: str, commit: str) -> List[str]:
return await (
dag.tapes()
.publish_containers(registry, username, password, tags, version, commit)
)@func()
async example(registry: string, username: string, password: Secret, tags: string[], version: string, commit: string): Promise<string[]> {
return dag
.tapes()
.publishContainers(registry, username, password, tags, version, commit)
}releaseLatest() 🔗
Release builds release binaries and uploads to bucket. If container registry credentials are provided, it also builds and publishes multi-arch container images tagged with the version and “latest”.
Return Type
Directory !Arguments
| Name | Type | Default Value | Description |
|---|---|---|---|
| version | String ! | - | Version string (e.g., "v1.0.0") |
| commit | String ! | - | Git commit SHA |
| endpoint | Secret ! | - | Bucket endpoint URL |
| bucket | Secret ! | - | Bucket name |
| accessKeyId | Secret ! | - | Bucket access key ID |
| secretAccessKey | Secret ! | - | Bucket secret access key |
| registry | String ! | - | Container registry address (e.g., "ghcr.io") |
| registryUsername | String ! | - | Container registry username / namespace |
| registryPassword | Secret ! | - | Container registry password or token |
Example
dagger -m github.com/papercomputeco/tapes@e4ebc5a5044378b2ce173841c14b1778229e9f5f call \
release-latest --version string --commit string --endpoint env:MYSECRET --bucket env:MYSECRET --access-key-id env:MYSECRET --secret-access-key env:MYSECRET --registry string --registry-username string --registry-password env:MYSECRETfunc (m *MyModule) Example(version string, commit string, endpoint *dagger.Secret, bucket *dagger.Secret, accessKeyId *dagger.Secret, secretAccessKey *dagger.Secret, registry string, registryUsername string, registryPassword *dagger.Secret) *dagger.Directory {
return dag.
Tapes().
ReleaseLatest(version, commit, endpoint, bucket, accessKeyId, secretAccessKey, registry, registryUsername, registryPassword)
}@function
def example(version: str, commit: str, endpoint: dagger.Secret, bucket: dagger.Secret, access_key_id: dagger.Secret, secret_access_key: dagger.Secret, registry: str, registry_username: str, registry_password: dagger.Secret) -> dagger.Directory:
return (
dag.tapes()
.release_latest(version, commit, endpoint, bucket, access_key_id, secret_access_key, registry, registry_username, registry_password)
)@func()
example(version: string, commit: string, endpoint: Secret, bucket: Secret, accessKeyId: Secret, secretAccessKey: Secret, registry: string, registryUsername: string, registryPassword: Secret): Directory {
return dag
.tapes()
.releaseLatest(version, commit, endpoint, bucket, accessKeyId, secretAccessKey, registry, registryUsername, registryPassword)
}test() 🔗
Test runs the tapes unit tests via “go test”
Return Type
String ! Example
dagger -m github.com/papercomputeco/tapes@e4ebc5a5044378b2ce173841c14b1778229e9f5f call \
testfunc (m *MyModule) Example(ctx context.Context) string {
return dag.
Tapes().
Test(ctx)
}@function
async def example() -> str:
return await (
dag.tapes()
.test()
)@func()
async example(): Promise<string> {
return dag
.tapes()
.test()
}testE2E() 🔗
TestE2E runs end-to-end tests against Postgres and Ollama services.
It stands up a PostgreSQL database and an Ollama LLM service, builds the tapes binary, runs the proxy and API as Dagger services backed by Postgres, and uses hurl to verify the full pipeline.
Return Type
String ! Example
dagger -m github.com/papercomputeco/tapes@e4ebc5a5044378b2ce173841c14b1778229e9f5f call \
test-e-2-efunc (m *MyModule) Example(ctx context.Context) string {
return dag.
Tapes().
TestE2E(ctx)
}@function
async def example() -> str:
return await (
dag.tapes()
.test_e2_e()
)@func()
async example(): Promise<string> {
return dag
.tapes()
.testE2E()
}testKafkaE2E() 🔗
TestKafkaE2E runs the opt-in proxy Kafka e2e test suite against a local Confluent Local Kafka service.
Return Type
String ! Example
dagger -m github.com/papercomputeco/tapes@e4ebc5a5044378b2ce173841c14b1778229e9f5f call \
test-kafka-e-2-efunc (m *MyModule) Example(ctx context.Context) string {
return dag.
Tapes().
TestKafkaE2E(ctx)
}@function
async def example() -> str:
return await (
dag.tapes()
.test_kafka_e2_e()
)@func()
async example(): Promise<string> {
return dag
.tapes()
.testKafkaE2E()
}uploadInstallSh() 🔗
UploadInstallSh uploads the install.sh script to the artifacts bucket
Return Type
Void !Arguments
| Name | Type | Default Value | Description |
|---|---|---|---|
| endpoint | Secret ! | - | Bucket endpoint URL |
| bucket | Secret ! | - | Bucket name |
| accessKeyId | Secret ! | - | Bucket access key ID |
| secretAccessKey | Secret ! | - | Bucket secret access key |
Example
dagger -m github.com/papercomputeco/tapes@e4ebc5a5044378b2ce173841c14b1778229e9f5f call \
upload-install-sh --endpoint env:MYSECRET --bucket env:MYSECRET --access-key-id env:MYSECRET --secret-access-key env:MYSECRETfunc (m *MyModule) Example(ctx context.Context, endpoint *dagger.Secret, bucket *dagger.Secret, accessKeyId *dagger.Secret, secretAccessKey *dagger.Secret) {
return dag.
Tapes().
UploadInstallSh(ctx, endpoint, bucket, accessKeyId, secretAccessKey)
}@function
async def example(endpoint: dagger.Secret, bucket: dagger.Secret, access_key_id: dagger.Secret, secret_access_key: dagger.Secret) -> None:
return await (
dag.tapes()
.upload_install_sh(endpoint, bucket, access_key_id, secret_access_key)
)@func()
async example(endpoint: Secret, bucket: Secret, accessKeyId: Secret, secretAccessKey: Secret): Promise<void> {
return dag
.tapes()
.uploadInstallSh(endpoint, bucket, accessKeyId, secretAccessKey)
}