self merging test repo for orchestrator
Find a file
2026-08-13 05:56:19 +00:00
.orchestrator refactor yml to run merge on worker-1 2026-08-12 18:55:41 +05:45
src/wordtools initial test 2026-08-12 18:07:58 +05:45
tests fail branch fix 2026-08-12 18:12:32 +05:45
tools initial test 2026-08-12 18:07:58 +05:45
.DS_Store initial test 2026-08-12 18:07:58 +05:45
.gitignore initial test 2026-08-12 18:07:58 +05:45
after test fefense 2026-08-13 11:40:09 +05:45
before_test test before defense 2026-08-13 11:13:18 +05:45
merge_flag_3 removed comment from action.yml 2026-08-12 18:52:04 +05:45
README.md initial test 2026-08-12 18:07:58 +05:45
sample.txt initial test 2026-08-12 18:07:58 +05:45
test test fefense 2 2026-08-13 11:41:06 +05:45

wordtools

A tiny text-analysis library, and the reason it exists: a pipeline that guards the main branch.

The library is deliberately small — split text into words, count them, print a report. Standard library only, no pip install anywhere. The interesting part is .orchestrator/actions.yml.

The rule the pipeline implements

push to any branch except main
  -> run every check and every test
     -> if all of them pass, merge that branch into main

Push to main directly and the pipeline runs but every job exits immediately: main is the merged result, so there is nothing to check.

The shape

check              test                merge
┌──────────┐       ┌─────────────┐     ┌───────────────┐
│ compile  │       │ test-words  │     │ merge-to-main │
│ style    │  ──▶  │ test-stats  │ ──▶ │               │
└──────────┘       │ test-report │     └───────────────┘
                   │ test-switch │
                   └─────────────┘

Seven jobs, and between them the two things worth understanding:

Parallel. compile and style declare no needs, so the scheduler releases both at once. One stage down, the four test jobs all become runnable at the same moment and run side by side — on different machines, if more than one worker is online. One test job per module, so a red job names the module that broke instead of just saying "the tests failed".

Chain. The four test jobs needs: [compile], so none of them starts until compile has passed. merge-to-main needs all five jobs before it, so it is reached only when every one of them is green.

That chain is what makes this a gate rather than a suggestion. When a job fails, the orchestrator marks everything downstream of it skipped: dependency '<job>' failed and never runs it. A broken branch cannot reach the merge job at all.

How the branch rule is written

This orchestrator has no only: / except: filter, so each job decides for itself, on its first line:

if [ "$REPO_BRANCH" = "main" ]; then echo "on main — nothing to do"; exit 0; fi

REPO_BRANCH, REPO_URL and COMMIT_SHA are injected into every job by the coordinator, so nothing here hardcodes the repo or the branch.

Setting up the merge

tools/merge_to_main.py opens a pull request in Forgejo and merges it. It needs a token with write access, and the token must be visible to the job.

The executor passes its own environment through to every job it runs, so set it there — in the executor service in docker-compose.yml:

environment:
  FORGEJO_TOKEN: <a token with write access to the repo>

Do not put the token in the env: block of actions.yml — that block lives in the repo in plain text.

Create the token in Forgejo under Settings → Applications, with write:repository scope.

One more setting: the webhook in Forgejo must be a push webhook pointing at POST http://<coordinator>/api/webhooks/forgejo with content type JSON. Leave the other event types off — a pull-request payload has no branch ref, and the run would be labelled against the wrong branch.

Trying it

git switch -c try-something
echo "just testing" >> sample.txt
git commit -am "test the pipeline"
git push -u origin try-something

Watch the run appear in the dashboard. When the four jobs go green, merge-to-main opens a pull request and merges it, and try-something is now part of main.

Showing the failing path

tests/test_switch.py exists only for this. It has one flag in it:

FAIL_ON_PURPOSE = False

Set it to True, commit, push. test-switch goes red, merge-to-main is marked skipped: dependency 'test-switch' failed, and nothing reaches main. Set it back to False, push again on the same branch, and the run goes green and merges. Nothing else in the library touches that flag, so flipping it is always safe.

You can also break something real — change a number in tests/test_stats.py, or push a line longer than 88 characters to fail style.

Running it locally

python3 -m compileall -q src tests tools          # what `compile` does
python3 tools/style_check.py                      # what `style` does
PYTHONPATH=src python3 -m unittest discover -s tests -t . -v
PYTHONPATH=src python3 -m wordtools sample.txt    # the library itself

Layout

src/wordtools/    words, stats, report, cli — the library
tests/            one test file per module
tools/            style_check.py, merge_to_main.py
.orchestrator/    actions.yml — the pipeline
sample.txt        something for the CLI to read