Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions .github/actions/prepare-runner-image-release/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# @generated by Hollywood. Do not edit by hand.

name: Prepare runner image release
description: Validate release identity and derive canonical OCI tags.
inputs:
event:
description: GitHub event publishing the image.
required: true
image:
description: OCI image name without a tag.
required: true
package-json:
description: Package manifest that owns the release version.
required: false
default: package.json
ref:
description: Fully qualified Git ref.
required: true
ref-name:
description: Git branch or tag name.
required: true
revision:
description: Git revision embedded in the image.
required: true
outputs:
source-ref:
description: Validated source ref.
tags:
description: Newline-separated OCI tags.
version:
description: OCI image version label.
runs:
using: node24
main: dist/index.js
6 changes: 6 additions & 0 deletions .github/actions/prepare-runner-image-release/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// @generated by Hollywood. Do not edit by hand.

import { runGitHubAction } from "@dedalus-labs/hollywood/action-runtime";
import { prepareRunnerImageRelease } from "@/gha/runner-image-actions.ts";

void runGitHubAction(prepareRunnerImageRelease);
24 changes: 24 additions & 0 deletions .github/actions/verify-published-runner-image/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# @generated by Hollywood. Do not edit by hand.

name: Verify published runner image
description: Verify GitHub provenance and anonymous registry access.
inputs:
digest:
description: Published OCI manifest digest.
required: true
image:
description: Published OCI image name without a tag.
required: true
repository:
description: GitHub source repository.
required: true
source-digest:
description: Git source revision attested by GitHub.
required: true
source-ref:
description: Git source ref attested by GitHub.
required: true
outputs: {}
runs:
using: node24
main: dist/index.js
6 changes: 6 additions & 0 deletions .github/actions/verify-published-runner-image/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// @generated by Hollywood. Do not edit by hand.

import { runGitHubAction } from "@dedalus-labs/hollywood/action-runtime";
import { verifyPublishedRunnerImage } from "@/gha/runner-image-actions.ts";

void runGitHubAction(verifyPublishedRunnerImage);
5 changes: 5 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
version: 2
updates:
- package-ecosystem: docker
directory: /runner
schedule:
interval: weekly
open-pull-requests-limit: 3
- package-ecosystem: npm
directory: /
schedule:
Expand Down
197 changes: 197 additions & 0 deletions .github/workflows/runner-image.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
# @generated by Hollywood. Do not edit by hand.

name: Runner Image
on:
pull_request:
branches:
- main
paths:
- runner/**
- src/container*.ts
- src/runner*.ts
- gha/actions.ts
- gha/runner-image*.ts
- .npmrc
- package.json
- package-lock.json
- tsdown.config.ts
push:
branches:
- main
paths:
- runner/**
- src/container*.ts
- src/runner*.ts
- gha/actions.ts
- gha/runner-image*.ts
- .npmrc
- package.json
- package-lock.json
- tsdown.config.ts
release:
types:
- published
schedule:
- cron: 17 7 * * 1
workflow_dispatch: {}
concurrency:
group: runner-image-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
observe:
name: Observe (${{ matrix.architecture }})
if: github.repository == 'dedalus-labs/hollywood' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository)
runs-on: ${{ matrix.architecture == 'amd64' && 'ubuntu-24.04' || 'ubuntu-24.04-arm' }}
strategy:
matrix:
architecture:
- amd64
- arm64
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10
with:
persist-credentials: false
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e
with:
node-version: "24"
- name: Install dependencies
run: npm ci
- name: Audit dependencies
run: npm audit --audit-level=high
- name: Verify registry signatures
run: npm audit signatures
- name: Build Hollywood
run: npm run build
- name: Build local actions
run: npm run actions
- name: Capture runner
uses: ./.github/actions/capture-runner-probe
with:
output: runner-${{ matrix.architecture }}.json
- name: Verify runner
uses: ./.github/actions/verify-runner-probe
with:
contract: runner/contract.json
probe: runner-${{ matrix.architecture }}.json
- name: Upload runner probe
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
with:
name: runner-${{ matrix.architecture }}
path: runner-${{ matrix.architecture }}.json
if-no-files-found: error
retention-days: 30
verify:
name: Verify image (${{ matrix.provider }}, ${{ matrix.architecture }})
if: github.repository == 'dedalus-labs/hollywood' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository)
runs-on: ${{ matrix.architecture == 'amd64' && 'ubuntu-24.04' || 'ubuntu-24.04-arm' }}
strategy:
fail-fast: false
matrix:
architecture:
- amd64
- arm64
provider:
- docker
- podman
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10
with:
persist-credentials: false
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e
with:
node-version: "24"
- name: Install dependencies
run: npm ci
- name: Audit dependencies
run: npm audit --audit-level=high
- name: Verify registry signatures
run: npm audit signatures
- name: Build Hollywood
run: npm run build
- name: Build local actions
run: npm run actions
- name: Verify runner image
uses: ./.github/actions/verify-runner-image
with:
provider: ${{ matrix.provider }}
publish:
name: Publish image
needs:
- observe
- verify
if: ${{ github.repository == 'dedalus-labs/hollywood' && (github.event_name == 'push' && github.ref == 'refs/heads/main' || github.event_name == 'release') }}
runs-on: ubuntu-24.04
permissions:
attestations: write
contents: read
id-token: write
packages: write
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10
with:
persist-credentials: false
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e
with:
node-version: "24"
- name: Install dependencies
run: npm ci
- name: Audit dependencies
run: npm audit --audit-level=high
- name: Verify registry signatures
run: npm audit signatures
- name: Build Hollywood
run: npm run build
- name: Build local actions
run: npm run actions
- id: release
name: Prepare release
uses: ./.github/actions/prepare-runner-image-release
with:
event: ${{ github.event_name }}
image: ghcr.io/dedalus-labs/hollywood-runner
ref: ${{ github.ref }}
ref-name: ${{ github.ref_name }}
revision: ${{ github.sha }}
- name: Log in to GHCR
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ github.token }}
- name: Set up QEMU
uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130
- name: Set up Buildx
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f
- id: build
name: Build and publish
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8
with:
context: runner
file: runner/Containerfile
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.release.outputs.tags }}
labels: ${{ format('org.opencontainers.image.version={0}', steps.release.outputs.version) }}
build-args: ${{ format('SOURCE_REVISION={0}', github.sha) }}
cache-from: type=gha,scope=runner-image-main
cache-to: type=gha,mode=max,scope=runner-image-main
provenance: mode=max
sbom: true
- name: Attest image
uses: actions/attest-build-provenance@43d14bc2b83dec42d39ecae14e916627a18bb661
with:
subject-name: ghcr.io/dedalus-labs/hollywood-runner
subject-digest: ${{ steps.build.outputs.digest }}
push-to-registry: true
- env:
GH_TOKEN: ${{ github.token }}
name: Verify publication
uses: ./.github/actions/verify-published-runner-image
with:
digest: ${{ steps.build.outputs.digest }}
image: ghcr.io/dedalus-labs/hollywood-runner
repository: dedalus-labs/hollywood
source-digest: ${{ github.sha }}
source-ref: ${{ steps.release.outputs.source-ref }}
18 changes: 18 additions & 0 deletions gha/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,22 @@ export const uploadPagesArtifactAction =
export const deployPagesAction =
"actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128"; // v5.0.0

export const uploadArtifactAction =
"actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02"; // v4

export const dockerLoginAction =
"docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9"; // v3

export const dockerSetupBuildxAction =
"docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f"; // v3

export const dockerSetupQemuAction =
"docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130"; // v3

export const dockerBuildPushAction =
"docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8"; // v6

export const attestBuildProvenanceAction =
"actions/attest-build-provenance@43d14bc2b83dec42d39ecae14e916627a18bb661"; // v3

export const checkHollywoodStateCommand = "node dist/cli.js check";
11 changes: 10 additions & 1 deletion gha/dogfood.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,17 @@ import { docs } from "./docs";
import { flowers } from "./flowers";
import { publishNpm } from "./publish-npm";
import { release } from "./release";
import { runnerImageWorkflow } from "./runner-image";

const workflows = [ci, cla, docs, flowers, publishNpm, release] satisfies readonly GitHubWorkflow[];
const workflows = [
ci,
cla,
docs,
flowers,
publishNpm,
release,
runnerImageWorkflow,
] satisfies readonly GitHubWorkflow[];

test("repository workflows invoke Hollywood actions as local action steps", () => {
for (const workflow of workflows) {
Expand Down
Loading
Loading