426e9eeabd
Benchmark Bridge Tests / benchmark (bunx @biomejs/biome check packages/lifeops-bench/src, benchmark-lint) (push) Waiting to run
Benchmark Bridge Tests / benchmark (bunx vitest run --config packages/lifeops-bench/vitest.config.ts --root packages/lifeops-bench --passWithNoTests, benchmark-tests) (push) Waiting to run
Build Agent Image / build-and-push (push) Waiting to run
Chat shell gestures / Chat shell gesture + parity e2e (push) Waiting to run
ci / test (push) Waiting to run
ci / lint-and-format (push) Waiting to run
ci / build (push) Waiting to run
ci / dev-startup (push) Waiting to run
Cloud Gateway Discord / Test (push) Waiting to run
Cloud Gateway Webhook / Test (push) Waiting to run
Cloud Tests / lint-and-types (push) Waiting to run
Cloud Tests / unit-tests (push) Waiting to run
Cloud Tests / integration-tests (push) Waiting to run
Cloud Tests / e2e-tests (push) Blocked by required conditions
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Deploy Apps Worker (Product 2) / Determine environment (push) Waiting to run
Deploy Apps Worker (Product 2) / Deploy apps worker to apps-control host (${{ needs.determine-env.outputs.environment }}) (push) Blocked by required conditions
Deploy Eliza Provisioning Worker / Determine environment (push) Waiting to run
Deploy Eliza Provisioning Worker / Deploy worker to Hetzner host (${{ needs.determine-env.outputs.environment }} @ ${{ needs.determine-env.outputs.deployment_sha }}) (push) Blocked by required conditions
Dev Smoke / Classify changed paths (push) Waiting to run
Dev Smoke / bun run dev onboarding chat (push) Blocked by required conditions
Dev Smoke / Vite HMR dependency-level smoke (push) Blocked by required conditions
Electrobun Submodule Guard / electrobun gitlink is fetchable (push) Waiting to run
gitleaks / gitleaks (push) Waiting to run
Markdown Links / Relative Markdown Links (push) Waiting to run
Publish @elizaos/example-code / check_npm (push) Waiting to run
Publish @elizaos/example-code / publish_npm (push) Blocked by required conditions
Publish @elizaos/plugin-elizacloud / verify_version (push) Waiting to run
Publish @elizaos/plugin-elizacloud / publish_npm (push) Blocked by required conditions
Quality (Extended) / Homepage Build (PR smoke) (push) Waiting to run
Quality (Extended) / Comment-only diff guard (push) Waiting to run
Quality (Extended) / Format + Type Safety Ratchet (push) Waiting to run
Quality (Extended) / Develop Gate (secret scan + UI determinism) (push) Waiting to run
Quality (Extended) / Develop Gate (lint) (push) Waiting to run
Sandbox Live Smoke / Sandbox live smoke (push) Waiting to run
Snap Build & Test / Build Snap (amd64) (push) Waiting to run
Snap Build & Test / Build Snap (arm64) (push) Waiting to run
supply-chain / sbom (push) Waiting to run
supply-chain / vulnerability-scan (push) Waiting to run
Build, Push & Deploy to Phala Cloud / build-and-push (push) Waiting to run
Test Packaging / Validate Packaging Configs (push) Waiting to run
Test Packaging / PyPI on Python ${{ matrix.python }} (push) Waiting to run
Test Packaging / Pack & Test JS Tarballs (push) Waiting to run
Test Packaging / elizaos CLI global-install smoke (node + bun) (push) Waiting to run
UI Fixture E2E / ui-fixture-e2e (push) Waiting to run
UI Fixture E2E / fixture-e2e (push) Waiting to run
UI Story Gate / story-gate (push) Waiting to run
vault-ci / test (macos-latest) (push) Waiting to run
vault-ci / test (ubuntu-latest) (push) Waiting to run
vault-ci / test (windows-latest) (push) Waiting to run
vault-ci / app-core wiring tests (push) Waiting to run
verify-patches / verify patches/CHECKSUMS.sha256 (push) Waiting to run
Voice Benchmark Smoke / voice-emotion fixture smoke (push) Waiting to run
Voice Benchmark Smoke / voiceagentbench fixture smoke (push) Waiting to run
Voice Benchmark Smoke / voicebench-quality unit smoke (push) Waiting to run
Voice Benchmark Smoke / voicebench TypeScript unit (no audio) (push) Waiting to run
Voice Benchmark Smoke / voice bench smoke summary (push) Blocked by required conditions
Windows CI / windows ([bun run --cwd packages/app-core test bun run --cwd packages/elizaos test bun run --cwd packages/cloud/shared test], app-and-cli) (push) Waiting to run
Windows CI / windows ([bun run --cwd packages/scenario-runner test bun run --cwd packages/vault test bun run --cwd packages/security test bun run --cwd plugins/plugin-coding-tools test], framework-packages) (push) Waiting to run
Windows CI / windows ([bun run --cwd plugins/plugin-elizacloud test bun run --cwd plugins/plugin-discord test bun run --cwd plugins/plugin-anthropic test bun run --cwd plugins/plugin-openai test bun run --cwd plugins/plugin-app-control test bun run --cwd plugins/pl… (push) Waiting to run
Windows CI / windows ([node packages/scripts/run-turbo.mjs run build --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/agent --concurrency=4 node packages/scripts/run-bash-linux-only.mjs scripts/verify-riscv64-buildpaths.sh node packages/scripts/run… (push) Waiting to run
Windows CI / windows ([node packages/scripts/run-turbo.mjs run typecheck --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/cloud-shared --concurrency=4 bun run --cwd packages/core test bun run --cwd packages/shared test], core-runtime, 75) (push) Waiting to run
Test Packaging / Build & Test PyPI Package (push) Waiting to run
Voice Workbench / headless workbench (mocked backends) (push) Has been cancelled
Voice Workbench / real acoustic lane (nightly, provisioned only) (push) Has been cancelled
291 lines
13 KiB
YAML
291 lines
13 KiB
YAML
name: elizaOS Full OS Release
|
|
|
|
on:
|
|
release:
|
|
types: [created]
|
|
workflow_dispatch:
|
|
inputs:
|
|
publish:
|
|
description: Upload artifacts to release
|
|
type: boolean
|
|
default: false
|
|
|
|
# Default to least privilege. Override per-job where needed.
|
|
permissions:
|
|
contents: read
|
|
|
|
jobs:
|
|
# Compute the bare semver version string (no leading 'v') from the ref name.
|
|
# On a 'release' event github.ref_name is the tag (e.g. v2.0.1); we strip
|
|
# the prefix here so downstream jobs get a clean version like '2.0.1'.
|
|
prepare:
|
|
runs-on: ${{ fromJSON(vars.HETZNER_FLEET_ONLINE == 'false' && '["ubuntu-24.04"]' || '["self-hosted","hetzner-robot"]') }}
|
|
outputs:
|
|
version: ${{ steps.parse.outputs.version }}
|
|
tag: ${{ steps.parse.outputs.tag }}
|
|
steps:
|
|
- name: Parse version from ref
|
|
id: parse
|
|
run: |
|
|
TAG="${{ github.ref_name }}"
|
|
VERSION="${TAG#v}"
|
|
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
|
|
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
|
|
echo "Resolved: tag=$TAG version=$VERSION"
|
|
|
|
trigger-linux-iso:
|
|
uses: ./.github/workflows/build-linux-iso.yml
|
|
with:
|
|
channel: stable
|
|
publish: ${{ github.event_name == 'release' || inputs.publish == true }}
|
|
secrets: inherit
|
|
|
|
trigger-debian-package:
|
|
uses: ./.github/workflows/build-debian-package.yml
|
|
secrets: inherit
|
|
|
|
trigger-vm-image:
|
|
uses: ./.github/workflows/build-vm-image.yml
|
|
with:
|
|
format: ova
|
|
publish: ${{ github.event_name == 'release' || inputs.publish == true }}
|
|
secrets: inherit
|
|
|
|
verify-artifacts:
|
|
name: Verify build artifacts exist and are non-empty
|
|
needs: [trigger-linux-iso, trigger-debian-package, trigger-vm-image]
|
|
runs-on: ${{ fromJSON(vars.HETZNER_FLEET_ONLINE == 'false' && '["ubuntu-24.04"]' || '["self-hosted","hetzner-robot"]') }}
|
|
timeout-minutes: 10
|
|
steps:
|
|
- name: Download Linux ISO artifact
|
|
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c
|
|
with:
|
|
pattern: elizaos-live-iso-*
|
|
path: ./_verify/iso
|
|
merge-multiple: true
|
|
|
|
- name: Download Debian package artifact
|
|
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c
|
|
with:
|
|
name: elizaos-debian-package
|
|
path: ./_verify/deb
|
|
|
|
- name: Download VM image artifact
|
|
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c
|
|
with:
|
|
name: elizaos-vm-image
|
|
path: ./_verify/vm
|
|
|
|
- name: Assert artifacts present and non-empty
|
|
run: |
|
|
set -euo pipefail
|
|
fail=0
|
|
assert_nonempty() {
|
|
local pattern="$1"
|
|
local label="$2"
|
|
local match
|
|
match=$(find "$pattern" -type f \( -name "$3" \) -size +0c 2>/dev/null | head -1)
|
|
if [ -z "$match" ]; then
|
|
echo "ERROR: missing or empty $label artifact (pattern $3 under $pattern)"
|
|
fail=1
|
|
else
|
|
echo "OK: $label -> $match ($(stat --format=%s "$match") bytes)"
|
|
fi
|
|
}
|
|
assert_nonempty ./_verify/iso "Linux ISO" "*.iso"
|
|
assert_nonempty ./_verify/deb "Debian .deb" "*.deb"
|
|
assert_nonempty ./_verify/vm "VM image" "*.ova"
|
|
exit "$fail"
|
|
|
|
populate-and-validate-manifest:
|
|
name: Populate manifest checksums and gate on publishable validation
|
|
needs: [verify-artifacts]
|
|
runs-on: ${{ fromJSON(vars.HETZNER_FLEET_ONLINE == 'false' && '["ubuntu-24.04"]' || '["self-hosted","hetzner-robot"]') }}
|
|
timeout-minutes: 15
|
|
permissions:
|
|
# contents: write — required by softprops/action-gh-release to
|
|
# attach SHA256SUMS to the release asset list.
|
|
# id-token: write + attestations: write — required by
|
|
# actions/attest-build-provenance@v4 to mint a Sigstore-signed
|
|
# SLSA provenance attestation over SHA256SUMS via GitHub OIDC.
|
|
contents: write
|
|
id-token: write
|
|
attestations: write
|
|
steps:
|
|
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
|
|
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6
|
|
with:
|
|
bun-version: "canary"
|
|
- name: Download all release artifacts
|
|
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c
|
|
with:
|
|
path: ./_artifacts
|
|
merge-multiple: true
|
|
- name: Check manifest file exists
|
|
id: manifest_check
|
|
# The manifest file is hand-maintained per beta cycle. If it is
|
|
# missing (or got renamed without this workflow being updated)
|
|
# every downstream step would fail with ENOENT inside a Node
|
|
# readFileSync — a confusing 1-2 min failure with no clear call
|
|
# to action. Surface it explicitly so the maintainer either adds
|
|
# the manifest, updates this hardcoded path, or accepts the skip.
|
|
env:
|
|
MANIFEST_PATH: packages/os/release/beta-2026-05-16/manifest.json
|
|
run: |
|
|
if [ -f "$MANIFEST_PATH" ]; then
|
|
echo "can_validate_manifest=true" >> "$GITHUB_OUTPUT"
|
|
else
|
|
echo "::warning::Release manifest $MANIFEST_PATH not found. Manifest population + canonical SHA256SUMS + SLSA-over-SHA256SUMS attestation skipped. Per-artifact SLSA attestations from build-linux-iso.yml / build-debian-package.yml / build-vm-image.yml still mint correctly."
|
|
echo "can_validate_manifest=false" >> "$GITHUB_OUTPUT"
|
|
fi
|
|
- name: Populate manifest with real sha256 + sizes
|
|
if: steps.manifest_check.outputs.can_validate_manifest == 'true'
|
|
# Discovery is driven by the *manifest filename* — each entry's
|
|
# `filename` is searched verbatim under ./_artifacts. This keeps
|
|
# the workflow and manifest in lock-step: rename in the manifest,
|
|
# rename in the build, no workflow edits required.
|
|
#
|
|
# Build workflows that currently feed this step:
|
|
# - build-linux-iso.yml → *.iso (raw-linux-* entry)
|
|
# - build-vm-image.yml → *.qcow2, *.ova (vm-linux-* entry)
|
|
# Android (cf_x86_64, pixel-arm64) and macOS UTM bundles are NOT
|
|
# produced by any CI workflow today. They must be attached to the
|
|
# _artifacts staging dir out-of-band (release engineer uploads the
|
|
# built bundle as a workflow artifact via a prior manual job, or
|
|
# via release asset download) before this job runs. The strict
|
|
# gate at the end will fail loudly if any artifact is missing.
|
|
run: |
|
|
set -euo pipefail
|
|
MANIFEST=packages/os/release/beta-2026-05-16/manifest.json
|
|
ids=$(node -e '
|
|
const m = JSON.parse(require("node:fs").readFileSync(process.argv[1], "utf8"));
|
|
for (const a of m.artifacts) console.log(`${a.id}\t${a.filename}`);
|
|
' "$MANIFEST")
|
|
while IFS=$'\t' read -r id filename; do
|
|
path=$(find ./_artifacts -type f -name "$filename" | head -1 || true)
|
|
if [ -z "$path" ] || [ ! -f "$path" ]; then
|
|
echo "::warning::no artifact named $filename found for $id — strict gate will fail"
|
|
continue
|
|
fi
|
|
sha=$(sha256sum "$path" | cut -d' ' -f1)
|
|
size=$(stat --format=%s "$path")
|
|
node packages/os/scripts/update-release-manifest.mjs \
|
|
--manifest "$MANIFEST" \
|
|
--artifact "$id" \
|
|
--sha256 "$sha" \
|
|
--size "$size"
|
|
done <<< "$ids"
|
|
|
|
- name: Gate on publishable checksums (before status promotion)
|
|
if: steps.manifest_check.outputs.can_validate_manifest == 'true'
|
|
# Status promotion is gated on strict validation. If any artifact
|
|
# is missing a real checksum, the release stays "candidate" and
|
|
# this job fails — no half-published manifest.
|
|
run: |
|
|
node packages/os/scripts/validate-release-manifest.mjs \
|
|
--manifest packages/os/release/beta-2026-05-16/manifest.json \
|
|
--require-publishable-checksums
|
|
|
|
- name: Generate canonical SHA256SUMS via the in-repo tool
|
|
if: steps.manifest_check.outputs.can_validate_manifest == 'true'
|
|
# Runs BEFORE manifest promotion so that any failure here prevents
|
|
# the "available" status from being set and uploaded. SHA256SUMS
|
|
# generation is a hard prerequisite for promotion — closing the
|
|
# window where a promoted manifest could exist without a
|
|
# corresponding SHA256SUMS file or SLSA attestation.
|
|
#
|
|
# Calls packages/os/scripts/generate-release-checksums.mjs (which
|
|
# already exists, has unit tests under __tests__, and is the
|
|
# repo's canonical checksum tool) against the populated manifest
|
|
# + downloaded artifacts. Produces sha256sum -c compatible output
|
|
# mirroring the Debian / Fedora / Tails / Arch convention.
|
|
run: |
|
|
set -euo pipefail
|
|
node packages/os/scripts/generate-release-checksums.mjs \
|
|
--manifest packages/os/release/beta-2026-05-16/manifest.json \
|
|
--artifact-root ./_artifacts \
|
|
--output ./_artifacts/SHA256SUMS
|
|
echo "Generated SHA256SUMS:"
|
|
cat ./_artifacts/SHA256SUMS
|
|
|
|
- name: Attest SLSA build provenance over SHA256SUMS
|
|
if: steps.manifest_check.outputs.can_validate_manifest == 'true'
|
|
# Mints a single Sigstore-signed in-toto/SLSA provenance
|
|
# attestation that covers every release artifact via its hash,
|
|
# by attesting the canonical SHA256SUMS file generated above.
|
|
# Requires id-token: write + attestations: write (set in this
|
|
# job's permissions block). Users verify with:
|
|
#
|
|
# gh attestation verify SHA256SUMS --owner elizaOS
|
|
# sha256sum -c SHA256SUMS --ignore-missing
|
|
uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373
|
|
with:
|
|
subject-path: ./_artifacts/SHA256SUMS
|
|
|
|
- name: Upload SHA256SUMS artifact
|
|
if: steps.manifest_check.outputs.can_validate_manifest == 'true'
|
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a
|
|
with:
|
|
name: elizaos-release-checksums
|
|
path: ./_artifacts/SHA256SUMS
|
|
retention-days: 90
|
|
|
|
- name: Promote release status to available
|
|
if: steps.manifest_check.outputs.can_validate_manifest == 'true'
|
|
run: |
|
|
set -euo pipefail
|
|
node -e '
|
|
const fs = require("node:fs");
|
|
const p = "packages/os/release/beta-2026-05-16/manifest.json";
|
|
const m = JSON.parse(fs.readFileSync(p, "utf8"));
|
|
m.release.status = "available";
|
|
fs.writeFileSync(p, JSON.stringify(m, null, 2) + "\n");
|
|
'
|
|
|
|
- name: Upload populated manifest
|
|
if: steps.manifest_check.outputs.can_validate_manifest == 'true'
|
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a
|
|
with:
|
|
name: elizaos-os-release-manifest-published
|
|
path: packages/os/release/beta-2026-05-16/manifest.json
|
|
retention-days: 90
|
|
|
|
- name: Attach SHA256SUMS to release
|
|
if: github.event_name == 'release' && steps.manifest_check.outputs.can_validate_manifest == 'true'
|
|
uses: softprops/action-gh-release@718ea10b132b3b2eba29c1007bb80653f286566b
|
|
with:
|
|
files: ./_artifacts/SHA256SUMS
|
|
tag_name: ${{ github.event.release.tag_name || github.ref_name }}
|
|
env:
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
publish-apt:
|
|
needs: [prepare, trigger-debian-package, verify-artifacts]
|
|
if: needs.trigger-debian-package.result == 'success' && needs.verify-artifacts.result == 'success'
|
|
uses: ./.github/workflows/publish-apt-repo.yml
|
|
with:
|
|
version: ${{ needs.prepare.outputs.version }}
|
|
tag: ${{ needs.prepare.outputs.tag }}
|
|
channel: stable
|
|
secrets: inherit
|
|
|
|
summary:
|
|
needs: [trigger-linux-iso, trigger-debian-package, trigger-vm-image, verify-artifacts, populate-and-validate-manifest, publish-apt]
|
|
runs-on: ${{ fromJSON(vars.HETZNER_FLEET_ONLINE == 'false' && '["ubuntu-24.04"]' || '["self-hosted","hetzner-robot"]') }}
|
|
if: always()
|
|
timeout-minutes: 5
|
|
steps:
|
|
- name: Release summary
|
|
run: |
|
|
{
|
|
echo "## elizaOS OS Release Summary"
|
|
echo "| Artifact | Status |"
|
|
echo "| -------- | ------ |"
|
|
echo "| Linux ISO | ${{ needs.trigger-linux-iso.result }} |"
|
|
echo "| Debian .deb | ${{ needs.trigger-debian-package.result }} |"
|
|
echo "| VM Image | ${{ needs.trigger-vm-image.result }} |"
|
|
echo "| Verify artifacts | ${{ needs.verify-artifacts.result }} |"
|
|
echo "| Populate + gate manifest | ${{ needs.populate-and-validate-manifest.result }} |"
|
|
echo "| apt Repo | ${{ needs.publish-apt.result }} |"
|
|
} >> "$GITHUB_STEP_SUMMARY"
|