ci: one CI path — .hanzo/workflows
Gitea collects workflows from the FIRST of WORKFLOW_DIRS that exists in the
pushed commit and ignores the rest (modules/actions/workflows.go,
listWorkflowsInDirs breaks on the first hit), so creating .hanzo/workflows
switches .github/workflows off wholesale — no run, no queued job, no error.
Every file therefore moves or dies in this one commit; nothing is left to look
like a fallback it could not be.
MIGRATED, unchanged apart from the label form and the notes below:
ci.yml (the Layer-2 deploy + E2E orchestrator), build-service.yml (the Layer-1
reusable), service-released.yml and update-image.yml (the two repository_dispatch
auto-bump shapes). Their runner label was already right — zoo-build-linux-amd64
is what the fleet advertises — and is now written in the list form the rest of
the fleet uses.
FIXED — service-released.yml HAS NEVER PARSED. Its `gh pr create --body`
markdown table sat at column 0 inside a block scalar indented to column 10, so
the scalar terminated at the table and the `|` was read as a second block
indicator:
yaml.scanner.ScannerError: while scanning a block scalar
expected a comment or a line break, but found 'f' (line 132, col 3)
That is why every single run of it is a failure. The table is now indented into
the scalar, which YAML strips back off, so the shell and the rendered PR body
are byte-identical to what was intended and the file loads.
DELETED — renovate.yml, and renovate.json with it. A `*/15 * * * *` cron, so 96
runs a day against the shared amd64 pool, for an inherited dependency bot we do
not use; it was measured at 83 runs in the last 24 hours, more than any real
pipeline on this forge. Its config file goes too rather than sit behind a bot
that is not there.
The reusable's PATH is part of its contract, so moving it is a caller-visible
change: services/actions.ResolveUses enforces the WORKFLOW_DIRS allowlist on
`uses:` paths, which means .github/workflows would have stopped resolving at the
narrowing anyway. Searched across the zooai org by both spellings — zoolabs/ and
zooai/ — and nothing outside this repo referenced it; the only hits were the
file itself and a comment in ci.yml. Callers now use
zooai/universe/.hanzo/workflows/build-service.yml@main.
build-push's matrix no longer carries the runner label. It still carries `arch`,
which is part of the published image tag (…-amd64), but which label the fleet
advertises is a fleet fact rather than a tag fact, and behind
${{ matrix.runner }} the one thing worth grepping for could not be grepped.
Concurrency groups added where they were missing: one in-flight bump per
service, never cancelled between `git push` and `gh pr create`, and one build
per calling service so two services do not serialise behind each other.
Co-authored-by: Hanzo Dev <[email protected]>
This commit is contained in:
@@ -1,20 +0,0 @@
|
||||
name: Renovate
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '*/15 * * * *'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
renovate:
|
||||
runs-on: zoo-build-linux-amd64
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: renovatebot/github-action@v41
|
||||
with:
|
||||
configurationFile: renovate.json
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -1,11 +1,20 @@
|
||||
# Reusable workflow: Lint + Test + Build + Push for a single service.
|
||||
#
|
||||
# Called from each service repo:
|
||||
# uses: zoolabs/universe/.github/workflows/build-service.yml@main
|
||||
# uses: zooai/universe/.hanzo/workflows/build-service.yml@main
|
||||
# with:
|
||||
# service_key: zoo-ngo
|
||||
# app_name: zoo-ngo
|
||||
#
|
||||
# THE PATH IS PART OF THE CONTRACT, and it moved with the rest of this repo's
|
||||
# CI. A reusable is resolved through services/actions.ResolveUses, which
|
||||
# enforces the WORKFLOW_DIRS allowlist on the referenced path, so a `uses:`
|
||||
# naming .github/workflows stops resolving the moment that list narrows to
|
||||
# .hanzo/workflows alone. Nothing outside this repo referenced the old path when
|
||||
# it moved — searched across the zooai org by both spellings, zoolabs/ and
|
||||
# zooai/, and the only hits were this file and a comment in ci.yml. A caller
|
||||
# added since uses the path above.
|
||||
#
|
||||
# Layer 1 of 2-layer CI defense:
|
||||
# Layer 1 (this): unit tests + lint per service
|
||||
# Layer 2 (ci.yml): full E2E across all services in universe
|
||||
@@ -52,10 +61,17 @@ permissions:
|
||||
packages: write
|
||||
id-token: write
|
||||
|
||||
# Keyed on the calling service and its ref, so two services never serialise
|
||||
# behind each other. Not cancellable: a superseded run may already have pushed a
|
||||
# layer under the tag it was given.
|
||||
concurrency:
|
||||
group: build-service-${{ inputs.service_key }}-${{ github.ref }}
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
lint-test:
|
||||
name: Lint + Test
|
||||
runs-on: zoo-build-linux-amd64
|
||||
runs-on: [zoo-build-linux-amd64]
|
||||
if: ${{ !inputs.skip_tests }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@@ -118,13 +134,18 @@ jobs:
|
||||
# amd64 only. arm64 paused — DOKS does not currently offer arm64
|
||||
# droplets. See ~/work/zoo/universe/LLM.md and shared Docker Build
|
||||
# Standard for re-enable conditions.
|
||||
#
|
||||
# The matrix carries `arch` because it is part of the published image tag
|
||||
# (…-amd64). It no longer carries the runner: which label the fleet
|
||||
# advertises is a fleet fact, not a tag fact, and hiding it behind
|
||||
# ${{ matrix.runner }} makes the one thing worth grepping for ungreppable.
|
||||
# Re-enabling arm64 means a second matrix entry AND a runner that
|
||||
# advertises the arm64 label — the two are not the same decision.
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- arch: amd64
|
||||
runner: zoo-build-linux-amd64
|
||||
runs-on: ${{ matrix.runner }}
|
||||
arch: [amd64]
|
||||
runs-on: [zoo-build-linux-amd64]
|
||||
needs: [lint-test]
|
||||
if: always() && (needs.lint-test.result == 'success' || needs.lint-test.result == 'skipped') && (github.event_name == 'push' || github.event_name == 'workflow_dispatch')
|
||||
outputs:
|
||||
@@ -1,5 +1,12 @@
|
||||
# Universe CI -- Layer 2 Orchestrator
|
||||
#
|
||||
# Runs from .hanzo/workflows, which is the one directory this forge collects.
|
||||
# Gitea takes the FIRST of WORKFLOW_DIRS that exists in the pushed commit and
|
||||
# ignores the rest (modules/actions/workflows.go, listWorkflowsInDirs breaks on
|
||||
# the first hit), so this directory and .github/workflows were never going to
|
||||
# coexist: creating one switches the other off silently, with no run, no queued
|
||||
# job and no error. Everything this repo still wants moved here in one commit.
|
||||
#
|
||||
# Two modes:
|
||||
# 1. service-built (repository_dispatch): A single service was built + tested.
|
||||
# Update manifest, deploy that service, run smoke test.
|
||||
@@ -23,7 +30,7 @@ on:
|
||||
paths:
|
||||
- 'manifests/**'
|
||||
- 'scripts/**'
|
||||
- '.github/workflows/ci.yml'
|
||||
- '.hanzo/workflows/ci.yml'
|
||||
- 'e2e/**'
|
||||
|
||||
workflow_dispatch:
|
||||
@@ -67,7 +74,7 @@ jobs:
|
||||
# ============================================================
|
||||
resolve:
|
||||
name: Resolve Environment
|
||||
runs-on: zoo-build-linux-amd64
|
||||
runs-on: [zoo-build-linux-amd64]
|
||||
outputs:
|
||||
environment: ${{ steps.env.outputs.environment }}
|
||||
namespace: ${{ steps.env.outputs.namespace }}
|
||||
@@ -125,7 +132,7 @@ jobs:
|
||||
# ============================================================
|
||||
update-manifest:
|
||||
name: Update Manifest
|
||||
runs-on: zoo-build-linux-amd64
|
||||
runs-on: [zoo-build-linux-amd64]
|
||||
needs: resolve
|
||||
if: needs.resolve.outputs.mode == 'deploy-single'
|
||||
steps:
|
||||
@@ -213,7 +220,7 @@ jobs:
|
||||
|
||||
deploy-single:
|
||||
name: Deploy ${{ needs.resolve.outputs.service_key }}
|
||||
runs-on: zoo-build-linux-amd64
|
||||
runs-on: [zoo-build-linux-amd64]
|
||||
needs: [resolve]
|
||||
if: needs.resolve.outputs.mode == 'deploy-single' && github.event_name == 'push'
|
||||
environment: ${{ needs.resolve.outputs.environment }}
|
||||
@@ -290,7 +297,7 @@ jobs:
|
||||
# ============================================================
|
||||
deploy-all:
|
||||
name: Deploy All Services
|
||||
runs-on: zoo-build-linux-amd64
|
||||
runs-on: [zoo-build-linux-amd64]
|
||||
needs: [resolve]
|
||||
if: needs.resolve.outputs.mode == 'deploy-all'
|
||||
environment: ${{ needs.resolve.outputs.environment }}
|
||||
@@ -350,7 +357,7 @@ jobs:
|
||||
# ============================================================
|
||||
e2e:
|
||||
name: E2E
|
||||
runs-on: zoo-build-linux-amd64
|
||||
runs-on: [zoo-build-linux-amd64]
|
||||
needs: [resolve, deploy-all]
|
||||
if: always() && (needs.resolve.outputs.mode == 'deploy-all' || needs.resolve.outputs.mode == 'e2e-only') && needs.resolve.result == 'success'
|
||||
timeout-minutes: 25
|
||||
@@ -6,7 +6,7 @@
|
||||
# 2. Opens a PR: auto-bump/<service>-<version>
|
||||
# 3. Enables auto-merge (squash) — merges on green CI
|
||||
#
|
||||
# Companion to .github/workflows/update-image.yml which handles the older
|
||||
# Companion to .hanzo/workflows/update-image.yml which handles the older
|
||||
# `image-published` dispatch shape (kept for repos that haven't migrated).
|
||||
# New service repos should dispatch a per-service event type listed below.
|
||||
|
||||
@@ -32,10 +32,17 @@ permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
# Per service, not per version: two dispatches for the same service must not
|
||||
# race each other onto the same auto-bump branch. Not cancellable — a cancelled
|
||||
# run can leave a pushed branch with no PR on it.
|
||||
concurrency:
|
||||
group: service-released-${{ github.event.action }}
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
auto-bump:
|
||||
name: "Bump ${{ github.event.action }} → ${{ github.event.client_payload.version }}"
|
||||
runs-on: zoo-build-linux-amd64
|
||||
runs-on: [zoo-build-linux-amd64]
|
||||
steps:
|
||||
- name: Validate payload
|
||||
run: |
|
||||
@@ -129,13 +136,13 @@ jobs:
|
||||
--title "chore(deps): bump ${SERVICE} to ${VERSION}" \
|
||||
--body "Auto-bump from zooai/${SERVICE} release.
|
||||
|
||||
| field | value |
|
||||
|---------|-------|
|
||||
| service | \`${SERVICE}\` |
|
||||
| version | \`${VERSION}\` |
|
||||
| image | \`${IMAGE}\` |
|
||||
| sha | \`${SHA}\` |
|
||||
" \
|
||||
| field | value |
|
||||
|---------|-------|
|
||||
| service | \`${SERVICE}\` |
|
||||
| version | \`${VERSION}\` |
|
||||
| image | \`${IMAGE}\` |
|
||||
| sha | \`${SHA}\` |
|
||||
" \
|
||||
--label "auto-bump" \
|
||||
--base main 2>&1 | tail -1)
|
||||
|
||||
@@ -8,9 +8,15 @@ permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
# Same reasoning as service-released.yml: one in-flight bump per service, and
|
||||
# never cancelled midway between `git push` and `gh pr create`.
|
||||
concurrency:
|
||||
group: update-image-${{ github.event.client_payload.service }}
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
update:
|
||||
runs-on: zoo-build-linux-amd64
|
||||
runs-on: [zoo-build-linux-amd64]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": ["config:recommended"],
|
||||
"enabledManagers": ["kubernetes", "custom.regex"],
|
||||
"kubernetes": {
|
||||
"fileMatch": ["(^k8s|^infra/k8s)/.+\\.yaml$"]
|
||||
},
|
||||
"customManagers": [
|
||||
{
|
||||
"customType": "regex",
|
||||
"fileMatch": ["^manifests/.*\\.yml$", "compose.*\\.yml$", "(^k8s|^infra/k8s)/.+\\.yaml$"],
|
||||
"matchStrings": [
|
||||
"image:\\s*(?<depName>[\\w.\\-/]+):(?<currentValue>[\\w][\\w.\\-]+)"
|
||||
],
|
||||
"datasourceTemplate": "docker",
|
||||
"versioningTemplate": "docker"
|
||||
}
|
||||
],
|
||||
"packageRules": [
|
||||
{
|
||||
"description": "Group all image updates into a single PR",
|
||||
"matchDatasources": ["docker"],
|
||||
"groupName": "docker-images",
|
||||
"groupSlug": "docker-images",
|
||||
"automerge": false,
|
||||
"labels": ["dependencies", "docker"]
|
||||
},
|
||||
{
|
||||
"description": "Auto-merge patch updates for internal images",
|
||||
"matchDatasources": ["docker"],
|
||||
"matchPackagePatterns": ["ghcr.io/(hanzoai|luxfi|zooai)/.*"],
|
||||
"matchUpdateTypes": ["patch"],
|
||||
"automerge": true,
|
||||
"automergeType": "pr"
|
||||
},
|
||||
{
|
||||
"description": "Major versions require review",
|
||||
"matchDatasources": ["docker"],
|
||||
"matchUpdateTypes": ["major"],
|
||||
"automerge": false,
|
||||
"labels": ["major-upgrade"]
|
||||
},
|
||||
{
|
||||
"description": "Ignore ARC runner images",
|
||||
"matchPackagePatterns": ["ghcr.io/actions/actions-runner"],
|
||||
"enabled": false
|
||||
},
|
||||
{
|
||||
"description": "Pin digests for deterministic deploys",
|
||||
"matchDatasources": ["docker"],
|
||||
"pinDigests": true
|
||||
}
|
||||
],
|
||||
"schedule": ["every 15 minutes"],
|
||||
"prHourlyLimit": 10,
|
||||
"prConcurrentLimit": 3,
|
||||
"rebaseWhen": "behind-base-branch",
|
||||
"labels": ["renovate", "dependencies"]
|
||||
}
|
||||
Reference in New Issue
Block a user