Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
3905bfb
feat: implement Hetzner server management and update Probot integration
mafreud Oct 7, 2025
1f74e06
feat: add runner requirement check for workflow jobs
mafreud Oct 7, 2025
5245bdb
feat: implement job requirement check for OpenCI runner in Probot int…
mafreud Oct 7, 2025
e84d796
feat: add logging for workflow job events in Probot integration
mafreud Oct 7, 2025
63d0406
refactor: rename deploy step for clarity in Firebase functions workflow
mafreud Oct 7, 2025
4844dab
feat: add @octokit/rest dependency to package.json and package-lock.json
mafreud Oct 7, 2025
7c49e1a
feat: add Hetzner API secrets to GitHub webhook configuration
mafreud Oct 7, 2025
1b05ea2
feat: add Hetzner API secrets to GitHub webhook configuration
mafreud Oct 7, 2025
15794c8
fix: add missing return statements in workflow job event handlers
mafreud Oct 7, 2025
66b9da5
fix: ensure proper handling of response in GitHub webhook function
mafreud Oct 7, 2025
649f051
fix: ensure consistent resource allocation for GitHub webhook function
mafreud Oct 7, 2025
171438e
fix: reduce CPU allocation for GitHub webhook function
mafreud Oct 7, 2025
2ee11f7
fix: reduce memory allocation for GitHub webhook function
mafreud Oct 7, 2025
5c8a4de
fix: remove explicit CPU and memory allocation for GitHub webhook fun…
mafreud Oct 7, 2025
eb04987
fix: ensure consistent resource allocation for GitHub webhook function
mafreud Oct 7, 2025
a059c31
fix: implement matrix strategy for CI and deployment runners
mafreud Oct 7, 2025
ce5975e
fix: add error handling for missing environment variables and SSH con…
mafreud Oct 7, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 131 additions & 3 deletions openci-runner/firebase/functions/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion openci-runner/firebase/functions/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"build:watch": "tsc --watch",
"serve": "npm run build && firebase emulators:start --only functions",
"shell": "npm run build && firebase functions:shell",
"start": "probot run ./lib/probot/index.js",
"start": "npm run build && probot run ./lib/probot/index.js",
"deploy": "firebase deploy --only functions",
"logs": "firebase functions:log",
"test": "vitest run"
Expand All @@ -18,6 +18,7 @@
"firebase-admin": "^12.6.0",
"firebase-functions": "^6.0.1",
"nock": "^14.0.10",
"node-ssh": "^13.2.1",
"probot": "^14.0.2"
},
"devDependencies": {
Expand Down
99 changes: 99 additions & 0 deletions openci-runner/firebase/functions/probot/hetzner.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import type { Octokit } from "@octokit/rest";

const baseUrl = "https://api.hetzner.cloud/v1/servers";

export interface OctokitToken {
token: string;
}

export async function deleteServer(id: string, apiKey: string) {
await fetch(`${baseUrl}/${id}`, {
method: "DELETE",
headers: {
Authorization: `Bearer ${apiKey}`,
},
});
}

export type HetznerResponse = {
serverId: number;
ipv4: string;
};

export async function createServer(apiKey: string): Promise<HetznerResponse> {
const body = {
name: crypto.randomUUID(),
location: "fsn1",
server_type: "cpx41",
image: "ubuntu-24.04",
ssh_keys: ["openci-runner-probot"],
};

const response = await fetch(baseUrl, {
method: "POST",
headers: {
Authorization: `Bearer ${apiKey}`,
},
body: JSON.stringify(body),
});

const responseJson = await response.json();

const server = responseJson.server;
const ipv4 = server.public_net.ipv4.ip;

const serverId = server.id;

return {
serverId: serverId,
ipv4: ipv4,
};
}

export async function getServerStatusById(
serverId: number,
apiKey: string,
): Promise<string> {
const _response = await fetch(`${baseUrl}/${serverId}`, {
headers: {
Authorization: `Bearer ${apiKey}`,
},
});
const jsonRes = await _response.json();
return jsonRes.server.status;
}

export async function getJitConfig(
octokit: Octokit,
owner: string,
repo: string,
serverId: number,
): Promise<string> {
const jitConfigRes = await octokit.request(
`POST /repos/{owner}/{repo}/actions/runners/generate-jitconfig`,
{
owner: `${owner}`,
repo: `${repo}`,
name: `OpenCI ランナー ${serverId}`,
runner_group_id: 1,
labels: ["openci-runner-beta"],
work_folder: "_work",
headers: {
"X-GitHub-Api-Version": "2022-11-28",
},
},
);

return jitConfigRes.data.encoded_jit_config;
}

export function initRunner(runnerConfig: string): string {
const command = `
mkdir actions-runner
cd actions-runner
curl -o actions-runner-linux-x64-2.328.0.tar.gz -L https://github.com/actions/runner/releases/download/v2.328.0/actions-runner-linux-x64-2.328.0.tar.gz
tar xzf ./actions-runner-linux-x64-2.328.0.tar.gz
tmux new -d -s runner "RUNNER_ALLOW_RUNASROOT=true ./run.sh --jitconfig ${runnerConfig}"
`;
return command;
}
Loading
Loading