Getting started¶
Pin to @v1¶
Reference everything at the moving major tag. release (release-please) cuts a
new version on merge to main and moves the v1 tag to it automatically, so
@v1 always points at the latest backward-compatible release.
- uses: FSHTech/github-actions/setup-python@v1
# reusable workflow:
# uses: FSHTech/github-actions/.github/workflows/pr-title.yml@v1
Breaking changes ship as v2 (a new major tag); pin to a full version
(@v1.3.0) if you need to freeze.
Composite actions vs reusable workflows¶
Composite actions are step bundles — they go inside an existing job’s
steps:, afteractions/checkout(and the relevant language setup). Use them to assemble a job whose shape is specific to your repo (e.g.lint).Reusable workflows are whole jobs — you call them with
uses:at the job level and they bring their own runner, permissions and steps. Use them when the entire job is the same across repos (pr-title,release,docs).
A typical Python repo¶
# .github/workflows/lint.yml — job graph stays local, built from actions
name: lint
on:
push: { branches: [main] }
pull_request:
workflow_dispatch:
permissions:
contents: read
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: FSHTech/github-actions/setup-python@v1
- uses: FSHTech/github-actions/uv-sync@v1
with: { args: --group dev --group lint }
- uses: FSHTech/github-actions/just-run@v1
with: { recipes: lint type-check }
pre-commit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: FSHTech/github-actions/setup-python@v1
- uses: FSHTech/github-actions/pre-commit@v1
tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: FSHTech/github-actions/setup-python@v1
- uses: FSHTech/github-actions/uv-sync@v1
with: { args: --group dev }
- uses: FSHTech/github-actions/just-run@v1
with: { recipes: coverage-ci }
The recipes (lint, type-check, coverage-ci, …) live in your repo’s
justfile. A node repo is the same shape — setup-node then just-run — so it
needs a justfile exposing the equivalent recipes (e.g. lint, type-check,
build, test) that wrap the underlying yarn workspace … calls.
# .github/workflows/pr-title.yml — thin caller for the reusable workflow
name: pr-title
on:
pull_request:
types: [opened, edited, synchronize, reopened]
jobs:
validate:
uses: FSHTech/github-actions/.github/workflows/pr-title.yml@v1
with:
scopes: |
my-repo
deps
ci
release
# .github/workflows/release.yml — thin caller for the reusable workflow
name: release
on:
push: { branches: [main] }
jobs:
release:
uses: FSHTech/github-actions/.github/workflows/release-python.yml@v1
secrets: inherit
# monorepo: with: { all-packages: true, check-url: true }
Preview environments¶
Demo apps get an ephemeral environment per pull request — a full app
(be/fe/opa/render + Postgres) on a per-PR EC2, seeded from the base branch’s
trunk database, reachable at https://<branch>.<app>.preview.efesaitch.com
behind Cloudflare Access (Google login). The PR gets a comment with the link;
closing it tears the environment down. Push to main/staging refreshes that
base branch’s always-on trunk, which PR previews seed from.
# .github/workflows/preview.yml — thin caller for the reusable workflow
name: preview
on:
pull_request:
types: [opened, synchronize, reopened, closed]
push:
branches: [main, staging]
workflow_dispatch:
jobs:
preview:
# fork PRs can't read secrets, so skip them
if: >-
github.event_name != 'pull_request' ||
github.event.pull_request.head.repo.full_name == github.repository
uses: FSHTech/github-actions/.github/workflows/deploy-preview.yml@v1
with:
app: my-app
worker_entrypoint: my_app.queue.main:main
db_name_prefix: my_app
ecr_registry: ${{ vars.PREVIEW_ECR_REGISTRY }}
launch_template_id: ${{ vars.PREVIEW_LAUNCH_TEMPLATE_ID }}
subnet_id: ${{ vars.PREVIEW_SUBNET_ID }}
cf_account_id: ${{ vars.PREVIEW_CF_ACCOUNT_ID }}
secrets:
AWS_ACCESS_KEY_ID: ${{ secrets.PREVIEW_AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.PREVIEW_AWS_SECRET_ACCESS_KEY }}
CF_API_TOKEN: ${{ secrets.PREVIEW_CF_API_TOKEN }}
Onboarding a new demo app: add one line to infra/demo-repos.hcl and
just apply domain (creates the app’s Cloudflare Access app at
*.<app>.preview.efesaitch.com), then copy the caller above into the repo. The
PREVIEW_* repo vars/secrets are provisioned by infra’s development account.
The full design + AWS/Cloudflare substrate is in infra/docs/internal-paas.md.
See Reference for the exact inputs of each action and workflow, and Conventions for what your repo must provide (uv layout, deploy keys, CodeArtifact / Cloudflare variables, …).