# How we stop our dependencies falling behind

Once a week a Machine agent bumps our packages, installs them clean in a private sandbox and runs every test. You only get a pull request when the whole suite is green.

Canonical page: https://themachine.myapps.ai/use-cases/dependency-upgrades

Nobody wakes up wanting to bump packages. So they sit. A few months on, the
project is several versions behind, the security fixes have stacked up, and the
catch-up job has grown into a scary rewrite with no volunteer. Version bots do
not really help: they file one PR per bump and leave you to decide if each is
safe. In practice that means a tab of PRs nobody opens.

Our fix is an agent on Machine that tests the upgrade before it bothers anyone.
Every week it picks the packages worth bumping, applies them on a private cloud
computer, runs every test we have, and files a PR only if all of it passes. Below
is the whole setup: what starts a run, where the run happens, and the limits we
put on it.

- **Team:** Machine
- **Runs on:** A cron schedule, once a week
- **Connected systems:** GitHub · CI
- **Mode:** Scheduled · a PR only on a green suite

## The problem

Upgrades are chores with no owner and no slot in the sprint. A bump bot will
happily file a PR for each package, yet it has no idea if anything broke. A
person still has to find out, the queue grows, and you fall behind regardless.

The usual escape routes all leak. Wait until you are forced to upgrade, and a
small bump becomes a migration project. Auto-merge on green CI, and you are only
as safe as the tests you happened to write. Do it by hand, and it works, slowly,
right up until a busy week pushes it off the list.

## What we built

A cron job on Machine wakes the upgrade agent once a week. Every run gets its own
**session**: a fresh cloud computer (a sandbox) used for that run alone, with
limited access to the repo and CI. Inside it, the agent works out what is out of
date, applies the bumps on a new branch, does a clean install and runs the
complete test suite. Green means a PR. Merging stays a human job.

## How it works

### Start the run from a weekly schedule

A timed **trigger** goes off once a week. Each time, Machine starts a new
**session** on its own sandbox and gives it a clean copy of the default branch.
The machine is thrown away afterwards, so last week's leftovers never leak into
this week, and separate batches of upgrades can run side by side.

### Hand the agent your upgrade playbook

Our house rules for upgrades are kept as **skills** and **memory**, a playbook
the agent carries and keeps improving. It records the packages we pin on purpose,
the right way to run our tests, which order to take major versions in, and the
migrations that hurt us in the past. If a bump ever needs a manual fix, we note
it once and the agent does it itself from then on.

### Plug in what an upgrade has to touch

**Connectors** are scoped links to your tools. The keys stay on our servers, so
the model never holds a raw token. With them the agent can:

- **Check the manifests**: see which packages are out of date and by how much,
keeping small patch and minor bumps apart from major ones.
- **Bump and install inside the sandbox**: refresh the lockfile on a branch, do
a clean install, and save the full resolver output.
- **Run every test**: unit, integration and end-to-end, all in the sandbox, so a
breaking bump fails on its own machine instead of in someone's review.
- **File the PR on GitHub**: push the branch with each package's changelog and
the passing result as a pull request.

### Draw the lines it cannot cross

No green suite, no PR. A failing upgrade gets dropped or broken into smaller
pieces, never passed along for a person to debug. Merging is off limits: that
step is a **human approval gate**. Keys are stored encrypted in the **Secrets
Manager**, handed over only when a run starts, and only to the agents you grant
them to.

### Let the weekly run do its thing

From then on, the week takes care of itself. The agent spots what is out of date,
bumps it, tests it in the sandbox and hands you a PR that has already passed,
with related bumps bundled and changelogs attached. When a bump breaks a test, it
never turns into a PR. You get a flag and the failing test instead.

> **The pattern**
> Once a week a **trigger** opens a session with scoped **connectors** to the
> repo and CI. Your upgrade know-how lives in **skills** and **memory**. The agent
> shows the change is green on its own machine, and a person decides whether it
> merges.

## Guardrails

This agent edits dependencies and runs code, so we keep its reach small and its
work boxed in:

- **Isolation.** Each run gets a private sandbox and a branch of its own. It can
  install, resolve and test as much as it needs, but the branch and the test
  result are the only things that leave.
- **Scoped secrets.** The GitHub and CI keys are stored encrypted in the
  **Secrets Manager**, passed into the sandbox when the run begins, and only
  handed to the agents you grant them to.
- **PR-gated.** Once the pull request is filed, the agent is done. It cannot
  merge and cannot push to the default branch. A person makes that call.
- **Everything is code.** Setup, skills and permissions live as files in the
  repo, tracked in version control. To change them you open a reviewed **change
  request**; there is no dashboard toggle.

## The outcome

- **Weekly:** Bumps arrive on a timetable, not after something breaks
- **Green-only:** No PR until every test in the suite has passed
- **Human merge:** The agent brings proof, your team makes the call

The packages stay fresh, and no one has to put upgrades on a calendar. Every
upgrade PR in your queue has already survived the complete test suite. Instead of
pulling a branch down and testing a bump yourself, you open a passing change with
its changelog right there.
