Skip to content

feat: exercise no-env orchestration 20260703073815-28645931346 #31

feat: exercise no-env orchestration 20260703073815-28645931346

feat: exercise no-env orchestration 20260703073815-28645931346 #31

Workflow file for this run

# AUTO-GENERATED by cascade - DO NOT EDIT MANUALLY
# Regenerate with: cascade generate-workflow --config .github/manifest.yaml
name: Orchestrate CI/CD
on:
push:
branches: [main]
paths:
- 'src/**'
workflow_dispatch:
inputs:
dry_run:
description: 'Dry run mode'
type: boolean
default: false
concurrency:
group: orchestrate-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
actions: read
jobs:
setup:
name: Setup
runs-on: ubuntu-latest
timeout-minutes: 30
outputs:
run_build_lib: ${{ steps.setup.outputs.run_build_lib }}
head_sha: ${{ steps.setup.outputs.head_sha }}
version: ${{ steps.setup.outputs.version }}
previous_tag: ${{ steps.setup.outputs.previous_tag }}
changelog_base_sha: ${{ steps.setup.outputs.changelog_base_sha }}
base_build_lib: ${{ steps.setup.outputs.base_build_lib }}
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0
- name: Setup CLI
uses: stablekernel/cascade/.github/actions/setup-cli@v0.7.0-rc.0
with:
token: ${{ secrets.CASCADE_STATE_TOKEN }}
version: v0.7.0-rc.0
- name: Run Setup
id: setup
run: |
cascade orchestrate setup \
--config .github/manifest.yaml \
--gha-output
build-lib:
name: Build (lib)
needs: [setup]
if: |
needs.setup.outputs.run_build_lib == 'true'
uses: ./.github/workflows/build-lib.yaml
with:
sha: ${{ needs.setup.outputs.head_sha }}
finalize:
name: Finalize
needs: [setup, build-lib]
if: always() && needs.setup.result == 'success'
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: write
outputs:
lib_artifact: ${{ needs.build-lib.outputs.artifact }}
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0
- name: Generate Summary
run: |
echo "## Orchestration Complete" >> "$GITHUB_STEP_SUMMARY"
echo "" >> "$GITHUB_STEP_SUMMARY"
echo "### Callback Results" >> "$GITHUB_STEP_SUMMARY"
echo "| Callback | Result | On Failure |" >> "$GITHUB_STEP_SUMMARY"
echo "|----------|--------|------------|" >> "$GITHUB_STEP_SUMMARY"
echo "| Build (lib) | ${{ needs.build-lib.result }} | abort |" >> "$GITHUB_STEP_SUMMARY"
echo "" >> "$GITHUB_STEP_SUMMARY"
echo "### Outputs" >> "$GITHUB_STEP_SUMMARY"
HAS_OUTPUTS=false
if [[ -n "${{ needs.build-lib.outputs.artifact }}" ]]; then
if [[ "$HAS_OUTPUTS" == "false" ]]; then
echo "| Output | Value |" >> "$GITHUB_STEP_SUMMARY"
echo "|--------|-------|" >> "$GITHUB_STEP_SUMMARY"
HAS_OUTPUTS=true
fi
echo "| lib_artifact | ${{ needs.build-lib.outputs.artifact }} |" >> "$GITHUB_STEP_SUMMARY"
fi
if [[ "$HAS_OUTPUTS" == "false" ]]; then
echo "_No outputs produced_" >> "$GITHUB_STEP_SUMMARY"
fi
- name: Setup CLI
uses: stablekernel/cascade/.github/actions/setup-cli@v0.7.0-rc.0
with:
token: ${{ secrets.CASCADE_STATE_TOKEN }}
version: v0.7.0-rc.0
- name: Generate Changelog
id: changelog
env:
GH_TOKEN: ${{ secrets.CASCADE_STATE_TOKEN }}
run: |
# Use changelog_base_sha which compares this env to next env
# This shows commits in this env NOT yet promoted to next env
RESULT=$(cascade generate-changelog \
--base-sha "${{ needs.setup.outputs.changelog_base_sha }}" \
--head-sha "${{ needs.setup.outputs.head_sha }}" \
--contributors \
--repo "${{ github.repository }}")
echo "changelog<<EOF" >> "$GITHUB_OUTPUT"
echo "$RESULT" | jq -r '.changelog' >> "$GITHUB_OUTPUT"
echo "EOF" >> "$GITHUB_OUTPUT"
- name: Manage Release
uses: ./.github/actions/manage-release
with:
repo: ${{ github.repository }}
action: update
tag: ${{ needs.setup.outputs.version }}
create_tag: 'true'
environment: prerelease
sha: ${{ needs.setup.outputs.head_sha }}
changelog: ${{ steps.changelog.outputs.changelog }}
previous_tag: ${{ needs.setup.outputs.previous_tag }}
token: ${{ secrets.CASCADE_STATE_TOKEN }}
- name: Update Manifest
env:
GH_TOKEN: ${{ secrets.CASCADE_STATE_TOKEN }}
HEAD_SHA: ${{ needs.setup.outputs.head_sha }}
VERSION: ${{ needs.setup.outputs.version }}
run: |
MANIFEST_FILE=".github/manifest.yaml"
MANIFEST_KEY="ci"
if [[ ! -f "$MANIFEST_FILE" ]]; then
echo "No $MANIFEST_FILE found - skipping state update"
exit 0
fi
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
BRANCH="${GITHUB_REF##refs/heads/}"
apply_state_edits() {
TIMESTAMP=$(date -u +%Y-%m-%dT%H:%M:%SZ)
# Update state under prerelease key (no environments)
yq eval -i ".$MANIFEST_KEY.state.prerelease.sha = \"$HEAD_SHA\"" "$MANIFEST_FILE"
yq eval -i ".$MANIFEST_KEY.state.prerelease.version = \"$VERSION\"" "$MANIFEST_FILE"
yq eval -i ".$MANIFEST_KEY.state.prerelease.committed_at = \"$TIMESTAMP\"" "$MANIFEST_FILE"
yq eval -i ".$MANIFEST_KEY.state.prerelease.committed_by = \"${{ github.actor }}\"" "$MANIFEST_FILE"
}
if [[ "$GITHUB_SERVER_URL" != "https://github.com" ]]; then
# act/gitea e2e: no GitHub API, and the trunk is neither protected nor
# signature-checked, so push the state commit directly with retries.
for attempt in 1 2 3 4 5; do
git fetch origin "$BRANCH"
git reset --hard "origin/$BRANCH"
apply_state_edits
if git diff --quiet "$MANIFEST_FILE"; then
echo "No state changes"
exit 0
fi
git add "$MANIFEST_FILE"
git commit -m "chore: update state [skip ci]"
if git push origin "HEAD:$BRANCH"; then
echo "Pushed state on attempt $attempt"
exit 0
fi
echo "Push attempt $attempt rejected (likely concurrent run); retrying..." >&2
sleep $((RANDOM % 5 + 2))
done
echo "::error::Failed to push state after 5 attempts" >&2
exit 1
fi
# Real GitHub: write state through the Contents REST API. API commits are
# signed by GitHub (Verified) and, with a bypass-capable token, update the
# trunk even when a required status check protects it.
for attempt in 1 2 3 4 5; do
git fetch origin "$BRANCH"
git reset --hard "origin/$BRANCH"
apply_state_edits
if git diff --quiet "$MANIFEST_FILE"; then
echo "No state changes"
exit 0
fi
CONTENT_B64=$(base64 -w0 "$MANIFEST_FILE" 2>/dev/null || base64 "$MANIFEST_FILE" | tr -d '\n')
CURRENT_SHA=$(gh api "repos/${{ github.repository }}/contents/$MANIFEST_FILE?ref=$BRANCH" --jq '.sha' 2>/dev/null || true)
API_ARGS=("repos/${{ github.repository }}/contents/$MANIFEST_FILE" -X PUT
-f "message=chore: update state [skip ci]"
-f "content=$CONTENT_B64"
-f "branch=$BRANCH"
-f "author[name]=github-actions[bot]"
-f "author[email]=github-actions[bot]@users.noreply.github.com"
-f "committer[name]=github-actions[bot]"
-f "committer[email]=github-actions[bot]@users.noreply.github.com")
if [[ -n "$CURRENT_SHA" ]]; then
API_ARGS+=(-f "sha=$CURRENT_SHA")
fi
if gh api "${API_ARGS[@]}" >/dev/null; then
echo "Pushed state via API on attempt $attempt"
exit 0
fi
echo "State write attempt $attempt failed (likely concurrent run); retrying..." >&2
sleep $((RANDOM % 5 + 2))
done
echo "::error::Failed to write state via API after 5 attempts" >&2
exit 1
- name: Check for Failures
if: contains(fromJSON('["failure", "cancelled"]'), needs.build-lib.result)
run: |
echo "One or more critical callbacks failed or were cancelled"
exit 1