Zoo

← back to the zoo

6. A push is a deploy

Pushing to main puts the code live within a minute.

git push is the deploy. What is running, and since when, is in RC_FACTS/deploy.json, written by root, readable by the app.

This is the code serving the zoo right now: read from disk for this request, from commit 0c1c124a02 (live). The zoo's own self-check fetches this page and compares it byte for byte with the file it runs.

exhibits/06-push-is-deploy.php sha256 6d1a46ab9a0a · raw

1<?php
2// Exhibit 6. Root records every deploy in the app's own facts: RC_FACTS/deploy.json has the live
3// and staging commit, when it arrived and who pushed it. The footer of this page reads it.
4return [
5    "n" => 6, "wing" => "Deploy",
6    "title" => "A push is a deploy",
7    "promise" => "Pushing to main puts the code live within a minute.",
8    "block" => "git push is the deploy. What is running, and since when, is in RC_FACTS/deploy.json, written by root, readable by the app.",
9    "show" => function (?array $me): string {
10        $d = fact("deploy.json") ?? [];
11        $out = '<ul class="list">';
12        foreach (["live", "staging"] as $env) {
13            $x = $d[$env] ?? null;
14            $out .= '<li><span class="tag ' . $env . '">' . $env . "</span>" . ($x ? "<code>" . h(substr($x["commit"], 0, 10)) . "</code> by " . h($x["by"]) . ", " . ago(strtotime($x["at"])) : "nothing yet") . "</li>";
15        }
16        return $out . "</ul>";
17    },
18    // The commit running here must be the newest one pushed to this environment's branch.
19    "check" => function (): array {
20        $env = env("RC_ENV");
21        $running = fact("deploy.json")[$env] ?? null;
22        $pushes = fact("pushes.json");
23        if (!$running || $pushes === null) return [false, "RC_FACTS has no deploy.json or pushes.json"];
24        $last = array_values(array_filter($pushes, fn($p) => $p["env"] === $env && str_starts_with($p["result"], "deployed")))[0] ?? null;
25        if (!$last) return [false, "no successful push to $env is recorded"];
26        if ($last["commit"] !== $running["commit"]) return [false, "running " . substr($running["commit"], 0, 10) . " but the last push to $env was " . substr($last["commit"], 0, 10)];
27        $lag = strtotime($running["at"]) - strtotime($last["at"]);
28        if ($lag > 60) return [false, "the last push took {$lag}s to go live"];
29        return [true, "running " . substr($running["commit"], 0, 10) . ", the last push to $env, live {$lag}s after the push"];
30    },
31];