setup-ci · git:20261009.9dd80f8 · 2026-10-09 · sha256 57f1bd5e6a5fd675
setup-ci git:20261009.9dd80f8A
Immutable. This exact content never changes and is served at /api/v1/blob/57f1bd5e6a5fd675.
---
name: setup-ci
description: >
Defines GitHub Actions workflow structure: ci.yml + release.yml naming, concurrency
groups, bot-commit skip, workflow_call reuse, App-token checkout, and optional
fsrc/teasr steps. Language-specific pipelines live in scaffold-rust, scaffold-go,
scaffold-python, scaffold-node, scaffold-terraform. Use when setting up GitHub Actions,
wiring ci.yml/release.yml, configuring concurrency or workflow_call, or adding fsrc/teasr
steps. Do NOT use for sr.yaml schema, typed publishers, or the sr CLI/action; use
sync-release for those.
allowed-tools: Read, Grep, Glob, Bash(git *), Bash(gh *), Edit, Write
metadata:
title: CI/CD Standards
category: development
order: 1
---
# CI/CD Standards
Universal conventions that apply across all languages. For language-specific CI jobs, build matrices, and caching, see the corresponding `scaffold-*` skill.
## Workflow Naming Convention
| File | Trigger | Purpose |
|------|---------|---------|
| `ci.yml` | `pull_request: branches: [main]` + `workflow_call` | Quality gate: fmt, lint, test |
| `release.yml` | `push: branches: [main]` + `workflow_dispatch` | Automated releases |
- **No `build.yml` or `publish.yml`** build and publish are jobs within `release.yml`
- Specialized workflows allowed for domain-specific needs (e.g., `experiments.yml`)
- Exception: Terraform uses a single `terraform.yml` (see `scaffold-terraform`)
## Pipeline Flow
```text
PR -> ci.yml (fmt -> lint -> test)
Push main -> release.yml:
fsrc -> ci -> sr release -> build -> publish -> teasr
```
sr v9+ syncs lock files (`Cargo.lock`, `uv.lock`, `poetry.lock`, `package-lock.json`) during the version bump and commits them in the release commit, so `release.yml` needs no separate lock sync step or `[skip ci]` lock commit. See `sync-release` for details.
## Release Config
- Canonical filename: `sr.yaml` (not `.urmzd.sr.yml`)
- `floating_tags: true` in all configs
- `tag_prefix: "v"` and Angular commit pattern
- See `sync-release` for full sr.yaml reference
## Concurrency
```yaml
# CI workflows: cancel stale runs
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
# Release workflows: never cancel mid-release
concurrency:
group: release
cancel-in-progress: false
```
## Bot Skip
Prevent infinite loops from bot commits:
```yaml
if: github.actor != 'sr[bot]'
```
## CI Reuse Pattern
`ci.yml` exposes `workflow_call` so `release.yml` can gate on it:
```yaml
# ci.yml
on:
pull_request:
branches: [main]
workflow_call:
# release.yml
jobs:
ci:
uses: ./.github/workflows/ci.yml
release:
needs: ci
```
## App Token Pattern
Release workflows use a GitHub App for bot commits that can trigger further workflows:
```yaml
- name: Generate app token
id: app-token
uses: actions/create-github-app-token@v1
with:
app-id: ${{ secrets.SR_RELEASER_APP_ID }}
private-key: ${{ secrets.SR_RELEASER_PRIVATE_KEY }}
repositories: ${{ github.event.repository.name }}
- uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ steps.app-token.outputs.token }}
```
## fsrc Step (Optional)
Sync code snippets into README before release:
```yaml
- uses: urmzd/fsrc@v4
with:
files: "README.md"
commit-message: "chore: sync embedded files [skip ci]"
```
## teasr Step (Post-Release, Optional)
Capture terminal demo after release:
```yaml
- uses: urmzd/teasr/.github/actions/teasr@main
```
## Force Re-release
All release workflows support manual dispatch with a `force` flag for partial failures:
```yaml
workflow_dispatch:
inputs:
force:
description: "Re-release the current tag (use when a previous release partially failed)"
type: boolean
default: false
```