buildspace-ci-cd

v2026.09.24

Configure and troubleshoot BuildSpace reusable GitHub Actions workflows and blocks for automated releases. Covers Rust, TypeScript (single package and monorepo), Go, Swift package, macOS .pkg (binary and payload-only), dylib (Xcode and Makefile), generic release, AI-based versioning/release notes, README freshness checks, skills documentation checks, labels, permissions, secrets, Homebrew tap updates, Jamf uploads, dry-run testing, and custom block composition. Use when users mention BuildSpace, release automation, reusable workflows, GitHub Actions CI/CD, or publishing to npm/crates/Homebrew/Jamf. Keywords: buildspace, ci/cd, github actions, release automation, reusable workflows, npm, crates, homebrew, rust, typescript, go, swift, monorepo, dylib, macOS, pkg, jamf, skills.

GitHub
Install command
npx skhub add photon-hq/buildspace-ci-cd
Markdown
SKILL.md

BuildSpace Release Workflows Skill

Use this skill to set up or debug BuildSpace-powered release automation in repositories that use reusable GitHub Actions workflows.

What BuildSpace Provides

BuildSpace has two layers:

  • Workflows: full release pipelines under .github/workflows/*.
  • Blocks: reusable composite actions under .github/blocks/* for custom pipelines.

Default recommendation: use a prebuilt workflow unless the user explicitly needs custom behavior.

Workflow Selection

Pick exactly one primary workflow based on project type:

Project typeWorkflow fileTrigger
Rust binary/libraryrust-service-release.yamlPR label release
TypeScript/JavaScript single packagetypescript-service-release.yamlPR label release
TypeScript monorepo (multiple packages)typescript-monorepo-release.yamlPR label release
Go binarygo-service-release.yamlPR label release
Swift macOS .pkg (with compiled binary)swift-release.ymlPR label release
macOS .pkg without binary (payload/scripts only)pkg-release.ymlPR label release
macOS .pkg PR build (payload/scripts only)pkg-release-pr.ymlEvery PR commit
Swift macOS .pkg PR build previewsswift-pkg-pr.ymlEvery PR commit
macOS dylib release (Xcode workspace)dylib-release.ymlPR label release
macOS dylib release (Makefile)makefile-dylib-release.ymlPR label release
Generic release (version + GitHub Release only)release.yamlPR label release
README freshness check on PRscheck-readme.yamlEvery PR
Skills documentation freshness check on PRscheck-skills.yamlEvery PR

Required Inputs, Secrets, and Permissions

Always verify these before writing YAML:

  1. Inputs: service/package names, paths, build command, package lists, Homebrew tap info, Jamf config.
  2. Secrets:
    • Always required for AI features: OPENAI_API_KEY
    • npm publishing: NPM_TOKEN
    • crates publishing: CARGO_REGISTRY_TOKEN
    • Swift compile-time env vars: SECRET_ENV_VARS
    • Jamf upload: JAMF_CLIENT_ID + JAMF_CLIENT_SECRET
    • Protected-branch pushes or Homebrew tap updates: APP_ID + APP_PRIVATE_KEY
    • Skills documentation check (private repos): SKILLS_REPO_TOKEN
    • Note: DEVELOPER_ID_INSTALLER_NAME is deprecated and ignored — packages are always unsigned.
  3. Permissions:
    • Release/version bump jobs need contents: write
    • Label checks need pull-requests: read
    • PR commenting needs pull-requests: write

Release Trigger Rules (Important)

BuildSpace is label-gated by default.

  • Standard release label: release
  • Optional prerelease label: prerelease
  • No label usually means no release job.

Behavior nuance to keep accurate:

  • typescript-monorepo-release supports prerelease path directly.
  • typescript-service-release, rust-service-release, and go-service-release gate release jobs on release (or forced input), and treat prerelease as flavor once release is active.
  • swift-release, pkg-release, dylib-release, and makefile-dylib-release check only release.
  • release.yaml (generic) checks release label and supports a release boolean input to force.

Implementation Procedure

When asked to set up BuildSpace in a repo:

  1. Detect repo type (Rust, TS single, TS monorepo, Go, Swift, macOS pkg, dylib).
  2. Confirm publish targets (GitHub only, npm, crates, Jamf, Homebrew tap).
  3. Create a caller workflow in the user repo (.github/workflows/release.yaml or ci.yaml) with uses: photon-hq/buildspace/...@v1.
  4. Wire with: inputs and secrets: exactly for that workflow.
  5. Add recommended permissions block.
  6. Add dry-run: true for first validation run unless the user requests immediate publish.
  7. Explain how to trigger (release label + merge path, or forced release: true).
  8. For monorepos, validate packages JSON and dependency order behavior.
  9. For Homebrew tap updates, wire tap-repo and tap-formula inputs plus APP_ID/APP_PRIVATE_KEY secrets.
  10. For Jamf uploads, wire jamf-url and Jamf secrets.

Workflow Reference

rust-service-release.yaml

Complete release pipeline for Rust services: label check, AI version + release notes, cross-build (Linux x64, macOS ARM64, Windows x64), sync workspace crate versions, publish crates to crates.io, create GitHub Release with binaries, optionally update Homebrew tap.

Inputs:

InputTypeRequiredDefaultDescription
service-namestringYes—Display name for the service
binary-namestringYes—Name of the binary from Cargo.toml
binary-pathstringNo""Path to crate directory (e.g., crates/client)
cratesstringNo[]JSON array of crate paths to publish in dependency order
build-envstringNo""Compile-time env vars (e.g., BASE_URL=https://...)
labels-to-checkstringNo["release", "prerelease"]PR labels that trigger releases
prereleasebooleanNofalseForce prerelease (adds -rc.N suffix)
releasebooleanNofalseForce release (bypasses label check)
dry-runbooleanNofalseTest without actually publishing
tap-repostringNo""Homebrew tap repository (e.g., photon-hq/homebrew-photon). Empty to skip.
tap-formulastringNo""Formula name in tap (e.g., jamf-package-updater). Required if tap-repo is set.

Secrets:

SecretRequiredDescription
OPENAI_API_KEYYesFor AI-powered versioning and release notes
CARGO_REGISTRY_TOKENNocrates.io API token (required for publishing)
APP_IDNoGitHub App ID (for protected branches and Homebrew tap updates)
APP_PRIVATE_KEYNoGitHub App private key

typescript-service-release.yaml

Complete release pipeline for a single TypeScript/JavaScript package: label check, AI version + release notes, bump package.json, create GitHub Release, publish to npm.

Inputs:

InputTypeRequiredDefaultDescription
service-namestringYes—Display name for the service
bun-versionstringNolatestBun version to use
npm-tagstringNolatestnpm dist-tag (e.g., latest, beta, next)
no-npm-publishbooleanNofalseSkip npm publishing (GitHub Release only)
working-directorystringNo.Directory containing package.json
build-commandstringNobun run buildBuild command to run
labels-to-checkstringNo["release", "prerelease"]PR labels that trigger releases
prereleasebooleanNofalseForce prerelease
releasebooleanNofalseForce release (bypasses label check)
dry-runbooleanNofalseTest without actually publishing

Secrets:

SecretRequiredDescription
OPENAI_API_KEYYesFor AI-powered versioning and release notes
NPM_TOKENNonpm auth token (required for publishing)

typescript-monorepo-release.yaml

Complete release pipeline for TypeScript monorepos with independently-versioned packages. Detects changed packages, topologically sorts by dependency order, single AI call for all versions/notes, bumps each package.json, creates GitHub Release with release/YYYY-MM-DD.N tag, publishes to npm in order.

Inputs:

InputTypeRequiredDefaultDescription
service-namestringYes—Display name for the monorepo
packagesstringYes—JSON array: [{"name":"pkg","path":"packages/pkg"}]
bun-versionstringNolatestBun version to use
npm-tagstringNolatestnpm dist-tag
build-commandstringNobun run buildPer-package build command (ignored if root-build-command is set)
root-build-commandstringNo""Build once at repo root (e.g., turbo build)
include-dependentsbooleanNofalseAlso release downstream dependents
labels-to-checkstringNo["release", "prerelease"]PR labels that trigger releases
prereleasebooleanNofalseForce prerelease
releasebooleanNofalseForce release
dry-runbooleanNofalseTest without actually publishing

Secrets:

SecretRequiredDescription
OPENAI_API_KEYYesFor AI-powered versioning and release notes
NPM_TOKENYesnpm authentication token
APP_IDNoGitHub App ID (for pushing to protected branches)
APP_PRIVATE_KEYNoGitHub App private key

go-service-release.yaml

Complete release pipeline for Go binaries: label check, AI version + release notes, cross-compile for macOS (ARM64) and Linux (AMD64), create GitHub Release with binaries, optionally update Homebrew tap.

Inputs:

InputTypeRequiredDefaultDescription
service-namestringYes—Display name for the service
binary-namestringYes—Output binary name
go-versionstringNostableGo version to use
build-flagsstringNo""Additional go build flags
ldflagsstringNo-s -wLinker flags
labels-to-checkstringNo["release", "prerelease"]PR labels that trigger releases
prereleasebooleanNofalseForce prerelease
releasebooleanNofalseForce release
tap-repostringNo""Homebrew tap repository. Empty to skip.
tap-formulastringNo""Formula name in tap. Required if tap-repo is set.

Secrets:

SecretRequiredDescription
OPENAI_API_KEYYesFor AI-powered versioning and release notes
APP_IDNoGitHub App ID (for Homebrew tap updates)
APP_PRIVATE_KEYNoGitHub App private key

swift-release.yml

Complete release pipeline for macOS .pkg distribution with a compiled Swift binary: label check, AI version + release notes, Swift build, .pkg creation (unsigned), GitHub Release, optional Jamf upload.

Inputs:

InputTypeRequiredDefaultDescription
package-namestringYes—Name of the Swift binary / package
identifierstringYes—Package identifier (e.g., com.example.mytool)
scripts-pathstringNo""Path to scripts directory with preinstall/postinstall scripts
payload-pathstringNo""Path to additional payload directory (mirrors install root)
jamf-urlstringNo""Jamf Pro instance URL (leave empty to skip)
jamf-package-prioritystringNo""Package priority in Jamf Pro
jamf-package-namestringNo""Package name to match in Jamf Pro

Secrets:

SecretRequiredDescription
OPENAI_API_KEYYesFor AI-powered versioning and release notes
SECRET_ENV_VARSNoCompile-time env vars written to .env
JAMF_CLIENT_IDNoJamf Pro API client ID
JAMF_CLIENT_SECRETNoJamf Pro API client secret

pkg-release.yml

Release pipeline for macOS .pkg that does not contain a compiled binary. Packages payload files and scripts into a .pkg, creates GitHub Release, optionally uploads to Jamf. Use instead of swift-release when packages only deliver configuration files, LaunchDaemons, scripts, or other non-binary payload.

Inputs:

InputTypeRequiredDefaultDescription
package-namestringYes—Name of the package
identifierstringYes—Package identifier (e.g., com.example.my-config)
scripts-pathstringNo""Path to scripts directory with preinstall/postinstall scripts
payload-pathstringNo""Path to payload directory (mirrors install root)
jamf-urlstringNo""Jamf Pro instance URL (leave empty to skip)
jamf-package-prioritystringNo""Package priority in Jamf Pro
jamf-package-namestringNo""Package name to match in Jamf Pro

Secrets:

SecretRequiredDescription
OPENAI_API_KEYYesFor AI-powered versioning and release notes
JAMF_CLIENT_IDNoJamf Pro API client ID
JAMF_CLIENT_SECRETNoJamf Pro API client secret

pkg-release-pr.yml

Builds a macOS .pkg (without a compiled binary) on every PR commit and reports status in the PR as a living comment. Same experience as swift-pkg-pr but for payload/scripts-only packages. Stale in-progress builds are automatically cancelled on new commits.

Inputs:

InputTypeRequiredDefaultDescription
package-namestringYes—Name of the package
identifierstringYes—Package identifier (e.g., com.example.my-config)
scripts-pathstringNo""Path to scripts directory with preinstall/postinstall scripts
payload-pathstringNo""Path to payload directory (mirrors install root)

swift-pkg-pr.yml

Builds a macOS .pkg (with Swift binary) on every PR commit, posts/updates a single PR comment with build status, uploads artifact (7-day retention). Stale in-progress builds are automatically cancelled on new commits.

Inputs:

InputTypeRequiredDefaultDescription
package-namestringYes—Name of the Swift binary / package
identifierstringYes—Package identifier (e.g., com.example.mytool)
scripts-pathstringNo""Path to scripts directory with preinstall/postinstall scripts

Secrets:

SecretRequiredDescription
SECRET_ENV_VARSNoCompile-time env vars written to .env

dylib-release.yml

Release pipeline for macOS dynamic libraries built from an Xcode workspace with CocoaPods. Label check, AI version + release notes, install CocoaPods, build dylib (arm64e), create GitHub Release with .dylib artifact.

Inputs:

InputTypeRequiredDefaultDescription
workspacestringYes—Path to .xcworkspace
schemestringYes—Xcode scheme to build
dylib-namestringYes—Name of the output dylib (e.g., BlueBubblesHelper)
project-directorystringYes—Directory containing the Podfile

Secrets:

SecretRequiredDescription
OPENAI_API_KEYYesFor AI-powered versioning and release notes

makefile-dylib-release.yml

Release pipeline for macOS dynamic libraries built from a Makefile. Label check, AI version + release notes, make release, create GitHub Release with .dylib artifact.

Inputs:

InputTypeRequiredDefaultDescription
dylib-namestringYes—Name of the output dylib (e.g., imessage-helper)

Secrets:

SecretRequiredDescription
OPENAI_API_KEYYesFor AI-powered versioning and release notes

release.yaml

Generic release pipeline for projects that only need AI-powered versioning and a GitHub Release (no build step, no package publishing). Useful for configuration repos, documentation repos, or any project that just needs tagged releases.

Inputs:

InputTypeRequiredDefaultDescription
service-namestringYes—Display name for the service
labels-to-checkstringNo["release"]JSON array of PR labels to check
releasebooleanNofalseForce release (overrides label)

Secrets:

SecretRequiredDescription
OPENAI_API_KEYYesFor AI-powered versioning and release notes

check-readme.yaml

Runs on every PR to check if README.md is up to date with the changes. Uses AI to analyze changed files against the README. Posts/removes PR comments automatically.

Inputs:

InputTypeRequiredDefaultDescription
blockingbooleanNofalseIf true, fail the workflow when README is outdated. If false, only post a warning comment.

Secrets:

SecretRequiredDescription
OPENAI_API_KEYYesFor AI-powered README analysis

check-skills.yaml

Runs on every PR to check if skills documentation (in a separate skills repo) is up to date with the changes. Uses AI to analyze changed files against skill SKILL.md files. Posts/removes PR comments automatically.

Inputs:

InputTypeRequiredDefaultDescription
fail_on_missing_skillsbooleanNofalseIf true, fail workflow when skills are outdated. If false, only post a warning comment.
skills-repostringNophoton-hq/skillsSkills repository to check against (owner/repo format)

Secrets:

SecretRequiredDescription
OPENAI_API_KEYYesFor AI-powered skills analysis
SKILLS_REPO_TOKENNoGitHub token for skills repo (defaults to GITHUB_TOKEN; use PAT for private repos)

Monorepo-Specific Guidance

For typescript-monorepo-release:

  • packages input must be a JSON array: [{"name":"pkg","path":"packages/pkg"}]
  • Changed package detection is diffed from last release tag.
  • Packages are topologically sorted using local dependency edges.
  • Optional include-dependents: true pulls downstream packages into release.
  • root-build-command takes precedence over per-package build-command.
  • Pre-release npm tag is automatically beta when prerelease is active.
  • Uses release/YYYY-MM-DD.N date-based tags since there's no single version.

Rust/Go Notes

  • Rust workflow can:
    • cross-build artifacts for Linux x64, macOS ARM64, Windows x64
    • sync workspace versions across all crates
    • publish crates in provided order
    • optionally update Homebrew tap (tap-repo + tap-formula, requires APP_ID + APP_PRIVATE_KEY)
  • Go workflow:
    • cross-builds for macOS ARM64 and Linux AMD64
    • can also update Homebrew tap (tap-repo + tap-formula, requires APP_ID + APP_PRIVATE_KEY)

Swift / macOS .pkg Notes

  • swift-release builds the Swift binary, creates an unsigned .pkg, creates GitHub Release, and optionally uploads to Jamf.
  • pkg-release is for .pkg packages that contain no compiled binary — only payload files and/or scripts.
  • swift-pkg-pr and pkg-release-pr are the PR preview counterparts (build on every commit, comment on PR).
  • Packages are always unsigned (DEVELOPER_ID_INSTALLER_NAME is deprecated and ignored).
  • Compile-time env vars are passed via SECRET_ENV_VARS secret (written to .env).
  • Jamf upload is optional — set jamf-url input and provide JAMF_CLIENT_ID + JAMF_CLIENT_SECRET secrets.

Dylib Notes

  • dylib-release.yml is for projects using an Xcode workspace with CocoaPods. Builds arm64e dylib.
  • makefile-dylib-release.yml is for projects using a Makefile. Runs make release and embeds version.
  • Both create a GitHub Release with the .dylib as an artifact.

README Check Guidance

Use check-readme.yaml for PR docs drift detection:

  • blocking: false (default): warning comment only.
  • blocking: true: fails job when README appears stale.
  • Requires OPENAI_API_KEY and PR write permission for comments.

Skills Check Guidance

Use check-skills.yaml for skills documentation drift detection:

  • fail_on_missing_skills: false (default): warning comment only.
  • fail_on_missing_skills: true: fails job when skills appear outdated.
  • Requires OPENAI_API_KEY and PR write permission for comments.
  • For private skills repos, provide SKILLS_REPO_TOKEN (PAT with repo access).

Blocks Reference

All blocks live under .github/blocks/. Workflows compose these internally — use them directly only for custom pipelines.

Version & Release Info

BlockPathPurpose
determine-publish-version.github/blocks/determine-publish-version/action.yamlAI-powered next semantic version (standalone, no release notes)
generate-release-info.github/blocks/generate-release-info/action.yamlAI-powered version + release notes in one step
create-github-release.github/blocks/create-github-release/action.yamlCreate GitHub Release with optional artifact attachments

Label & PR Interaction

BlockPathPurpose
check-pr-label.github/blocks/check-pr-label/action.yamlCheck PR labels to decide if release should trigger
comment-on-pr.github/blocks/comment-on-pr/action.yamlPost or update a single PR comment (idempotent via comment-key)
check-readme.github/blocks/check-readme/action.yamlAI-powered README freshness check
check-skills.github/blocks/check-skills/action.yamlAI-powered skills documentation freshness check

Build Blocks

BlockPathPurpose
rust-build.github/blocks/rust-build/action.yamlBuild Rust binary for a target triple
go-build.github/blocks/go-build/action.yamlBuild Go binary for a target OS/arch
typescript-build.github/blocks/typescript-build/action.yamlBuild TypeScript project using Bun
swift-build.github/blocks/swift-build/action.ymlBuild Swift binary (SPM, supports .env injection)
swift-pkg.github/blocks/swift-pkg/action.ymlCreate macOS .pkg from binary and/or payload/scripts
build-dylib.github/blocks/build-dylib/action.ymlBuild macOS dylib from Xcode workspace (arm64e)
build-makefile-dylib.github/blocks/build-makefile-dylib/action.ymlBuild macOS dylib from Makefile
install-cocoapods.github/blocks/install-cocoapods/action.ymlCache and install CocoaPods dependencies

Publish Blocks

BlockPathPurpose
publish-npm.github/blocks/publish-npm/action.yamlPublish single package to npm
publish-npm-packages.github/blocks/publish-npm-packages/action.yamlPublish multiple monorepo packages to npm in dependency order
publish-crates.github/blocks/publish-crates/action.yamlPublish workspace crates to crates.io in order
bump-npm-version.github/blocks/bump-npm-version/action.yamlBump version in package.json and push
bump-monorepo-versions.github/blocks/bump-monorepo-versions/action.yamlAI version bump for all changed monorepo packages
sync-crates-version.github/blocks/sync-crates-version/action.yamlSet a single version across all Rust workspace crates
update-tap.github/blocks/update-tap/action.yamlUpdate Homebrew tap formula (auto-calculates SHA256 for npm/Go/prebuilt)
detect-changed-packages.github/blocks/detect-changed-packages/action.yamlDetect changed monorepo packages and return in topological order

Troubleshooting Checklist

If release did not run:

  • Confirm PR had expected label before merge.
  • Confirm workflow permissions include required scopes.
  • Confirm secrets exist at repository level.
  • Confirm caller workflow points to correct reusable workflow path.
  • For monorepos, confirm packages JSON is valid and paths exist.
  • For publish failures, test with dry-run: true and verify auth token scopes.
  • For Homebrew tap updates, confirm APP_ID + APP_PRIVATE_KEY secrets are set and the GitHub App has push access to the tap repo.
  • For Jamf uploads, confirm JAMF_CLIENT_ID + JAMF_CLIENT_SECRET are set and jamf-url is a valid Jamf Pro URL.
  • For dylib builds, confirm Xcode workspace/scheme or Makefile exists and produces expected output.

Output Format for Agent Responses

When generating BuildSpace setup instructions, respond with:

  1. Chosen workflow and why.
  2. Copy-ready YAML for caller workflow.
  3. Secrets to add (list exactly which ones and where to get them).
  4. How to trigger and verify.
  5. First-run safe mode (dry-run) recommendation.

Keep recommendations concrete and default to the smallest working setup.

Discovery
Tags

No tags published for this skill.

Version
Latest version metadata

Version

v2026.09.24

Published

Sep 24, 2026

Category

Uncategorized

License

Not specified

Source path

skills/buildspace-ci-cd

Default branch

main

Latest commit

abf227f

Tree SHA

23d90f8