Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## What this repository is

This is Certego's shared org-level `.github` repository: a library of reusable GitHub Actions **workflows** and **composite actions**, plus canonical linter/formatter **configurations**, that other Certego projects consume via `git subtree`. It is not an application — there is no build step, no runtime, and (outside of the self-test fixtures) no product code.

Consumers add this repo into their own project at `.github/` via:
```bash
git subtree add --squash --prefix .github https://github.com/certego/.github.git main && rm -rf .github/{.github,README.md}
```
and update it later with `git subtree pull` (same flags). Keep this consumption model in mind when changing inputs/outputs of workflows or actions — they are a semi-public API for every Certego project, not internal implementation details.

The trailing `rm -rf .github/{.github,README.md}` is not optional cleanup — it removes this repo's own nested self-test copy (`.github/.github/`, see below) and this repo's own `README.md`, neither of which belong in a consumer project. **Every time a project adds or updates (`subtree pull`) this CI, it must re-run that `rm -rf` step**, otherwise the consumer ends up with a stray nested `.github/.github` directory and a leftover `.github/README.md` from this repo.

## Repository layout

- `workflows/` — reusable (`workflow_call`) YAML workflows plus two trigger workflows:
- `pull_request_automation.yml` — entry point run on every PR to `master`/`main`/`develop`/`dev`. Calls `_detect_changes.yml` to see which of backend/frontend/infra changed, then conditionally calls `_python.yml`, `_node.yml`, `_opentofu.yml`.
- `release.yml` — entry point run on PR close / push to `test`/`opentofu`. Calls `_release_and_tag.yml`, which tags+releases on a numeric PR title (e.g. `1.2.3`) merged into a release branch, and optionally publishes to PyPI/TestPyPI/npm/Twitter/ECR.
- `_detect_changes.yml`, `_python.yml`, `_node.yml`, `_opentofu.yml`, `_release_and_tag.yml` — underscore-prefixed reusable workflows, each with many boolean `use_*`/`check_*` inputs that toggle individual linters/services/steps. See `workflows/README.md` for the full input/output reference and step-by-step breakdown of each workflow — update that README whenever inputs or steps change.
- `actions/` — composite actions invoked by the reusable workflows (e.g. `python_linter`, `node_linter`, `codeql`, `services` (spins up Postgres/Redis/RabbitMQ/Mongo/Elasticsearch/Memcached test containers), `push_on_ecr`, `apt_requirements/*` and `python_requirements/*` cache helpers). Each has an `action.yml` and usually a `README.md`.
- `configurations/` — canonical linter/formatter config files consumers point their tools at directly (e.g. `pylint --rcfile=.github/configurations/python_linters/.pylintrc`):
- `python_linters/` — `.pylintrc`, `.flake8`, `.black`, `.isort.cfg`, `.bandit.yaml`, `.ruff.toml`, `requirements-linters.txt`.
- `node_linters/` — `eslint.config.mjs`, `.prettierrc.json`, `.stylelintrc.json`, `packages-linters.txt`.
- `.github/test/` — the fixture projects (`python_test/` a minimal Django+Celery app, `node_test/` a minimal npm/React app) used to self-test the workflows in this repo. These are hard-linked (not symlinked, since GitHub can't store symlink-as-hardlink semantics) into `.github/.github/{workflows,actions,configurations}` so the reusable workflows can `uses: ./.github/workflows/_xxx.yml` against themselves.
- `.pre-commit-config.yaml`, `.husky-pre-commit` — reference pre-commit/husky configs consumers copy into their own repo; they point at the `configurations/` files above.
- `dependabot.yml`, `CHANGELOG.md` — reference configs/format for consumers.

## The hardlink self-test setup (important, easy to get wrong)

Because this repo's own CI (`pull_request_automation.yml`) exercises `./.github/workflows/_python.yml` etc. against the fixture projects, the root-level `workflows/`, `actions/`, `configurations/` directories must also exist as identical copies under `.github/.github/`. These are maintained as **hard links**, not a symlink or a second copy:

```bash
.github/hooks/post-merge # runs: cp -rfl {workflows,actions,configurations} .github/
```

Consequences when editing this repo:
- After checkout/merge, run `.github/hooks/post-merge` (or symlink it as `.git/hooks/post-merge`) to restore the hardlinks — see `README.dev.md`.
- If you add, move, or rename a file (not just edit its content in place), the hardlink is not automatically created/updated for the new path — re-run the post-merge script.
- When staging changes, stage **both** the root file and its `.github/.github/...` counterpart.
- Do not `rm -rf` and recreate `.github/.github` casually; it is regenerated by the script, but any unstaged edits made only under one of the two paths can be lost if you're not careful about which copy you edited.

## Making changes

- There is no build/lint/test command to run locally in the traditional sense — this repo is tested by its own GitHub Actions CI (`pull_request_automation.yml`) exercising the fixture projects in `.github/test/`. To validate a workflow/action change, open a PR (or push to a branch that triggers the workflow) and watch the run against `python_test`/`node_test`.
- When changing a reusable workflow's inputs, outputs, or steps, update the corresponding section of `workflows/README.md` to match (it's an intentionally detailed input/output/step reference, not generated).
- When changing a linter configuration, update the matching `configurations/*/README.md` if usage instructions change.
- PRs target `develop` (see `README.dev.md`); releases are cut by merging a PR whose title is a bare semver (e.g. `1.2.3`) into `master`/`main`/`prod`.