Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
18 changes: 9 additions & 9 deletions .github/workflows/crowdgpt-runner.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Build and publish the CrowdGPT runner image (plugins/crowdgpt/runner).
# Build and publish the CrowdGPT runner image (node/crates/c0mpute-core/crowdgpt-runner).
#
# The image holds CrowdGPT's client (GPL-3.0, unmodified) at the commit pinned
# by ARG CROWDGPT_COMMIT in the Dockerfile, which must equal CROWDGPT_COMMIT in
Expand All @@ -18,11 +18,11 @@ on:
push:
branches: [master]
paths:
- "plugins/crowdgpt/runner/**"
- "node/crates/c0mpute-core/crowdgpt-runner/**"
- ".github/workflows/crowdgpt-runner.yml"
pull_request:
paths:
- "plugins/crowdgpt/runner/**"
- "node/crates/c0mpute-core/crowdgpt-runner/**"
- ".github/workflows/crowdgpt-runner.yml"
workflow_dispatch:

Expand All @@ -38,9 +38,9 @@ jobs:
- name: Watchdog parses and the pin is consistent
run: |
set -eu
sh -n plugins/crowdgpt/runner/c0mpute-crowdgpt-run
shellcheck -s sh plugins/crowdgpt/runner/c0mpute-crowdgpt-run || true
pin=$(sed -n 's/^ARG CROWDGPT_COMMIT=//p' plugins/crowdgpt/runner/Dockerfile)
sh -n node/crates/c0mpute-core/crowdgpt-runner/c0mpute-crowdgpt-run
shellcheck -s sh node/crates/c0mpute-core/crowdgpt-runner/c0mpute-crowdgpt-run || true
pin=$(sed -n 's/^ARG CROWDGPT_COMMIT=//p' node/crates/c0mpute-core/crowdgpt-runner/Dockerfile)
grep -q "CROWDGPT_COMMIT: &str = \"$pin\"" node/crates/c0mpute-core/src/crowdgpt.rs
grep -q "crowdgpt-$(echo "$pin" | cut -c1-12)" plugins/crowdgpt/module.toml
echo "pinned CrowdGPT commit: $pin"
Expand Down Expand Up @@ -73,7 +73,7 @@ jobs:
id: tags
run: |
set -eu
pin=$(sed -n 's/^ARG CROWDGPT_COMMIT=//p' plugins/crowdgpt/runner/Dockerfile)
pin=$(sed -n 's/^ARG CROWDGPT_COMMIT=//p' node/crates/c0mpute-core/crowdgpt-runner/Dockerfile)
short=$(echo "$pin" | cut -c1-12)
echo "pin=${pin}" >> "$GITHUB_OUTPUT"
echo "tags=${IMAGE}:crowdgpt-${short},${IMAGE}:stable,${IMAGE}:${GITHUB_SHA}" >> "$GITHUB_OUTPUT"
Expand All @@ -84,8 +84,8 @@ jobs:
with:
labels: |
org.opencontainers.image.source=https://github.com/${{ github.repository }}
context: plugins/crowdgpt/runner
file: plugins/crowdgpt/runner/Dockerfile
context: node/crates/c0mpute-core/crowdgpt-runner
file: node/crates/c0mpute-core/crowdgpt-runner/Dockerfile
load: ${{ github.event_name == 'pull_request' }}
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.tags.outputs.tags }}
Expand Down
3 changes: 0 additions & 3 deletions Dockerfile.web
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,6 @@ FROM rust:1.92-bookworm AS rustbuild
WORKDIR /src
COPY Cargo.toml Cargo.lock ./
COPY node ./node
# The crowdgpt runner's Dockerfile and watchdog are compiled into the binary
# (`c0mpute crowdgpt setup --build`).
COPY plugins/crowdgpt/runner ./plugins/crowdgpt/runner
RUN cargo build --release --bin c0mpute

# ── stage 2: build the Next.js site (Bun) ────────────────────────────────
Expand Down
13 changes: 9 additions & 4 deletions node/crates/c0mpute-cli/src/crowdgpt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,8 +171,7 @@ pub async fn run(cmd: CrowdgptCmd, config_path: &Path) -> Result<()> {
}

fn owner_args(dir: &Path) -> Vec<String> {
use std::os::unix::fs::MetadataExt;
std::fs::metadata(dir).map(|m| vec!["--user".to_string(), format!("{}:{}", m.uid(), m.gid())]).unwrap_or_default()
cg::owner_of(dir).map(|(u, g)| vec!["--user".to_string(), format!("{u}:{g}")]).unwrap_or_default()
}

fn credited_as() -> String {
Expand All @@ -190,11 +189,17 @@ fn credited_as() -> String {

fn write_token(token: &str) -> Result<()> {
use std::io::Write;
use std::os::unix::fs::OpenOptionsExt;
anyhow::ensure!(!token.is_empty() && token.len() < 4096 && !token.chars().any(char::is_whitespace), "that does not look like a token");
let p = cg::token_path();
std::fs::create_dir_all(p.parent().unwrap())?;
let mut f = std::fs::OpenOptions::new().write(true).create(true).truncate(true).mode(0o600).open(&p)?;
let mut o = std::fs::OpenOptions::new();
o.write(true).create(true).truncate(true);
#[cfg(unix)]
{
use std::os::unix::fs::OpenOptionsExt;
o.mode(0o600);
}
let mut f = o.open(&p)?;
f.write_all(token.as_bytes())?;
Ok(())
}
Expand Down
18 changes: 13 additions & 5 deletions node/crates/c0mpute-core/src/crowdgpt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
//! The client is GPL-3.0. c0mpute never vendors, links or imports it: it runs
//! as a separate process in its own container, built from CrowdGPT's public
//! repository at the reviewed commit [`CROWDGPT_COMMIT`] by our MIT Dockerfile
//! (plugins/crowdgpt/runner). c0mpute talks to it only through `docker run` /
//! (node/crates/c0mpute-core/crowdgpt-runner). c0mpute talks to it only through `docker run` /
//! `docker stop` and its log lines.
//!
//! # Containment
Expand Down Expand Up @@ -96,10 +96,11 @@ pub fn pull_ref() -> String {
format!("{RUNNER_REPOSITORY}:crowdgpt-{}", &CROWDGPT_COMMIT[..12])
}

/// Our Dockerfile and watchdog, embedded so `c0mpute crowdgpt setup --build`
/// Our Dockerfile and watchdog (node/crates/c0mpute-core/crowdgpt-runner,
/// inside the crate so builds that copy only `node/` still compile), embedded so `c0mpute crowdgpt setup --build`
/// needs only docker (CrowdGPT's source is fetched inside the build).
pub const DOCKERFILE: &str = include_str!("../../../../plugins/crowdgpt/runner/Dockerfile");
pub const WATCHDOG: &str = include_str!("../../../../plugins/crowdgpt/runner/c0mpute-crowdgpt-run");
pub const DOCKERFILE: &str = include_str!("../crowdgpt-runner/Dockerfile");
pub const WATCHDOG: &str = include_str!("../crowdgpt-runner/c0mpute-crowdgpt-run");

/// `[crowdgpt]` in config.toml. Off by default.
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
Expand Down Expand Up @@ -454,11 +455,18 @@ pub fn decide(running: bool, busy: bool, blocked: bool, idle_for: Duration, idle
}
}

fn owner_of(dir: &Path) -> Option<(u32, u32)> {
/// The uid:gid owning `dir`, which the container runs as (`None` off Unix).
#[cfg(unix)]
pub fn owner_of(dir: &Path) -> Option<(u32, u32)> {
use std::os::unix::fs::MetadataExt;
std::fs::metadata(dir).ok().map(|m| (m.uid(), m.gid()))
}

#[cfg(not(unix))]
pub fn owner_of(_dir: &Path) -> Option<(u32, u32)> {
None
}

/// Running crowdgpt containers (by [`LABEL`]).
pub async fn running_containers() -> Vec<String> {
let out = crate::container::command().args(["ps", "-q", "--filter", &format!("label={LABEL}")]).stderr(std::process::Stdio::null()).output().await;
Expand Down
2 changes: 1 addition & 1 deletion plugins/crowdgpt/module.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
#
# GPL isolation. The client is GPL-3.0 and is never vendored, linked or
# imported: it runs unmodified as a separate process in a container built by
# runner/Dockerfile (MIT) from CrowdGPT's repository at one reviewed commit
# node/crates/c0mpute-core/crowdgpt-runner/Dockerfile (MIT) from CrowdGPT's repository at one reviewed commit
# (CROWDGPT_COMMIT in crowdgpt.rs, also the image's
# org.c0mpute.crowdgpt.commit label, checked before every run). CI publishes
# it as ghcr.io/profullstack/c0mpute-crowdgpt-runner:crowdgpt-<sha12>
Expand Down
Loading