Skip to content

Commit 58682a2

Browse files
committed
monitor: implement runner registration for Forgejo Actions
1 parent 40ad5fa commit 58682a2

File tree

2 files changed

+64
-10
lines changed

2 files changed

+64
-10
lines changed

monitor/src/github.rs

Lines changed: 63 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use chrono::{DateTime, FixedOffset};
77
use cmd_lib::{run_cmd, run_fun};
88
use jane_eyre::eyre::{self, Context};
99
use serde::{Deserialize, Serialize};
10+
use serde_json::json;
1011
use settings::{DOTENV, TOML};
1112
use tracing::trace;
1213

@@ -141,15 +142,72 @@ pub fn register_runner(runner_name: &str, label: &str, work_folder: &str) -> eyr
141142
let github_api_suffix = &TOML.github_api_suffix;
142143
let result = if TOML.github_api_is_forgejo {
143144
// FIXME: this leaks the token in logs when the command fails
144-
// TODO: this doesn’t actually register a runner, it just gets a registration token
145-
run_fun!(curl -fsSH "Authorization: token $github_or_forgejo_token"
146-
-X POST "$github_api_scope_url/actions/runners/registration-token/TODO")?
145+
let registration_token = run_fun!(curl -fsSH "Authorization: token $github_or_forgejo_token"
146+
-X POST "$github_api_scope_url/actions/runners/registration-token"
147+
| jq -er .token)?;
148+
149+
// Hit the internal(?) registration API using JSON instead of protobuf (<https://connectrpc.com>):
150+
// <https://code.forgejo.org/forgejo/actions-proto/src/commit/1b2c1084d34619fbb6cb768741a9321c49956032/proto/runner/v1/messages.proto>
151+
// <https://codeberg.org/forgejo/forgejo/src/commit/ffbd500600d45fd86805004694086faaf68ecbdb/routers/api/actions/runner/runner.go>
152+
#[derive(Clone, Debug, Deserialize, Serialize)]
153+
struct RegisterRequest {
154+
name: String,
155+
token: String,
156+
version: String,
157+
labels: Vec<String>,
158+
ephemeral: bool,
159+
}
160+
#[derive(Clone, Debug, Deserialize, Serialize)]
161+
struct ForgejoApiRegisterResponse {
162+
runner: ForgejoApiRegisterResponseRunner,
163+
}
164+
#[derive(Clone, Debug, Deserialize, Serialize)]
165+
struct ForgejoApiRegisterResponseRunner {
166+
id: String,
167+
uuid: String,
168+
token: String,
169+
name: String,
170+
version: String,
171+
labels: Vec<String>,
172+
}
173+
impl ForgejoApiRegisterResponseRunner {
174+
/// Convert the runner to the `.runner` format expected by forgejo-runner.
175+
fn to_forgejo_dot_runner(&self) -> eyre::Result<String> {
176+
let id = usize::from_str_radix(&self.id, 10)?;
177+
let address = TOML.github_api_scope_url.join("/")?.to_string();
178+
let address = address.strip_suffix("/").expect("Guaranteed by argument");
179+
Ok(serde_json::to_string(&json!({
180+
"id": id,
181+
"uuid": self.uuid,
182+
"name": self.name,
183+
"token": self.token,
184+
"address": address,
185+
"labels": self.labels,
186+
}))?)
187+
}
188+
}
189+
let request = RegisterRequest {
190+
name: format!("{runner_name}@{github_api_suffix}"),
191+
token: registration_token,
192+
version: "ServoCI".to_owned(),
193+
labels: vec!["self-hosted".to_owned(), label.to_owned()],
194+
ephemeral: true,
195+
};
196+
let request = serde_json::to_string(&request)?;
197+
let register_url =
198+
github_api_scope_url.join("/api/actions/runner.v1.RunnerService/Register")?;
199+
let response = run_fun!(curl -fsSH "Content-Type: application/json"
200+
--data-raw $request "$register_url")?;
201+
let response: ForgejoApiRegisterResponse = serde_json::from_str(&response)?;
202+
response.runner.to_forgejo_dot_runner()?
147203
} else {
148-
run_fun!(GITHUB_TOKEN=$github_or_forgejo_token gh api
204+
let response = run_fun!(GITHUB_TOKEN=$github_or_forgejo_token gh api
149205
-H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28"
150206
--method POST "$github_api_scope_url/actions/runners/generate-jitconfig"
151207
-f "name=$runner_name@$github_api_suffix" -F "runner_group_id=1" -f "work_folder=$work_folder"
152-
-f "labels[]=self-hosted" -f "labels[]=X64" -f "labels[]=$label")?
208+
-f "labels[]=self-hosted" -f "labels[]=X64" -f "labels[]=$label")?;
209+
let response: ApiGenerateJitconfigResponse = serde_json::from_str(&response)?;
210+
response.encoded_jit_config
153211
};
154212

155213
Ok(result)

monitor/src/runner.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -355,13 +355,9 @@ impl Runner {
355355

356356
cfg_if! {
357357
if #[cfg(not(test))] {
358-
use monitor::github::ApiGenerateJitconfigResponse;
359-
360358
fn read_github_jitconfig(id: usize) -> eyre::Result<String> {
361359
let result = get_runner_data_path(id, Path::new("github-api-registration"))?;
362-
let result: ApiGenerateJitconfigResponse =
363-
serde_json::from_reader(File::open(result)?)?;
364-
Ok(result.encoded_jit_config)
360+
Ok(std::fs::read_to_string(result)?)
365361
}
366362

367363
fn runner_created_time(id: usize) -> eyre::Result<SystemTime> {

0 commit comments

Comments
 (0)