Skip to content

BehindTheMusicTree/github-workflows

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

68 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

GitHub Workflows

Reusable GitHub Actions workflows for the BehindTheMusicTree organization.

See CHANGELOG.md for a detailed history of changes.

Contributions are welcome! See CONTRIBUTING.md for guidelines.

Table of Contents

Available Workflows

Actionlint

Runs actionlint on the caller repo. Uses .github/actionlint.yaml from the caller if present, so repo-specific ignore rules (e.g. for reusable workflow calls) apply.

Workflow file: .github/workflows/actionlint.yml

No inputs. Call from your repo on push or pull_request:

jobs:
  actionlint:
    uses: BehindTheMusicTree/github-workflows/.github/workflows/actionlint.yml@main

Call Redeployment Webhook

Triggers a server redeployment webhook. Validates configuration, ensures env is prod or staging, and POSTs to the webhook (optional JSON image overrides in body). The response body must start with Redeployment accepted (matches hooks.json from BehindTheMusicTree/infrastructure generate-hooks-json.sh for every stack).

Workflow file: .github/workflows/call-redeployment-webhook.yml

Input Required Description
env Yes prod or staging (lowercase)
images No Optional JSON object of image overrides (e.g. {"gateway_image": "user/repo:tag"}). Default {}.
hook_id_base Yes Hook id for /hooks/<hook_id_base>-<env> (trimmed). X-Secret: if this equals vars.TMD_ADMIN_REDEPLOYMENT_HOOK_ID_BASE (trimmed, var non-empty), use TMD_ADMIN_WEBHOOK_SECRET_<env>; else BTMT_REDEPLOYMENT_WEBHOOK_SECRET_<env>. Use distinct hook id bases for BTMT vs TMD on the same repo.

Set Image Tags On Server

Writes one pooled stack/env image-tags manifest on the server (atomic *.new then mv -f). Use this instead of per-service set-image-tag-on-server calls so API/DB/AFP tags are updated in one operation.

Workflow file: .github/workflows/set-image-tags-on-server.yml

Input Required Description
env Yes prod or staging
stack Yes Stack key in filename (e.g. btmt, tmd-admin)
tags Yes Multiline KEY=VALUE lines (e.g. HTMT_API_TAG=staging)
release_id No Optional release id metadata (RELEASE_ID=)
release_sha No Optional git SHA metadata (RELEASE_SHA=)

Required caller config: vars.SERVER_HOST, vars.IMAGE_TAGS_POOL_DIR (e.g. /srv/btmt/image-tags), secrets.SERVER_DEPLOY_USERNAME, secrets.SERVER_DEPLOY_SSH_PRIVATE_KEY.

Sync env to server

App-agnostic reusable: upload an env fragment into ENV_POOL_DIR on the server (atomic write). Redeploy (BehindTheMusicTree/infrastructure) promotes pool → scripts/sync-env/ via promote-sync-env-to-canonical.sh; compose generators read canonical sync-env files, not merged keys in scripts/.env.

Workflow file: .github/workflows/sync-env-to-server.yml

Input Required Description
sync_env Yes prod or staging (lowercase)
app_name Yes App name for fragment path (e.g. htmt-api)
fragment_artifact Yes Artifact name and path to fragment file (e.g. sync-env-fragment-staging/fragment.env)

Caller must: (1) Build the fragment in a job (app-specific keys), write it to a file (e.g. fragment.env), and upload it with actions/upload-artifact using the same artifact name. (2) Have a job that calls this workflow with needs: build-fragment, secrets: inherit, and inputs sync_env, app_name, fragment_artifact. Required vars (repo or environment): SERVER_HOST, ENV_POOL_DIR, SYNC_ENV_REMOTE_FILENAME_PREFIX_BASE, and either HTMT_API_APP_NAME or APP_NAME (app name for fragment path). Required secrets: SERVER_DEPLOY_USERNAME, SERVER_DEPLOY_SSH_PRIVATE_KEY, plus any vars/secrets for the keys included in the fragment (see workflow: FRAGMENT_KEYS and the “Build env fragment” step). Trigger redeploy after sync so promoted sync-env files reach compose/*.env / compose generation. To support a new app or new keys, add the key to FRAGMENT_KEYS and to the Build env fragment step env in this repo.

Deploy App Env File

Uploads compose env files to pool/compose/<app_name>/ on the server. Caller must upload an artifact (e.g. app-env-files) containing env files. Use non-dotfile names in the artifact (e.g. env_api, env_gtmt_front) so upload-artifact includes them; this workflow renames them to dotfiles (e.g. .env_api) before uploading.

Workflow file: .github/workflows/deploy-app-env-file.yml

Input Required Description
env Yes prod or staging (lowercase)
app_name Yes Subdir under pool/compose (e.g. htmt-api, gtmt-front)
artifact_name No Artifact name; default app-env-files

Deploy Nginx Env Fragment

Uploads a single nginx env fragment to pool/nginx/<app_name>.env. Caller must upload an artifact (e.g. nginx-env-fragment) containing exactly one file.

Workflow file: .github/workflows/deploy-nginx-env-fragment.yml

Input Required Description
env Yes prod or staging (lowercase)
app_name Yes Fragment is uploaded as pool/nginx/<app_name>.env
artifact_name No Artifact name; default nginx-env-fragment

Deploy Partial Docker Compose

Uploads partial docker-compose files to the server compose dir. Before upload, adds suffix -<env> to every container_name in the compose files (e.g. gtmt-frontgtmt-front-staging). Caller must upload an artifact (e.g. compose-parts) containing the partial YAML file(s).

Workflow file: .github/workflows/deploy-docker-compose-part.yml

Input Required Description
env Yes prod or staging (lowercase)
app_version No For logging only
artifact_name No Artifact name; default compose-parts

Usage

Call Redeployment Webhook

jobs:
  call-redeployment-webhook:
    name: Call Redeployment Webhook
    uses: BehindTheMusicTree/github-workflows/.github/workflows/call-redeployment-webhook.yml@main
    with:
      env: "staging" # or "prod"
      hook_id_base: ${{ vars.BTMT_REDEPLOYMENT_HOOK_ID_BASE }}
      images: "{}" # optional: {"gateway_image": "user/repo:tag"}
    secrets: inherit

BTMT main stack (e.g. hear-the-music-tree-api): pass hook_id_base: ${{ vars.BTMT_REDEPLOYMENT_HOOK_ID_BASE }} — same base string as in hooks.json on the server (from BehindTheMusicTree/infrastructure Server setup / Ansible).

the-music-deck-admin: pass hook_id_base: ${{ vars.TMD_ADMIN_REDEPLOYMENT_HOOK_ID_BASE }} (must match infra); call-redeployment-webhook chooses TMD_ADMIN_WEBHOOK_SECRET_* when hook_id_base equals vars.TMD_ADMIN_REDEPLOYMENT_HOOK_ID_BASE, otherwise BTMT_REDEPLOYMENT_WEBHOOK_SECRET_*.

Infrastructure (two stacks): BehindTheMusicTree/infrastructure server-setup runs two jobs with secrets: inherit: BTMT uses hook_id_base: ${{ vars.BTMT_REDEPLOYMENT_HOOK_ID_BASE }}; The Music Deck admin uses hook_id_base: ${{ vars.TMD_ADMIN_REDEPLOYMENT_HOOK_ID_BASE }} when that variable is set.

With dependencies (e.g. after build):

jobs:
  build-and-push:
    name: Build and Push
    runs-on: ubuntu-latest
    steps:
      - name: Build
        run: echo "Building..."

  call-redeployment-webhook:
    name: Call Redeployment Webhook
    needs: [build-and-push]
    uses: BehindTheMusicTree/github-workflows/.github/workflows/call-redeployment-webhook.yml@main
    with:
      env: "staging"
      hook_id_base: ${{ vars.BTMT_REDEPLOYMENT_HOOK_ID_BASE }}
    secrets: inherit

Deploy workflows (caller examples)

Reference caller workflows that prepare artifacts and call the deploy reusables are in examples/:

  • examples/deploy-htmt-api-env-and-compose.yml — API app: prepare nginx fragment, app env files (API/DB/AFP), and compose parts; call deploy-nginx-env-fragment, deploy-app-env-file, deploy-docker-compose-part. Copy to your htmt-api repo and adapt.
  • examples/deploy-gtmt-front-env-and-compose.yml — Front app: prepare env file and compose parts; call deploy-app-env-file and deploy-docker-compose-part. Copy to your gtmt-front repo and adapt.

Caller pattern: one prepare job uploads artifacts (use non-dotfile names for app env files); separate jobs with needs: [prepare] call each reusable with secrets: inherit. Deploy workflows run in the caller’s context and need the vars/secrets listed below.

Required Configuration

This repo only contains workflow definitions. Each repository that calls these workflows must configure the required secrets and variables in GitHub (repository or organization) under the environment used (staging or prod).

Webhook (call-redeployment-webhook)

Type Name Description
Variable SERVER_HOST VPS IP or hostname for webhook URL (use when main domain points elsewhere, e.g. Vercel)
Variable BTMT_REDEPLOYMENT_HOOK_ID_BASE Base hook id; URL path is /hooks/<BTMT_REDEPLOYMENT_HOOK_ID_BASE>-<env> (e.g. myhook-staging)
Secret REDEPLOYMENT_WEBHOOK_PORT Port the webhook service listens on
Secret BTMT_REDEPLOYMENT_WEBHOOK_SECRET_STAGING Webhook secret for BTMT env staging (X-Secret header)
Secret BTMT_REDEPLOYMENT_WEBHOOK_SECRET_PROD Webhook secret for BTMT env prod

When hook_id_base equals TMD_ADMIN_REDEPLOYMENT_HOOK_ID_BASE (repository variable, trimmed), X-Secret uses TMD_ADMIN_WEBHOOK_SECRET_PROD / TMD_ADMIN_WEBHOOK_SECRET_STAGING instead. Infrastructure sets that variable for The Music Deck admin; other repos can leave it unset. REDEPLOYMENT_WEBHOOK_PORT is always required.

Sync env to server

Required by sync-env-to-server (caller’s environment):

Type Name Description
Variable SERVER_HOST VPS IP or hostname for SSH
Variable ENV_POOL_DIR Server pool directory where env fragments are stored (e.g. /srv/btmt/env-pool)
Variable SYNC_ENV_REMOTE_FILENAME_PREFIX_BASE Fragment filename prefix (e.g. sync-env-)
Variable HTMT_API_APP_NAME or APP_NAME App name for fragment path (e.g. htmt-api)
Secret SERVER_DEPLOY_USERNAME SSH user
Secret SERVER_DEPLOY_SSH_PRIVATE_KEY SSH private key

Plus any vars/secrets for the fragment keys (see workflow; add new keys in the reusable when needed).

Deploy workflows

Required by deploy-app-env-file, deploy-nginx-env-fragment, and deploy-docker-compose-part (caller’s environment must have these):

Type Name Description
Variable REDEPLOYMENT_ROOT Redeployment tree root (e.g. /var/webhook/redeployment); pool/compose paths use {REDEPLOYMENT_ROOT}-{env}/
Variable DOCKER_COMPOSE_DIR_NAME Compose dir name under redeploy dir
Variable SERVER_HOST VPS IP or hostname for SSH
Secret SERVER_DEPLOY_USERNAME SSH user for deploy
Secret SERVER_DEPLOY_SSH_PRIVATE_KEY SSH private key for deploy

Setup Instructions

  1. Configure secrets and variables in the repo (or org) that calls the workflows: SettingsEnvironments → create or select staging / prod and add the required entries from Required Configuration.
  2. Add workflow calls to your workflow file (see Usage). For deploy flows, copy and adapt a caller from examples/.
  3. Verify access: Public repos can use these reusables as-is; private repos require the org to allow reusable workflows from private repos.

Workflow Behavior

Call Redeployment Webhook

  1. Validate env: Ensures env is prod or staging.
  2. Check required config: Validates webhook-related secrets and variables for that env.
  3. Call webhook: POSTs to the webhook URL (optional JSON body for image overrides).
  4. Validate response: Fails if the response body does not start with expected_response_prefix (default Redeploying BTMT ecosystem).

Expected Webhook Response

  • Status code: 200 OK
  • Response body: Must start with the configured prefix:
    • BTMT (default): Redeploying BTMT ecosystem (e.g. Redeploying BTMT ecosystem (staging)).
    • The Music Deck admin: pass expected_response_prefix: "Redeploying The Music Deck admin" (matches e.g. Redeploying The Music Deck admin (prod)).

Error Handling

The webhook workflow fails with clear errors if:

  • env is not prod or staging
  • Required secrets/variables are missing
  • Webhook is unreachable (e.g. connection refused)
  • Response does not start with Redeployment accepted (regenerate hooks.json on the server after infra upgrades) or hook not found (404)

Webhook Endpoint

The workflow builds the URL using SERVER_HOST (the webhook runs on the VPS; use VPS IP when the main domain points elsewhere, e.g. Vercel):

http://<SERVER_HOST>:<REDEPLOYMENT_WEBHOOK_PORT>/hooks/<BTMT_REDEPLOYMENT_HOOK_ID_BASE>-<env>

Example: SERVER_HOST=203.0.113.10, REDEPLOYMENT_WEBHOOK_PORT=9000, BTMT_REDEPLOYMENT_HOOK_ID_BASE=btmt-redeploy, env=staging
http://203.0.113.10:9000/hooks/btmt-redeploy-staging

Manual check (use the secret for the env you target):

curl -v -X POST -H "Content-Type: application/json" -H "X-Secret: YOUR_SECRET" -d '{}' --max-time 15 \
  http://<SERVER_HOST>:9000/hooks/btmt-redeploy-staging

Troubleshooting

"Workflow was not found" Error

  • Ensure the repository is public (or your organization allows private repo access)
  • Verify the workflow file exists on the main branch
  • Check that the repository path is correct

"Missing required config" / invalid env Error

  • Set all required secrets and variables for the environment you use (staging or prod)
  • Use BTMT_REDEPLOYMENT_WEBHOOK_SECRET_STAGING and BTMT_REDEPLOYMENT_WEBHOOK_SECRET_PROD (not a single combined secret name)
  • Ensure BTMT_REDEPLOYMENT_HOOK_ID_BASE is set; the hook path is <BTMT_REDEPLOYMENT_HOOK_ID_BASE>-<env>

"Webhook call failed" / "Connection refused" Error

  • Ensure the webhook service is running on the server: systemctl status webhook
  • Check port and firewall; REDEPLOYMENT_WEBHOOK_PORT must match the server
  • In hooks.json, the hook id must be <BTMT_REDEPLOYMENT_HOOK_ID_BASE>-<env> (e.g. btmt-redeploy-staging)
  • Verify the X-Secret header matches the secret for that env (BTMT_REDEPLOYMENT_WEBHOOK_SECRET_STAGING or _PROD)

"Artifact not found" when calling deploy workflows from another repo

  • Artifacts are created in the caller’s run; reusables in another repo may not see them. Use a single combined artifact (e.g. one app-env-files with all env files) and consider inlining the deploy job in the caller if the reusable still can’t download it.
  • Use non-dotfile names in app-env artifacts (e.g. env_api not .env_api) so upload-artifact includes the files; the deploy-app-env-file workflow renames them to dotfiles on the server.

Contributing

This repository contains reusable workflows for the BehindTheMusicTree organization.

For detailed contribution guidelines, including development workflow, branching strategy, and pull request process, see CONTRIBUTING.md.

Quick start:

  1. Create a feature branch
  2. Make your changes
  3. Test the workflow in a calling repository
  4. Submit a pull request

Changelog

See CHANGELOG.md for a detailed history of changes, including version history, new features, bug fixes, and improvements.

License

[Specify your license here]

About

No description, website, or topics provided.

Resources

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors