1#[derive(Debug, Clone, Copy)]
7pub struct ResourceTemplate {
8 pub name: &'static str,
9 pub description: &'static str,
10 pub contents: &'static str,
11 pub companions: &'static [CompanionFile],
12 pub companion_trackers: &'static [CompanionTracker],
13}
14
15#[derive(Debug, Clone, Copy)]
16pub struct CompanionFile {
17 pub name: &'static str,
18 pub contents: &'static str,
19}
20
21#[derive(Debug, Clone, Copy)]
25pub struct CompanionTracker {
26 pub name: &'static str,
27 pub audience: &'static str,
28 pub merge_with_source: bool,
29}
30
31pub const RESOURCE_TEMPLATES: &[ResourceTemplate] = &[
32 ResourceTemplate {
33 name: "process",
34 description: "a branch-local long-running process with its own port",
35 companions: &[],
36 companion_trackers: &[],
37 contents: r#"kind = "process"
38ownership = "branch"
39# Trackers or resources that must be ready first, e.g. ["deps", "runtime-env"].
40depends_on = []
41
42[ports]
43app = { start = 3100, env = "PORT" }
44
45[actions.start]
46# Edit to your dev command, e.g. "pnpm dev" or "bin/rails server".
47command = "npm run dev"
48long_running = true
49
50[actions.stop]
51signal = "term"
52
53[exports]
54APP_URL = "http://127.0.0.1:{{ports.app}}"
55"#,
56 },
57 ResourceTemplate {
58 name: "pnpm",
59 description: "dependency install via pnpm; recomputed, never copied",
60 companions: &[CompanionFile {
63 name: "pnpm-store",
64 contents: r#"kind = "external-store"
65ownership = "user"
66
67[checkpoint]
68mode = "hash"
69paths = ["pnpm-lock.yaml"]
70
71[restore]
72mode = "none"
73"#,
74 }],
75 companion_trackers: &[],
76 contents: r#"kind = "command"
77ownership = "workspace"
78depends_on = ["pnpm-store"]
79
80[identity]
81paths = ["package.json", "pnpm-lock.yaml"]
82
83[actions.prepare]
84command = "pnpm install --frozen-lockfile"
85
86[checkpoint]
87mode = "hash"
88paths = ["package.json", "pnpm-lock.yaml"]
89
90[restore]
91mode = "recompute"
92action = "prepare"
93"#,
94 },
95 ResourceTemplate {
96 name: "command-snapshot",
97 description: "a daemon-owned database captured through the daemon into a tracker",
98 companions: &[],
99 companion_trackers: &[CompanionTracker {
102 name: "db-snapshots",
103 audience: "project-devs",
104 merge_with_source: false,
105 }],
106 contents: r#"kind = "command-snapshot"
107ownership = "branch"
108
109# A branch-local database, named after the instance so instances never share
110# one. Edit the commands for your database; the shape is what matters:
111# checkpoint emits a dump into the lane, restore reads it back.
112
113[actions.prepare]
114command = "createdb {{branch.slug}} || true"
115
116[actions.migrate]
117# Edit to your migration command.
118command = "npm run db:migrate"
119
120[checkpoint]
121mode = "command"
122command = "pg_dump {{branch.slug}} > {{snapshot.path}}/db.sql && echo {{snapshot.path}}/db.sql"
123into_tracker = "db-snapshots"
124
125[restore]
126mode = "command"
127command = "dropdb {{branch.slug}} --if-exists && createdb {{branch.slug}} && psql --quiet {{branch.slug}} < {{state_ref}}"
128
129[cleanup]
130command = "dropdb {{branch.slug}} --if-exists"
131
132[exports]
133DATABASE_URL = "postgres://localhost/{{branch.slug}}"
134"#,
135 },
136 ResourceTemplate {
137 name: "external",
138 description: "a resource another system owns; newgit holds only a handle",
139 companions: &[],
140 companion_trackers: &[],
141 contents: r#"kind = "external"
142ownership = "external"
143
144# newgit does not own this resource, so it never assumes deletion semantics
145# it did not author: `ownership = "external"` means cleanup runs exactly the
146# command below and nothing else.
147#
148# `captures` reads names out of the prepare command's stdout — either a flat
149# JSON object or KEY=VALUE lines — and publishes them as this resource's
150# exports, so `newgit run` and the hooks below can use them.
151
152[actions.prepare]
153# Edit to your provisioning command.
154command = "cloudctl preview create --branch {{branch.name}} --json"
155captures = ["PREVIEW_ID", "PREVIEW_URL"]
156
157[checkpoint]
158mode = "external"
159state_ref = "{{exports.PREVIEW_ID}}"
160
161[restore]
162# The handle is recorded, not re-created: an undo does not rewind another
163# system. Change to `mode = "command"` if yours can be rewound.
164mode = "external"
165
166[cleanup]
167command = "cloudctl preview delete {{state_ref}}"
168"#,
169 },
170];
171
172pub fn resource_template(name: &str) -> Option<&'static ResourceTemplate> {
173 RESOURCE_TEMPLATES
174 .iter()
175 .find(|template| template.name == name)
176}