The shared CI code for Harish Seshadri's own repositories: three Dagger modules they install, and a daily check that each repo still runs its CI the same way.
Try it without cloning: dagger -m github.com/gainratio/ci/modules/portfolio-foundation@faf55ac51dfeb6bad274988941e9215117e5259e functions
Dagger runs CI steps as code inside containers, so the same steps run on a laptop and in GitHub Actions. Harish's projects (almamesh, aml-filter, assay, edge-proc, edge-reco and others) all need the same few things: check the source is safe, build a Python package, deploy a static site to Cloudflare Pages. Copying that code into each repo means many copies drifting apart. This repo holds one copy, as Dagger modules each repo installs at an exact commit.
It also watches the other repos. Once a day it reads the main branch of each repo on its
list from GitHub, and fails if a workflow runs anything outside Dagger, branch protection
has drifted, a repo pins a module older than the minimum version allowed, or the latest
main commit is not green. It also fails if a repo installs one of these modules but is
missing from that list.
Technical docs: Architecture · Getting started · Using the modules
A repo adds a module to its own dagger.json, pinned to one commit of this repo. This is
aml-filter's, as it is today:
"dependencies": [
{
"name": "cloudflare-pages",
"source": "github.com/gainratio/ci/modules/cloudflare-pages@dd19871486588b1582e432b7bc1f2cfffb296340",
"pin": "dd19871486588b1582e432b7bc1f2cfffb296340"
},
{
"name": "foundation",
"source": "github.com/gainratio/ci/modules/portfolio-foundation@dd19871486588b1582e432b7bc1f2cfffb296340",
"pin": "dd19871486588b1582e432b7bc1f2cfffb296340"
}
]Its own Dagger code then calls the modules like any other function, for example
dag.foundation().guard(...) before a build and dag.cloudflare_pages().deploy(...) to
ship the site. Its GitHub workflow stays tiny: check out the code, then call Dagger.
The three modules:
| Module | What it does | Used by |
|---|---|---|
portfolio-foundation |
Ties a build to one exact commit, runs secret and workflow scans over the full Git history, and wraps build output with a record of where it came from. | all nine repos |
cloudflare-pages |
Deploys a built site to Cloudflare Pages once, then checks the live site is serving that exact deployment. | almamesh, aml-filter, edge-reco |
python-package |
Audits dependencies, builds the wheel and sdist, and checks the version matches the tag. It does not upload to PyPI; a separate job does that with PyPI's official action. | edge-proc, edgeproc-core, agentic-context-service, agentic-saga |
Upgrading is a pull request in the consumer that changes the commit in both source and
pin. Nothing changes for a consumer when this repo's main moves.
You need Docker and Dagger 0.21.8.
-
List what the foundation module offers, straight from GitHub (about 15 seconds):
dagger -m github.com/gainratio/ci/modules/portfolio-foundation@faf55ac51dfeb6bad274988941e9215117e5259e functions
Name Description envelope Wrap a typed artifact with deterministic evidence. green-main Resolve exact-green main evidence using a typed secret. green-main-decision Deploy commit_sha only if it is main's exact-green HEAD; skip it if main moved on. guard Apply repository security checks to a bound source. source Bind a supplied workspace to a repository identity. verify-envelope Revalidate and return only a closed envelope's artifact subtree. -
Ask it whether a repo's
mainis green right now. This is the same call aml-filter makes before it deploys:export GITHUB_TOKEN="$(gh auth token)" dagger -m github.com/gainratio/ci/modules/portfolio-foundation@faf55ac51dfeb6bad274988941e9215117e5259e \ call green-main --github-token=env:GITHUB_TOKEN --repository=gainratio/aml-filter serialization
Real output from 25 Sep 2026, trimmed:
{"app_id":15368,"branch":"main","check_name":"Dagger", "commit_sha":"4392391bde505a8367fea87723e4ee8ef7bc4895", "repository":"gainratio/aml-filter","workflow_path":".github/workflows/dagger.yml", "workflow_run_id":"36177431244", ...}commit_shais aml-filter's currentmain, and theDaggercheck passed on it. If the check had not passed, the call would fail instead of returning. -
Run this repo's own checks from a clone (about 8 minutes):
git clone https://github.com/gainratio/ci && cd ci dagger call ci --github-token=env:GITHUB_TOKEN --repository=gainratio/ci
Success ends with
central Dagger gate passed.
Every workflow in this repo and in the consumer repos does two things: check out the code,
and call one Dagger function. All the real work happens in Dagger. dagger call ci runs
linting, strict type checks, tests with a 90% coverage floor, a dependency audit, workflow
security scans, and a secret scan over the full Git history. It also builds two tiny consumer
modules, one in Python and one in TypeScript, to prove the shared modules install and run
from both. dagger call fleet reads every consumer repo's main through the GitHub API and
applies the rules in .dagger/src/ci/fleet_policy.py. If any repo cannot be read, that is a
failure, not a skip.
- It is for Harish's repos. The modules assume his setup: GitHub, Cloudflare Pages, PyPI, Dagger 0.21.8. You can read and borrow from them, but there is no support promise.
- No reusable GitHub workflows or composite actions. The old ones were removed; they are in Git history and old tags only.
- It never publishes anything. No package, tag or registry upload comes from this repo.
python-packagebuilds a package; publishing is a separate job in the consumer. - No automatic upgrades. Consumers stay on their pinned commit until someone opens a PR.
- Dependabot PRs are never auto-merged.
The quick local loop (about 1 minute once Dagger has generated the SDK):
dagger develop
uv run --directory .dagger poe gateThe full check, the same one CI runs, is
dagger call ci --github-token=env:GITHUB_TOKEN --repository=gainratio/ci. CI passes its own
github.repository; there is no default owner.
On a branch, push first and add --commit-sha=$(git rev-parse HEAD).
Each module under modules/ has its own poe gate too. See
Getting started for versions, the code map, and a worked first
change.
- Getting started: set up, run the checks, make a first change, open a PR.
- Architecture: the four workflows, exactly what
ciandfleetcheck, the allowed publishing exceptions, and the tokenfleetneeds. - Interactive runtime map.
- Using the modules: installing at an exact commit, a full consumer example, secrets, Pages safety and rollback.
- Design (2026-08-27) and the first rollout plan: why the shared modules exist.
- CHANGELOG: what changed, including what was removed.
MIT. See LICENSE.