pr_01m47d15m3e54sn21z27rpy5n9/crates/contracts/src/actions.rs

319 lines9,800 bytesCodeBlame
1//! The actions service: GitHub Actions workflows, run on g1t as they are.
2//!
3//! A repository's `.g1t/workflows/*.yml`, in GitHub's format, are read
4//! from the commit an
5//! event is about (the default branch for issues, schedules and manual
6//! runs). Each workflow an event starts becomes a run; each job of the run
7//! (one per matrix combination) runs in a sandbox once the jobs it needs
8//! have finished. Jobs report their steps and logs back as they go, and a
9//! run on a pull request's head is a status on that pull request.
10//!
11//! Secrets and variables belong to a repository or to its workspace; a
12//! repository's override its workspace's of the same name. Secret values
13//! are sealed at rest and never returned.
14//!
15//! Mirrors `packages/contracts/src/actions.ts`.
16
17use serde::{Deserialize, Serialize};
18use serde_json::Value;
19
20use crate::repos::RepoPath;
21use crate::{User, Viewer};
22
23/// A note on something in a workflow that runs differently on g1t.
24#[derive(Clone, Debug, Serialize, Deserialize)]
25#[serde(rename_all = "camelCase")]
26pub struct WorkflowNote {
27 /// `info`, `warning` or `unsupported`.
28 pub severity: String,
29 pub job: Option<String>,
30 pub message: String,
31}
32
33#[derive(Clone, Debug, Serialize, Deserialize)]
34#[serde(rename_all = "camelCase")]
35pub struct Workflow {
36 pub id: String,
37 /// `.g1t/workflows/ci.yml`.
38 pub path: String,
39 pub name: String,
40 /// The events that start it, such as `push` and `pull_request`.
41 pub events: Vec<String>,
42 /// `active`, or `disabled` when a member turned it off.
43 pub state: String,
44 /// Why the file cannot be used, if it cannot.
45 pub error: Option<String>,
46 pub notes: Vec<WorkflowNote>,
47 /// `on.workflow_dispatch.inputs` as written, when it can be run by hand.
48 pub dispatch: Option<Value>,
49 pub last_run: Option<WorkflowRun>,
50}
51
52#[derive(Clone, Debug, Serialize, Deserialize)]
53#[serde(rename_all = "camelCase")]
54pub struct WorkflowRun {
55 pub id: String,
56 pub workflow_id: String,
57 pub path: String,
58 /// The workflow's name.
59 pub name: String,
60 /// `run-name`, or what started it: a commit's subject, a pull request's title.
61 pub title: String,
62 /// Counts the workflow's runs: 1, 2, 3…
63 pub number: u64,
64 pub attempt: u64,
65 /// The GitHub event: `push`, `pull_request`, `schedule`…
66 pub event: String,
67 #[serde(rename = "ref")]
68 pub git_ref: String,
69 pub sha: String,
70 /// The pull request it ran for, if any.
71 pub pull: Option<u32>,
72 /// `queued`, `in_progress` or `completed`.
73 pub status: String,
74 /// When completed: `success`, `failure`, `cancelled` or `skipped`.
75 pub conclusion: Option<String>,
76 /// Why it could not start, such as a workflow file that does not read.
77 pub error: Option<String>,
78 /// Username of whoever caused it.
79 pub actor: Option<String>,
80 pub created_at: String,
81 pub started_at: Option<String>,
82 pub finished_at: Option<String>,
83}
84
85#[derive(Clone, Debug, Default, Serialize, Deserialize)]
86#[serde(rename_all = "camelCase")]
87pub struct StepState {
88 /// From 1.
89 pub number: u32,
90 pub name: String,
91 /// `queued`, `in_progress` or `completed`.
92 pub status: String,
93 /// `success`, `failure`, `cancelled` or `skipped`.
94 pub conclusion: Option<String>,
95 pub started_at: Option<String>,
96 pub finished_at: Option<String>,
97}
98
99/// A message a step left with `::error::`, `::warning::` or `::notice::`.
100#[derive(Clone, Debug, Default, Serialize, Deserialize)]
101#[serde(rename_all = "camelCase")]
102pub struct Annotation {
103 /// `error`, `warning` or `notice`.
104 pub level: String,
105 pub message: String,
106 pub title: Option<String>,
107 pub file: Option<String>,
108 pub line: Option<u32>,
109}
110
111#[derive(Clone, Debug, Serialize, Deserialize)]
112#[serde(rename_all = "camelCase")]
113pub struct Job {
114 pub id: String,
115 pub run_id: String,
116 /// Its key under `jobs:`.
117 pub key: String,
118 /// With its matrix combination: `test (ubuntu-latest, 20)`.
119 pub name: String,
120 pub needs: Vec<String>,
121 /// `queued`, `waiting` (for the jobs it needs), `in_progress` or `completed`.
122 pub status: String,
123 pub conclusion: Option<String>,
124 pub steps: Vec<StepState>,
125 pub annotations: Vec<Annotation>,
126 /// Why it did not run, or what stopped it.
127 pub reason: Option<String>,
128 pub started_at: Option<String>,
129 pub finished_at: Option<String>,
130}
131
132#[derive(Clone, Debug, Serialize, Deserialize)]
133#[serde(rename_all = "camelCase")]
134pub struct RunDetail {
135 pub run: WorkflowRun,
136 pub jobs: Vec<Job>,
137 /// The workflow's notes, as of the run's commit.
138 pub notes: Vec<WorkflowNote>,
139}
140
141#[derive(Clone, Debug, Serialize, Deserialize)]
142#[serde(rename_all = "camelCase")]
143pub struct LogChunk {
144 pub seq: u64,
145 /// The step it belongs to, from 1; 0 for the job's setup.
146 pub step: u32,
147 pub text: String,
148}
149
150#[derive(Clone, Debug, Serialize, Deserialize)]
151#[serde(rename_all = "camelCase")]
152pub struct JobLog {
153 pub chunks: Vec<LogChunk>,
154 /// Whether the job has finished, so no more will come.
155 pub done: bool,
156}
157
158/// A secret's or variable's name, and for a variable its value.
159#[derive(Clone, Debug, Serialize, Deserialize)]
160#[serde(rename_all = "camelCase")]
161pub struct Setting {
162 pub name: String,
163 /// Variables only; secrets are never returned.
164 pub value: Option<String>,
165 /// `repository` or `workspace`.
166 pub scope: String,
167 pub updated_at: String,
168}
169
170// --- Methods ---------------------------------------------------------------
171
172/// `workflows`. Returns `Outcome<Vec<Workflow>>`.
173#[derive(Debug, Serialize, Deserialize)]
174pub struct WorkflowsArgs {
175 pub repo: RepoPath,
176 pub viewer: Viewer,
177}
178
179/// `runs`: newest first. Returns `Outcome<Vec<WorkflowRun>>`.
180#[derive(Debug, Serialize, Deserialize)]
181pub struct RunsArgs {
182 pub repo: RepoPath,
183 pub viewer: Viewer,
184 /// A workflow's id or file name.
185 #[serde(default)]
186 pub workflow: Option<String>,
187 #[serde(default)]
188 pub branch: Option<String>,
189 #[serde(default)]
190 pub event: Option<String>,
191 /// The pull request's number.
192 #[serde(default)]
193 pub pull: Option<u32>,
194 #[serde(default)]
195 pub sha: Option<String>,
196 #[serde(default)]
197 pub limit: Option<u32>,
198}
199
200/// `run`. Returns `Outcome<RunDetail>`.
201#[derive(Debug, Serialize, Deserialize)]
202pub struct RunArgs {
203 pub repo: RepoPath,
204 pub viewer: Viewer,
205 pub id: String,
206}
207
208/// `logs`: a job's log after `after`. Returns `Outcome<JobLog>`.
209#[derive(Debug, Serialize, Deserialize)]
210pub struct LogsArgs {
211 pub repo: RepoPath,
212 pub viewer: Viewer,
213 pub job: String,
214 #[serde(default)]
215 pub after: u64,
216}
217
218/// `dispatch`: run a workflow that has `workflow_dispatch`. Members only.
219/// Returns `Outcome<WorkflowRun>`.
220#[derive(Debug, Serialize, Deserialize)]
221pub struct DispatchArgs {
222 pub actor: User,
223 pub repo: RepoPath,
224 /// A workflow's id or file name.
225 pub workflow: String,
226 /// A branch or tag; the default branch when absent.
227 #[serde(default, rename = "ref")]
228 pub git_ref: Option<String>,
229 #[serde(default)]
230 pub inputs: serde_json::Map<String, Value>,
231}
232
233/// `cancel` and `rerun` (all jobs, or with `failed_only` the ones that did
234/// not succeed). Members only. Returns `Outcome<WorkflowRun>`.
235#[derive(Debug, Serialize, Deserialize)]
236pub struct RunActionArgs {
237 pub actor: User,
238 pub repo: RepoPath,
239 pub id: String,
240 #[serde(default)]
241 pub failed_only: bool,
242}
243
244/// `set_workflow_enabled`. Members only. Returns `Outcome<Workflow>`.
245#[derive(Debug, Serialize, Deserialize)]
246pub struct SetWorkflowEnabledArgs {
247 pub actor: User,
248 pub repo: RepoPath,
249 pub workflow: String,
250 pub enabled: bool,
251}
252
253/// Whose secrets or variables: a repository's, or with only `workspace`,
254/// a workspace's.
255#[derive(Clone, Debug, Serialize, Deserialize)]
256pub struct SettingsOwner {
257 #[serde(default)]
258 pub repo: Option<RepoPath>,
259 #[serde(default)]
260 pub workspace: Option<String>,
261}
262
263/// `settings`: the secrets (`kind: secret`) or variables (`kind: variable`)
264/// of a repository, with its workspace's, or of a workspace. Members only.
265/// Returns `Outcome<Vec<Setting>>`.
266#[derive(Debug, Serialize, Deserialize)]
267pub struct SettingsArgs {
268 pub actor: User,
269 #[serde(flatten)]
270 pub owner: SettingsOwner,
271 pub kind: String,
272}
273
274/// `set_setting`: add or replace one. A repository's need a member; a
275/// workspace's an owner. Returns `Outcome<Setting>`.
276#[derive(Debug, Serialize, Deserialize)]
277pub struct SetSettingArgs {
278 pub actor: User,
279 #[serde(flatten)]
280 pub owner: SettingsOwner,
281 pub kind: String,
282 pub name: String,
283 pub value: String,
284}
285
286/// `delete_setting`. Returns `Outcome<bool>`.
287#[derive(Debug, Serialize, Deserialize)]
288pub struct DeleteSettingArgs {
289 pub actor: User,
290 #[serde(flatten)]
291 pub owner: SettingsOwner,
292 pub kind: String,
293 pub name: String,
294}
295
296/// `job_spec` and `job_report`: the sandbox running a job, with the job's
297/// own token. `report` is one of:
298/// `{"kind": "step", "number", "status", "conclusion"}`,
299/// `{"kind": "log", "step", "text"}`,
300/// `{"kind": "annotation", "level", "message", "title", "file", "line"}`,
301/// `{"kind": "done", "conclusion", "outputs", "reason"}`.
302#[derive(Debug, Serialize, Deserialize)]
303pub struct JobCallArgs {
304 pub job: String,
305 pub token: String,
306 #[serde(default)]
307 pub report: Value,
308}
309
310/// What the runner needs to start a job's sandbox.
311#[derive(Debug, Serialize, Deserialize)]
312#[serde(rename_all = "camelCase")]
313pub struct StartJobArgs {
314 pub job: String,
315 pub token: String,
316 pub repo: RepoPath,
317 /// Minutes before the job is stopped.
318 pub timeout_minutes: u32,
319}