Cloud services · Git

Your code lives here, and it already knows how to ship.

Clone and push with the git you already have. Open a pull request, get a review, merge — and the thing you merged builds, lands in your registry and goes live. No webhook to wire, no CI service to connect, no registry credentials to paste anywhere.

Your code

Private repositories, browsable.

Unlimited private repos with the whole forge around them: a file browser with the README rendered at the root, commit history, diffs between any two refs, tags and releases. Clone over HTTPS or SSH with the client you already use — and drive the same thing from the REST API or your agent when you'd rather not click.

acme / crm-coremain · 3 branches
.githubworkflows: cache actions2d
.dodildeploy: pin the medium tier2d
cratesdedup contacts on merge key4h
migrationsadd contacts (org_id, email) index3d
Cargo.tomlbump to 0.4.24h
README.mddocument the merge key1w
README.md renders here, the way you'd expect.
Clonehttps or ssh
HTTPS
git clone https://git.dodil.io/acme/crm-core.git
SSH
git clone ssh://[email protected]/acme/crm-core.git
An SSH key for people, a Dodil API key for CI and scripts. Both resolve to the same per-repo permissions.
Also in the repo
Historyevery commit, with its diff
Compareany two branches or tags
Packagesthe images this repo built
Secretsscoped to the repo, masked in logs
Compatible, not similar

The workflow file you already have.

Same path — .github/workflows/ — same keys, same expressions, same actions pulled from github.com and cached. Move the repo and your pipeline runs. Each job becomes a check on the commit.

.github/workflows/ci.ymlunchanged
name: CI
on: [push]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: cargo build --release
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: cargo test --all
      - run: echo "token is ${{ secrets.API_TOKEN }}"
Run #248main · 2m 14s
Set up job3s
build58s
actions/checkout@v42s
cargo build --release54s
test1m 09s
cargo test --all1m 06s
dodil-ci/deploy24s
secrets masked in logs · cancel and re-run from the console or the CLI
Auto-deploy

Merge is the deploy button.

One file says which apps to publish, on which branch, behind which checks. When they go green the runner builds the image, pushes it to your registry and publishes the version to Ignite — creating the app on a first deploy if you ask it to.

.dodil/deploy.yamlin your repo
version: 1
create_if_missing: true

when:
  branches: [main]
  require_checks: all

apps:
  - name: crm-core
    image: ${{ registry }}/crm-core:${{ sha }}
    port: 8080
    public_invoke: false
    user_pool: acme/crm-suite
    resources:
      tier: medium
    scaling:
      max_replicas: 10
    health:
      path: /healthz
    env:
      DATABASE_URL: ${{ secrets.DATABASE_URL }}
Deploycrm-core · 41s
checks satisfied — main
build image22s
push → registry.dodil.io9s
create app (first deploy)2s
publish draft → live8s
now serving
https://crm-core.ignite.dodil.cloud

Publishing snapshots the merged tree and stamps the commit onto the version record — so the deployed artifact stands on its own, and a rollback is a pointer flip rather than a rebuild.

Pull requests

Review that actually blocks the merge.

Draft a PR while it's rough, open it when it's ready. Reviewers approve or request changes, comment threads hang off individual lines and have to be resolved, and CODEOWNERS are pulled in automatically for the files you touched. The merge button tells you what's still missing.

Pull request #412open · 3 commits
Add contact dedup on merge key
feat/dedupmain
danaapproved
priyacode ownerreview requested
2 threads · 1 unresolved
CI / build58s
CI / test1m 09s
Merge blocked
Waiting on the code owner, and one thread is still open.
Branch protectionmain
Require a pull requestdirect pushes refused
Required approvals1
Require passing checksCI / build · CI / test
Require threads resolved
Require code-owner reviewCODEOWNERS
Dismiss stale approvalson new commits
Block self-approval
Block force-push
Block deletion
Rules match a branch pattern and are enforced at the wire — a push that breaks one is refused by the server, not reverted by a bot afterwards.
Worth knowing before you move a repo
  • Creating the Ignite app on a first deploy is opt-in. Left off, a typo'd app name fails loudly instead of quietly creating something you didn't mean.
  • Images build on a version tag, not on every merge — so an ordinary merge runs your checks without pushing an image nobody asked for.
  • Checks are modelled per job. A job is the unit that reports; there are no per-step annotations or per-step re-runs.
FAQ

Questions, answered.

Push once. Watch it land.

Bring the repo and the workflow file you already have.

Start free
Regions
UKLiveEULiveMiddle EastSoonAfricaSoon
Compliance
SOC 2In progressISO 27001In progressGDPR-readyData residencyEnforced
© 2026 Circle Technologies Pte Ltd. All rights reserved.