Skip to content

Deploy the proxy from ontola/atomic-plugins via a thin atomic-integration-proxy wrapper - #77

Merged
michielbdejong merged 1 commit into
mainfrom
claude/wrap-atomic-integration-proxy
Sep 24, 2026
Merged

michielbdejong merged 1 commit into
mainfrom
claude/wrap-atomic-integration-proxy

Conversation

@michielbdejong

Copy link
Copy Markdown
Contributor

What changed

The proxy's source now lives in ontola/atomic-plugins/integration-proxy as the library crate atomic-integration-proxy (ontola/atomic-plugins#81). This PR removes the copy of it here and leaves only the Heroku deployment wrapper, taken from that repo's integration-proxy/examples/heroku-wrapper/:

  • src/main.rs: atomic_integration_proxy::run().await, nothing else.
  • Cargo.toml: the package and binary are still named auth-proxy, so the Procfile (web: target/release/auth-proxy) is unchanged. The crate isn't on crates.io yet, so the dependency is a git dependency pinned to ontola/atomic-plugins@494eb8af139b60a41e5197c92053890c0d841b2f (current main). Cargo finds the package in the integration-proxy/ subdirectory by its name. A comment says to switch to version = "0.1" once the crate is published.
  • Cargo.lock: seeded from the crate's own lockfile. Every third-party dependency resolves to the same version as the previous Cargo.lock here. The only new entry is atomic-integration-proxy itself.
  • rust-toolchain: stable, which is what emk/heroku-buildpack-rust already used by default when no such file existed.
  • Removed: src/* (apart from main.rs), static/, tests/, rustfmt.toml, AGENTS.md, SECURITY.md and TESTING_COVERAGE.md. Kept: LICENSE, .env.example (identical to the one in atomic-plugins) and .gitignore. README.md is now a short pointer to atomic-plugins plus instructions for deploying a newer version.
  • .github/workflows/ci.yml: now runs only cargo fmt --check, cargo clippy --locked -D warnings, cargo build --locked --release, and a check that the unconfigured binary exits with configuration error:. The proxy's own tests, including the PostgreSQL ones, run in atomic-plugins' integration-proxy-ci.yml.

Divergence check

Before deleting anything, I diffed src/, static/, tests/, Cargo.toml and Procfile here against ontola/atomic-plugins integration-proxy/ at 494eb8a. Nothing exists only in production:

  • This repo's main (c02b5e5) is an ancestor of ontola/atomic-plugins main, merged in by f46ca3a, so every commit here is already in atomic-plugins.
  • static/ and tests/ are byte-identical.
  • The differences in src/, Cargo.toml and Procfile all come from later atomic-plugins commits (88cda53, 075c9fb, b451747). They are listed under "Behaviour changes" below. The old main.rs body moved into lib.rs unchanged, apart from its error handling.

Heroku buildpacks and APP_BASE

The buildpacks are, in order, lstoll/heroku-buildpack-monorepo and emk/heroku-buildpack-rust. The repository layout is unchanged: Cargo.toml, Cargo.lock, Procfile and now rust-toolchain are all at the repo root, as before. Whatever APP_BASE makes the current production build work will therefore keep working.

What I checked about APP_BASE, running the monorepo buildpack's bin/compile in an ubuntu:24.04 container:

  • Unset: the build aborts with APP_BASE was not set. Aborting.
  • . or ./: the build fails with mv: cannot move '/build/.' ...: Device or resource busy / FAILED to copy directory into place.
  • Any subdirectory name: fails, because this repo has no subdirectories.
  • Empty string: worked in the container, only because moving the whole build directory away and back happens to succeed. I have not verified this on Heroku.

Nothing in this repo's history or docs says what APP_BASE production uses. Given the results above, the monorepo buildpack does nothing useful for a repo whose app sits at the root. Before merging, run heroku buildpacks -a <app> and heroku config:get APP_BASE -a <app>. The simplest safe setup is to remove the monorepo buildpack: heroku buildpacks:remove lstoll/heroku-buildpack-monorepo -a <app>.

emk/heroku-buildpack-rust reads the plain rust-toolchain file and runs cargo build --release in the build dir. Cargo fetches the git dependency itself; the build does not need a git binary.

Behaviour changes

These come from atomic-plugins commits made after this repo was merged in:

  1. Default catalog source. Without CATALOG_PATH, the proxy used to load https://raw.githubusercontent.com/localthought/overlays/5d344a62…/catalog.json, pinned to a commit. It now loads https://ontola.github.io/atomic-plugins/overlays/catalog.json, which GitHub Pages publishes from atomic-plugins main. This URL is not pinned: each restart or dyno cycle picks up whatever main has published at that moment. I compared the two catalogs: all seven existing platforms (github-issues, google-calendar, moneybird, todoist, spotify, discord, notion) have the same OAD URLs and selections, and their overlay files are byte-identical. That includes the google-calendar PATCH change from Bump DEFAULT_CATALOG_PATH: google-calendar events now support PATCH #75. The only difference is that clockify is added, using an API-key scheme. If Heroku sets CATALOG_PATH, none of this applies.
  2. Connection-code idle lifetime went from 10 minutes to 30 days (CONNECTION_CODE_IDLE_DAYS; issue Keep GitHub pagination within catalog-approved repository paths #42 in atomic-plugins). Before, a client that stopped syncing for 10 minutes lost its refresh token. The trade-off: a leaked but unused code now stays redeemable for up to 30 days. Codes are still single-use. There is no schema change.
  3. Log target renamed from auth_proxy to atomic_integration_proxy. A RUST_LOG filter such as auth_proxy=debug has to become atomic_integration_proxy=debug. The startup line is unchanged: auth-proxy listening on http://0.0.0.0:$PORT.
  4. Startup failures no longer panic. If the OIDC client can't be built or the port can't be bound, the binary now prints a one-line error and exits with status 1, where it used to panic. The configuration, catalog and security error messages are the same as before.

Heroku config vars are otherwise unchanged. The crate reads the same environment variables with the same defaults.

Verification (local, macOS, rustc 1.98.1)

  • cargo build --release --locked passed, and so did cargo clippy --all-targets -- -D warnings and cargo fmt --check.
  • Run with an empty environment, the binary printed configuration error: APP_AUTH_CLIENT_ID must be set and exited with status 1.
  • I ran it fully configured, with env vars as in atomic-plugins' integration-proxy CI, against a postgres:16-alpine container and the default catalog:
    • /healthz returned ok (200).
    • /catalog returned ["clockify","discord","github-issues","google-calendar","moneybird","notion","spotify","todoist"].
    • /catalog/clockify.yaml, / and /logo.png all returned 200.
  • Not verified: a real Heroku build, and whether production has APP_BASE, CATALOG_PATH or RUST_LOG set.

Rollback

  • Fastest: heroku releases:rollback -a <app> goes back to the previous slug. No build is needed, and there is no database migration to undo.
  • In git: revert this PR's merge commit on main (git revert -m 1 <merge sha>) and push. That restores the full source and the old pinned catalog.
  • Connection codes issued while the new version was running have 30-day expiries. After a rollback the old code still redeems them until they are used. Nothing else in the database differs.

🤖 Generated with Claude Code

The proxy now lives in ontola/atomic-plugins' integration-proxy/ as the
library crate `atomic-integration-proxy` (ontola/atomic-plugins#81). This
repository keeps only the Heroku deployment wrapper from that repo's
integration-proxy/examples/heroku-wrapper/: a one-line main calling
`atomic_integration_proxy::run()`, the `auth-proxy` package/binary name and
the unchanged Procfile.

The crate is not on crates.io yet, so it is a git dependency pinned to
ontola/atomic-plugins 494eb8af139b60a41e5197c92053890c0d841b2f; switch to
`version = "0.1"` once it is published. Cargo.lock was seeded from the
crate's own lockfile, so every third-party dependency resolves to the same
version as the previous Cargo.lock here.

ontola/atomic-plugins main contains this repository's main (c02b5e5) in its
history; the source there differs only by changes made since the move.

CI now only checks formatting, clippy, a locked release build, and that the
unconfigured binary exits with a configuration error; the proxy's tests run
in ontola/atomic-plugins.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@michielbdejong
michielbdejong merged commit 4478c31 into main Sep 24, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant