Repository navigation
Blackout Secure Launchpad #33
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Caller for the hub's `bos-launchpad.yml` (Blackout Secure Launchpad) reusable. | |
| # | |
| # monitor (github_release mode → actions/runner) → release (docker → balena → github release) | |
| # | |
| # Required vars: DOCKERHUB_NAMESPACE, BALENA_NAMESPACE | |
| # Required secrets: DOCKERHUB_USERNAME, DOCKERHUB_TOKEN, BALENA_API_TOKEN | |
| # | |
| # `balena.yml` is rendered by the hub on each run from the `balena_*` inputs | |
| # below. See blackoutsecure/bos-automation-hub for the full input reference. | |
| name: Blackout Secure Launchpad | |
| on: | |
| schedule: | |
| - cron: '17 */6 * * *' # stagger off :00 to dodge org cron pile-ups | |
| push: | |
| branches: | |
| - main | |
| paths: | |
| - 'Dockerfile' | |
| - '.dockerignore' | |
| - 'build/**' | |
| - 'root/**' | |
| # scripts/autoscale.sh is COPYed into the image at | |
| # /usr/local/bin/gh-runner-autoscale (Dockerfile line ~66), so | |
| # changes here must rebuild even when nothing under root/** moved. | |
| - 'scripts/**' | |
| - 'docker-compose.yml' | |
| - 'README.md' | |
| - '.github/upstream/**' | |
| - '.github/workflows/bos-launchpad.yml' | |
| workflow_dispatch: | |
| inputs: | |
| stage_docker: | |
| description: 'Stage: docker build & push' | |
| type: boolean | |
| default: true | |
| stage_balena: | |
| description: 'Stage: balena block publish' | |
| type: boolean | |
| default: true | |
| stage_github_release: | |
| description: 'Stage: GitHub Release publish' | |
| type: boolean | |
| default: true | |
| # Push events always rebuild via the `with: force_run:` | |
| # expression below; this checkbox only affects on-demand | |
| # `workflow_dispatch` runs. | |
| force_run: | |
| description: 'Force: run pipeline even if upstream unchanged' | |
| type: boolean | |
| default: false | |
| # No top-level `concurrency:` — the hub workflow owns serialization. | |
| # Declaring it on both sides triggers a GHA self-deadlock. | |
| permissions: | |
| contents: read | |
| jobs: | |
| release: | |
| permissions: | |
| contents: write # monitor tracking-file commit + GitHub Release publish | |
| actions: write # nested monitor declares this for `gh workflow run` (validated at workflow-call time) | |
| pull-requests: write # nested Docker Scout PR annotations | |
| security-events: write # nested Docker Scout SARIF upload | |
| uses: blackoutsecure/bos-automation-hub/.github/workflows/bos-launchpad.yml@main | |
| with: | |
| # Schedule + push runs use the defaults; manual runs honour the | |
| # dispatch checkboxes. Every launchpad stage defaults to `false` | |
| # in the hub — opt in explicitly. | |
| docker: ${{ github.event_name != 'workflow_dispatch' || inputs.stage_docker }} | |
| balena: ${{ github.event_name != 'workflow_dispatch' || inputs.stage_balena }} | |
| github_release: ${{ github.event_name != 'workflow_dispatch' || inputs.stage_github_release }} | |
| upstream_repo: actions/runner | |
| track_file: .github/upstream/actions-runner.json | |
| # Push always rebuilds; schedule only when upstream moves. | |
| force_run: ${{ github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && inputs.force_run) }} | |
| # When force_run is a manual dispatch, also bypass downstream caches | |
| # so the rebuild ACTUALLY produces a fresh image + balena release. | |
| # Without these, docker re-uses GHA layer cache (same digest) and balena | |
| # returns the existing release for the same source SHA — the "force" | |
| # ends up being a no-op deploy from the device's perspective. | |
| docker_force: ${{ github.event_name == 'workflow_dispatch' && inputs.force_run }} | |
| balena_force: ${{ github.event_name == 'workflow_dispatch' && inputs.force_run }} | |
| image_name: github-runner | |
| dockerhub_namespace: ${{ vars.DOCKERHUB_NAMESPACE }} | |
| # Sidecar autoscaler image built from the `autoscaler` Dockerfile stage | |
| # and published to Docker Hub alongside the main runner image. Requires | |
| # bos-automation-hub support for companion_* inputs (added in the hub's | |
| # bos-launchpad/release reusable workflows). | |
| companion_docker: true | |
| companion_image_name: github-runner-autoscaler | |
| companion_build_target: autoscaler | |
| companion_docker_short_description: GitHub Actions runner autoscaler sidecar image | |
| balena_namespace: ${{ vars.BALENA_NAMESPACE }} | |
| # Render balena.yml dynamically — no checked-in copy. | |
| balena_generate_yml: true | |
| # Preserve the historical device-type matrix from the old balena.yml. | |
| balena_default_device_type: raspberrypi3-64 | |
| balena_supported_device_types: | | |
| raspberrypi3 | |
| raspberrypi3-64 | |
| raspberrypi4 | |
| raspberrypi4-64 | |
| raspberrypi400 | |
| raspberrypi400-64 | |
| intel-nuc | |
| genericx86-64-ext | |
| balena_description: >- | |
| Containerized GitHub Actions self-hosted runner with s6 process supervision, | |
| non-root defaults, and ephemeral mode support. Features automatic token | |
| generation via GitHub PAT, Docker-in-Docker support, and built-in health | |
| monitoring for CI/CD workloads on IoT and edge devices. | |
| balena_post_provisioning: | | |
| ## Usage instructions | |
| Include this snippet in your docker-compose.yml file under 'services': | |
| ``` | |
| gh-runner: | |
| image: docker.io/${{ vars.DOCKERHUB_NAMESPACE }}/github-runner:latest | |
| restart: unless-stopped | |
| environment: | |
| - TZ=Etc/UTC | |
| - RUNNER_URL=https://github.com/OWNER/REPO | |
| - RUNNER_TOKEN=YOUR_REGISTRATION_TOKEN | |
| - RUNNER_NAME=my-runner | |
| - LOG_LEVEL=info | |
| volumes: | |
| - '/path/to/runner/config:/config' | |
| - '/var/run/docker.sock:/var/run/docker.sock' | |
| security_opt: | |
| - 'no-new-privileges:true' | |
| ``` | |
| Repository: https://github.com/${{ github.repository }} | |
| Upstream application: https://github.com/actions/runner | |
| secrets: | |
| DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} | |
| DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} | |
| BALENA_API_TOKEN: ${{ secrets.BALENA_API_TOKEN }} |