A new update_meta node renders internal/meta's flake.nix with hive-meta-flake, the renderer hive-c0re uses: hyperhive pinned to its forge main, each custom agent a hive places pinned to its agent-configs main, all over https, and the swarm-wide values from SWARM_CONTROLLER_META_FLAKE (set by swarm-controller.nix from services.hyperhive.swarm.*). The swarm builder locks it, and the controller commits flake.nix and flake.lock in one commit and gives every hive's forge account read on the repo. A render equal to the committed flake.nix sends no lock and commits nothing. It runs at start, when hyperhive's main moves, before the deploy of a merged config PR and before the first deploy of a new agent; those deploys now wait for it. agent_web_port moves into hive-meta-flake so both callers compute the same port; hive-c0re re-exports it. On deploy: internal/meta appears on the forge and follows every merge. No hive builds from it yet. Refs #4857
77 lines
2.5 KiB
Rust
77 lines
2.5 KiB
Rust
//! `internal/meta` on the forge: the repo the swarm meta flake is committed to
|
|
//! (`crate::meta_flake`), and the read grant each hive's account holds on it.
|
|
|
|
use anyhow::{Context, Result};
|
|
use base64::Engine as _;
|
|
use forgejo_api::structs::{
|
|
AddCollaboratorOptionPermission, ChangeFileOperation, ChangeFileOperationOperation,
|
|
ChangeFilesOptions,
|
|
};
|
|
|
|
use super::objects::SHARED_ORG;
|
|
use super::{Client, DefaultBranchFiles};
|
|
use crate::meta_flake::{META_REPO, MetaFile, MetaForge};
|
|
|
|
impl MetaForge for Client {
|
|
async fn head_files(
|
|
&self,
|
|
owner: &str,
|
|
repo: &str,
|
|
paths: &[&str],
|
|
) -> Result<Option<DefaultBranchFiles>> {
|
|
self.default_branch_files(owner, repo, paths).await
|
|
}
|
|
|
|
async fn ensure_meta_repo(&self) -> Result<()> {
|
|
self.create_shared_repo(SHARED_ORG, META_REPO, true).await
|
|
}
|
|
|
|
async fn grant_meta_read(&self, login: &str) -> Result<()> {
|
|
self.add_collaborator_to(
|
|
SHARED_ORG,
|
|
META_REPO,
|
|
login,
|
|
AddCollaboratorOptionPermission::Read,
|
|
)
|
|
.await
|
|
}
|
|
|
|
async fn commit_meta(&self, message: &str, files: Vec<MetaFile>) -> Result<()> {
|
|
let ops: Vec<ChangeFileOperation> = files
|
|
.into_iter()
|
|
.map(|f| ChangeFileOperation {
|
|
content: Some(base64::engine::general_purpose::STANDARD.encode(f.bytes)),
|
|
from_path: None,
|
|
operation: if f.sha.is_some() {
|
|
ChangeFileOperationOperation::Update
|
|
} else {
|
|
ChangeFileOperationOperation::Create
|
|
},
|
|
path: f.path.to_owned(),
|
|
sha: f.sha,
|
|
})
|
|
.collect();
|
|
self.api
|
|
.call(|api| {
|
|
api.repo_change_files(
|
|
SHARED_ORG,
|
|
META_REPO,
|
|
ChangeFilesOptions {
|
|
author: None,
|
|
branch: None,
|
|
committer: None,
|
|
dates: None,
|
|
files: ops.clone(),
|
|
force_overwrite_new_branch: None,
|
|
message: Some(message.to_owned()),
|
|
new_branch: None,
|
|
signoff: None,
|
|
},
|
|
)
|
|
.into_future()
|
|
})
|
|
.await
|
|
.with_context(|| format!("commit to {SHARED_ORG}/{META_REPO}"))?;
|
|
Ok(())
|
|
}
|
|
}
|