|
|
|
@@ -13,99 +13,115 @@ name: template-delivery-e2e
|
|
|
|
|
# /configs/plugins/seo-all/. The e2e asserts the skill arrives via the
|
|
|
|
|
# PLUGIN channel and NOT the asset channel (negative control).
|
|
|
|
|
#
|
|
|
|
|
# STAGED ROLLOUT (do NOT make required until green):
|
|
|
|
|
# Phase 1 (done): advisory — runs on the relevant paths + main + dispatch.
|
|
|
|
|
# Asserts the new two-channel contract.
|
|
|
|
|
# Phase 2a (THIS change, mc#2996): HARDEN the asset-channel assertions so the
|
|
|
|
|
# gate is reliable enough to make required. The C (config.yaml)
|
|
|
|
|
# + D (prompts) checks now poll within E2E_ASSET_SETTLE_SECS: a
|
|
|
|
|
# freshly-online tenant's /configs inspection endpoint can be
|
|
|
|
|
# transiently slow / time out the first read (the 9c2161d red was
|
|
|
|
|
# `curl: (28) ... 0 bytes` → config read as size 0, a FALSE stub,
|
|
|
|
|
# not a real delivery failure). A genuine stub still fails after
|
|
|
|
|
# the budget. continue-on-error STAYS in this PR — the flip is
|
|
|
|
|
# gated by lint-pre-flip-continue-on-error on recent green main
|
|
|
|
|
# runs, which this hardening produces.
|
|
|
|
|
# Phase 2b (follow-up, after 2a is green on main): remove continue-on-error and
|
|
|
|
|
# add the emitted context to branch protection
|
|
|
|
|
# required_status_checks → a delivery regression is merge-blocking.
|
|
|
|
|
# STAGED ROLLOUT (now COMPLETE — this gate is merge-blocking):
|
|
|
|
|
# Phase 1 (done): advisory — asserted the new two-channel contract.
|
|
|
|
|
# Phase 2a (done, f6155d68): HARDENED the asset-channel assertions (C
|
|
|
|
|
# config.yaml, D prompts) to poll within E2E_ASSET_SETTLE_SECS,
|
|
|
|
|
# killing the false stub from a transient /configs read
|
|
|
|
|
# (`curl: (28) ... 0 bytes`). Banked a green main run, which
|
|
|
|
|
# lint-pre-flip-continue-on-error requires before the flip.
|
|
|
|
|
# Phase 2b (THIS change, mc#2996): FLIP to merge-blocking —
|
|
|
|
|
# • continue-on-error removed → a real delivery regression fails;
|
|
|
|
|
# • `on: paths:` removed (required workflows must not be
|
|
|
|
|
# path-filtered); path-scoping moved to the detect-changes job
|
|
|
|
|
# (profile `template-delivery`) and applied per-step;
|
|
|
|
|
# • the emitted context is added to .gitea/required-contexts.txt
|
|
|
|
|
# and to branch-protection required_status_checks (as
|
|
|
|
|
# "... (pull_request)") so a delivery PR cannot merge unless a
|
|
|
|
|
# fresh seo-agent provisions and BOTH channels verify.
|
|
|
|
|
#
|
|
|
|
|
# Cost: provisions ONE throwaway tenant + ONE seo-agent (real EC2), teardown
|
|
|
|
|
# trap deletes the org even on failure. Path-filtered so it only runs when the
|
|
|
|
|
# delivery code actually changes.
|
|
|
|
|
# trap deletes the org even on failure. The workflow has NO `on: paths:` filter:
|
|
|
|
|
# a REQUIRED-check workflow must not carry one (lint-required-no-paths.py /
|
|
|
|
|
# feedback_path_filtered_workflow_cant_be_required — a docs-only PR would never
|
|
|
|
|
# emit the context, Gitea reports it `pending`, and the PR wedges forever).
|
|
|
|
|
# Instead the detect-changes job applies the same path-scoping at RUNTIME, and
|
|
|
|
|
# the delivery job's real steps are gated on its output: a non-delivery PR emits
|
|
|
|
|
# SUCCESS cheaply (no provision), while a delivery PR runs the full e2e and
|
|
|
|
|
# BLOCKS on failure. Mirrors the e2e-api / peer-visibility required-gate shape.
|
|
|
|
|
|
|
|
|
|
on:
|
|
|
|
|
workflow_dispatch: {}
|
|
|
|
|
push:
|
|
|
|
|
branches: [main]
|
|
|
|
|
paths:
|
|
|
|
|
- 'workspace-server/internal/provisioner/template_assets.go'
|
|
|
|
|
- 'workspace-server/internal/provisioner/gitea_template_assets.go'
|
|
|
|
|
- 'workspace-server/internal/provisioner/cp_provisioner.go'
|
|
|
|
|
- 'workspace-server/internal/handlers/platform_agent.go'
|
|
|
|
|
- 'workspace-server/cmd/server/main.go'
|
|
|
|
|
- 'workspace-server/internal/handlers/org_import.go'
|
|
|
|
|
- 'workspace-server/internal/handlers/workspace.go'
|
|
|
|
|
- 'workspace-server/internal/handlers/template_plugins.go'
|
|
|
|
|
- 'workspace-server/internal/handlers/plugins_reconcile.go'
|
|
|
|
|
- 'workspace-server/internal/handlers/registry.go'
|
|
|
|
|
- 'workspace-server/internal/handlers/plugins_install_pipeline.go'
|
|
|
|
|
- 'workspace-server/internal/handlers/plugins_tracking.go'
|
|
|
|
|
- 'workspace-server/internal/plugins/source.go'
|
|
|
|
|
- 'manifest.json'
|
|
|
|
|
- 'tests/e2e/test_template_delivery_e2e.sh'
|
|
|
|
|
- '.gitea/workflows/template-delivery-e2e.yml'
|
|
|
|
|
pull_request:
|
|
|
|
|
paths:
|
|
|
|
|
- 'workspace-server/internal/provisioner/template_assets.go'
|
|
|
|
|
- 'workspace-server/internal/provisioner/gitea_template_assets.go'
|
|
|
|
|
- 'workspace-server/internal/provisioner/cp_provisioner.go'
|
|
|
|
|
- 'workspace-server/internal/handlers/platform_agent.go'
|
|
|
|
|
- 'workspace-server/cmd/server/main.go'
|
|
|
|
|
- 'workspace-server/internal/handlers/org_import.go'
|
|
|
|
|
- 'workspace-server/internal/handlers/workspace.go'
|
|
|
|
|
- 'workspace-server/internal/handlers/template_plugins.go'
|
|
|
|
|
- 'workspace-server/internal/handlers/plugins_reconcile.go'
|
|
|
|
|
- 'workspace-server/internal/handlers/registry.go'
|
|
|
|
|
- 'workspace-server/internal/handlers/plugins_install_pipeline.go'
|
|
|
|
|
- 'workspace-server/internal/handlers/plugins_tracking.go'
|
|
|
|
|
- 'workspace-server/internal/plugins/source.go'
|
|
|
|
|
- 'manifest.json'
|
|
|
|
|
- 'tests/e2e/test_template_delivery_e2e.sh'
|
|
|
|
|
- '.gitea/workflows/template-delivery-e2e.yml'
|
|
|
|
|
branches: [main]
|
|
|
|
|
|
|
|
|
|
concurrency:
|
|
|
|
|
group: template-delivery-e2e-${{ github.ref }}
|
|
|
|
|
cancel-in-progress: true
|
|
|
|
|
group: template-delivery-e2e-${{ github.event.pull_request.head.sha || github.sha }}
|
|
|
|
|
cancel-in-progress: false
|
|
|
|
|
|
|
|
|
|
jobs:
|
|
|
|
|
# Job renamed for the RFC#2843 #32 two-channel contract (config+prompts via
|
|
|
|
|
# the asset channel; seo-all installs via the post-online plugin reconcile,
|
|
|
|
|
# not at boot). Renaming the job changes the emitted status context.
|
|
|
|
|
# bp-exempt: Phase 2a — still advisory (continue-on-error) while the hardened
|
|
|
|
|
# asset assertions bank green main runs; lint-pre-flip-continue-on-error then
|
|
|
|
|
# permits the Phase-2b flip + branch-protection add (mc#2996).
|
|
|
|
|
# Runtime path-scoping (replaces the removed `on: paths:`). Mirrors the
|
|
|
|
|
# e2e-api / peer-visibility detect-changes shape. Outputs `delivery=true`
|
|
|
|
|
# when the diff touches the delivery surface; the gate job runs the real e2e
|
|
|
|
|
# only then. bp-exempt: helper job; the REQUIRED context is the `delivery`
|
|
|
|
|
# job below, not this one.
|
|
|
|
|
detect-changes:
|
|
|
|
|
runs-on: ubuntu-latest
|
|
|
|
|
continue-on-error: false
|
|
|
|
|
outputs:
|
|
|
|
|
delivery: ${{ steps.decide.outputs.delivery }}
|
|
|
|
|
debug: ${{ steps.decide.outputs.debug }}
|
|
|
|
|
steps:
|
|
|
|
|
- uses: actions/checkout@v4
|
|
|
|
|
with:
|
|
|
|
|
fetch-depth: 0
|
|
|
|
|
- id: decide
|
|
|
|
|
env:
|
|
|
|
|
PR_BASE_SHA: ${{ github.event.pull_request.base.sha }}
|
|
|
|
|
PR_BASE_REF: ${{ github.event.pull_request.base.ref }}
|
|
|
|
|
PUSH_BEFORE: ${{ github.event.before }}
|
|
|
|
|
run: |
|
|
|
|
|
python3 .gitea/scripts/detect-changes.py \
|
|
|
|
|
--profile template-delivery \
|
|
|
|
|
--event-name "${{ github.event_name }}" \
|
|
|
|
|
--pr-base-sha "$PR_BASE_SHA" \
|
|
|
|
|
--base-ref "$PR_BASE_REF" \
|
|
|
|
|
--push-before "$PUSH_BEFORE" || {
|
|
|
|
|
# Script crash → fail OPEN so the gate runs rather than silently
|
|
|
|
|
# no-oping a potentially-breaking delivery PR.
|
|
|
|
|
echo "delivery=true" >> "$GITHUB_OUTPUT"
|
|
|
|
|
echo "debug=detect-script-error event=${{ github.event_name }}" >> "$GITHUB_OUTPUT"
|
|
|
|
|
exit 0
|
|
|
|
|
}
|
|
|
|
|
echo "debug=profile=template-delivery event=${{ github.event_name }}" >> "$GITHUB_OUTPUT"
|
|
|
|
|
|
|
|
|
|
# ONE job (no job-level `if:`) that ALWAYS runs and reports under the
|
|
|
|
|
# required-check name. Real work is gated per-step on
|
|
|
|
|
# `needs.detect-changes.outputs.delivery` — a non-delivery PR runs only the
|
|
|
|
|
# no-op step and emits SUCCESS (branch-protection-clean; a job-level `if:`
|
|
|
|
|
# would emit a SKIPPED check run that fails the required-check eval — see
|
|
|
|
|
# e2e-api.yml's PR#2264 note). A delivery PR runs the full e2e and, with no
|
|
|
|
|
# continue-on-error, BLOCKS the merge on failure.
|
|
|
|
|
# bp-required: yes — mc#2996 / RFC#2843 #37: this context is merge-blocking;
|
|
|
|
|
# branch protection lists "<this> (pull_request)".
|
|
|
|
|
delivery:
|
|
|
|
|
needs: detect-changes
|
|
|
|
|
# No colon in the name — lint-required-context's PyYAML AST parse rejects an
|
|
|
|
|
# unquoted scalar containing a colon.
|
|
|
|
|
name: Template-asset delivery (fresh seo-agent — config+prompts via asset channel, seo-all via plugin reconcile)
|
|
|
|
|
runs-on: ubuntu-latest
|
|
|
|
|
# Phase 2a: STILL advisory. The flip to required (remove this line + add to
|
|
|
|
|
# branch protection) is Phase 2b, gated by lint-pre-flip-continue-on-error on
|
|
|
|
|
# the green main runs this hardening produces. mc#2996.
|
|
|
|
|
continue-on-error: true # mc#2996
|
|
|
|
|
timeout-minutes: 30
|
|
|
|
|
env:
|
|
|
|
|
MOLECULE_CP_URL: ${{ vars.CP_URL || 'https://staging-api.moleculesai.app' }}
|
|
|
|
|
MOLECULE_ADMIN_TOKEN: ${{ secrets.CP_ADMIN_API_TOKEN }}
|
|
|
|
|
E2E_EXPECTED_MODEL: moonshot/kimi-k2.6
|
|
|
|
|
steps:
|
|
|
|
|
- uses: actions/checkout@v4
|
|
|
|
|
- name: No-op pass (delivery surface unchanged in this diff)
|
|
|
|
|
if: needs.detect-changes.outputs.delivery != 'true'
|
|
|
|
|
run: |
|
|
|
|
|
echo "No delivery-surface changes — gate satisfied without provisioning."
|
|
|
|
|
echo "::notice::template-delivery-e2e no-op pass (detect-changes: ${{ needs.detect-changes.outputs.debug }})."
|
|
|
|
|
- if: needs.detect-changes.outputs.delivery == 'true'
|
|
|
|
|
uses: actions/checkout@v4
|
|
|
|
|
- name: Verify required secret present
|
|
|
|
|
if: needs.detect-changes.outputs.delivery == 'true'
|
|
|
|
|
run: |
|
|
|
|
|
if [ -z "${MOLECULE_ADMIN_TOKEN:-}" ]; then
|
|
|
|
|
echo "::error::CP_ADMIN_API_TOKEN secret not set — cannot run delivery e2e"
|
|
|
|
|
exit 2
|
|
|
|
|
fi
|
|
|
|
|
- name: Run template-asset delivery e2e
|
|
|
|
|
if: needs.detect-changes.outputs.delivery == 'true'
|
|
|
|
|
run: bash tests/e2e/test_template_delivery_e2e.sh
|
|
|
|
|