refactor: move ForgeLike to git

This commit is contained in:
Paul Campbell 2024-05-23 16:50:36 +01:00
parent 639223fcaa
commit 64cbe36dac
16 changed files with 220 additions and 202 deletions

View file

@ -1,12 +1,13 @@
use git_next_config::BranchName;
use git_next_config as config;
use git_next_git as git;
use kxio::network::{self, Network};
use tracing::error;
pub async fn get_all(
repo_details: &git::RepoDetails,
net: &Network,
) -> Result<Vec<BranchName>, crate::branch::Error> {
) -> Result<Vec<config::BranchName>, git::branch::Error> {
let hostname = &repo_details.forge.hostname();
let repo_path = &repo_details.repo_path;
use secrecy::ExposeSecret;
@ -28,13 +29,13 @@ pub async fn get_all(
let result = net.get::<Vec<Branch>>(request).await;
let response = result.map_err(|e| {
error!(?e, "Failed to list branches");
crate::branch::Error::NoneFound // BranchListNotAvailable
git::branch::Error::NoneFound // BranchListNotAvailable
})?;
let branches = response
.response_body()
.unwrap_or_default()
.into_iter()
.map(BranchName::from)
.map(config::BranchName::from)
.collect::<Vec<_>>();
Ok(branches)
}
@ -43,7 +44,7 @@ pub async fn get_all(
struct Branch {
name: String,
}
impl From<Branch> for BranchName {
impl From<Branch> for config::BranchName {
fn from(value: Branch) -> Self {
Self::new(value.name)
}

View file

@ -1,15 +1,17 @@
use git_next_config::{BranchName, RepoConfig};
//
use crate as forge;
use git::ForgeLike as _;
use git_next_config as config;
use git_next_git as git;
use kxio::network;
use tracing::{debug, error, info, warn};
use crate::{forgejo::ForgeJoEnv, validation, ForgeLike as _};
pub async fn validate_positions(
forge: &ForgeJoEnv,
forge: &forge::forgejo::ForgeJoEnv,
repository: &git::OpenRepository,
repo_config: RepoConfig,
) -> validation::Result {
repo_config: config::RepoConfig,
) -> git::validation::Result {
let repo_details = &forge.repo_details;
// Collect Commit Histories for `main`, `next` and `dev` branches
let commit_histories = get_commit_histories(repo_details, &repo_config, &forge.net).await;
@ -17,7 +19,7 @@ pub async fn validate_positions(
Ok(commit_histories) => commit_histories,
Err(err) => {
error!(?err, "Failed to get commit histories");
return Err(validation::Error::Network(Box::new(err)));
return Err(git::validation::Error::Network(Box::new(err)));
}
};
@ -27,7 +29,7 @@ pub async fn validate_positions(
"No commits on main branch '{}'",
repo_config.branches().main()
);
return Err(validation::Error::BranchHasNoCommits(
return Err(git::validation::Error::BranchHasNoCommits(
repo_config.branches().main(),
));
};
@ -40,7 +42,7 @@ pub async fn validate_positions(
repo_config.branches().main(),
repo_config.branches().main(),
);
return Err(validation::Error::DevBranchNotBasedOn(
return Err(git::validation::Error::DevBranchNotBasedOn(
repo_config.branches().main(),
));
}
@ -50,7 +52,7 @@ pub async fn validate_positions(
"No commits on next branch '{}",
repo_config.branches().next()
);
return Err(validation::Error::BranchHasNoCommits(
return Err(git::validation::Error::BranchHasNoCommits(
repo_config.branches().next(),
));
};
@ -65,12 +67,12 @@ pub async fn validate_positions(
git::push::Force::From(next.clone().into()),
) {
warn!(?err, "Failed to reset next to main");
return Err(validation::Error::FailedToResetBranch {
return Err(git::validation::Error::FailedToResetBranch {
branch: repo_config.branches().next(),
commit: next,
});
}
return Err(validation::Error::BranchReset(
return Err(git::validation::Error::BranchReset(
repo_config.branches().next(),
));
}
@ -93,12 +95,12 @@ pub async fn validate_positions(
git::push::Force::From(next.clone().into()),
) {
warn!(?err, "Failed to reset next to main");
return Err(validation::Error::FailedToResetBranch {
return Err(git::validation::Error::FailedToResetBranch {
branch: repo_config.branches().next(),
commit: next,
});
}
return Err(validation::Error::BranchReset(
return Err(git::validation::Error::BranchReset(
repo_config.branches().next(),
));
}
@ -107,7 +109,7 @@ pub async fn validate_positions(
"No commits on next branch '{}'",
repo_config.branches().next()
);
return Err(validation::Error::BranchHasNoCommits(
return Err(git::validation::Error::BranchHasNoCommits(
repo_config.branches().next(),
));
};
@ -121,7 +123,7 @@ pub async fn validate_positions(
repo_config.branches().dev(),
repo_config.branches().next()
);
return Err(validation::Error::DevBranchNotBasedOn(
return Err(git::validation::Error::DevBranchNotBasedOn(
repo_config.branches().next(),
)); // dev is not based on next
}
@ -131,12 +133,12 @@ pub async fn validate_positions(
"No commits on dev branch '{}'",
repo_config.branches().dev()
);
return Err(validation::Error::BranchHasNoCommits(
return Err(git::validation::Error::BranchHasNoCommits(
repo_config.branches().dev(),
));
};
Ok(validation::Positions {
Ok(git::validation::Positions {
main,
next,
dev,
@ -146,7 +148,7 @@ pub async fn validate_positions(
async fn get_commit_histories(
repo_details: &git::RepoDetails,
repo_config: &RepoConfig,
repo_config: &config::RepoConfig,
net: &network::Network,
) -> Result<git::commit::Histories, network::NetworkError> {
let main =
@ -180,7 +182,7 @@ async fn get_commit_histories(
#[tracing::instrument(fields(%branch_name),skip_all)]
async fn get_commit_history(
repo_details: &git::RepoDetails,
branch_name: &BranchName,
branch_name: &config::BranchName,
find_commits: Vec<git::Commit>,
net: &kxio::network::Network,
) -> Result<Vec<git::Commit>, network::NetworkError> {

View file

@ -1,14 +1,15 @@
use git_next_config::BranchName;
use git_next_config as config;
use git_next_git as git;
use kxio::network::{self, Network};
use tracing::{error, warn};
pub(super) async fn contents_get(
repo_details: &git::RepoDetails,
net: &Network,
branch: &BranchName,
branch: &config::BranchName,
file_path: &str,
) -> Result<String, crate::file::Error> {
) -> Result<String, git::file::Error> {
let hostname = &repo_details.forge.hostname();
let repo_path = &repo_details.repo_path;
let api_token = &repo_details.forge.token();
@ -31,7 +32,7 @@ pub(super) async fn contents_get(
let result = net.get::<ForgeContentsResponse>(request).await;
let response = result.map_err(|e| {
warn!(?e, "");
crate::file::Error::NotFound(file_path.to_string())
git::file::Error::NotFound(file_path.to_string())
})?;
let status = response.status_code();
let contents = match response.response_body() {
@ -39,30 +40,30 @@ pub(super) async fn contents_get(
// we need to decode (see encoding field) the value of 'content' from the response
match body.content_type {
ForgeContentsType::File => decode_config(body),
_ => Err(crate::file::Error::NotFile(file_path.to_string())),
_ => Err(git::file::Error::NotFile(file_path.to_string())),
}
}
None => {
error!(%status, "Failed to fetch repo config file");
Err(crate::file::Error::Unknown(status.to_string()))
Err(git::file::Error::Unknown(status.to_string()))
}
}?;
Ok(contents)
}
fn decode_config(body: ForgeContentsResponse) -> Result<String, crate::file::Error> {
fn decode_config(body: ForgeContentsResponse) -> Result<String, git::file::Error> {
use base64::Engine;
match body.encoding.as_str() {
"base64" => {
let decoded = base64::engine::general_purpose::STANDARD
.decode(body.content)
.map_err(|_| crate::file::Error::DecodeFromBase64)?;
.map_err(|_| git::file::Error::DecodeFromBase64)?;
let decoded =
String::from_utf8(decoded).map_err(|_| crate::file::Error::DecodeFromUtf8)?;
String::from_utf8(decoded).map_err(|_| git::file::Error::DecodeFromUtf8)?;
Ok(decoded)
}
encoding => Err(crate::file::Error::UnknownEncoding(encoding.to_string())),
encoding => Err(git::file::Error::UnknownEncoding(encoding.to_string())),
}
}

View file

@ -1,14 +1,12 @@
pub mod branch;
mod file;
use git::OpenRepository;
use git_next_config::{BranchName, GitDir, RepoConfig};
use git_next_config as config;
use git_next_git as git;
use kxio::network::{self, Network};
use tracing::{error, info, warn};
use crate::validation;
struct ForgeJo;
#[derive(Clone, Debug)]
pub struct ForgeJoEnv {
@ -30,35 +28,35 @@ impl ForgeJoEnv {
}
}
#[async_trait::async_trait]
impl super::ForgeLike for ForgeJoEnv {
impl git::ForgeLike for ForgeJoEnv {
fn name(&self) -> String {
"forgejo".to_string()
}
async fn branches_get_all(&self) -> Result<Vec<BranchName>, crate::branch::Error> {
async fn branches_get_all(&self) -> Result<Vec<config::BranchName>, git::branch::Error> {
branch::get_all(&self.repo_details, &self.net).await
}
async fn file_contents_get(
&self,
branch: &BranchName,
branch: &config::BranchName,
file_path: &str,
) -> Result<String, crate::file::Error> {
) -> Result<String, git::file::Error> {
file::contents_get(&self.repo_details, &self.net, branch, file_path).await
}
async fn branches_validate_positions(
&self,
repository: git::OpenRepository,
repo_config: RepoConfig,
) -> validation::Result {
repo_config: config::RepoConfig,
) -> git::validation::Result {
branch::validate_positions(self, &repository, repo_config).await
}
fn branch_reset(
&self,
repository: &git::OpenRepository,
branch_name: BranchName,
branch_name: config::BranchName,
to_commit: git::GitRef,
force: git::push::Force,
) -> git::push::Result {
@ -110,7 +108,10 @@ impl super::ForgeLike for ForgeJoEnv {
}
}
fn repo_clone(&self, gitdir: GitDir) -> Result<OpenRepository, git::repository::Error> {
fn repo_clone(
&self,
gitdir: config::GitDir,
) -> Result<git::OpenRepository, git::repository::Error> {
let repository = if !gitdir.exists() {
info!("Local copy not found - cloning...");
self.repo.git_clone(&self.repo_details)?

View file

@ -1,7 +1,5 @@
#![allow(dead_code)]
use git::OpenRepository;
use git_next_config::{BranchName, GitDir, RepoConfig};
use git_next_git as git;
use kxio::network::Network;
@ -13,44 +11,6 @@ mod github;
mod mock_forge;
#[async_trait::async_trait]
pub trait ForgeLike {
fn name(&self) -> String;
/// Returns a list of all branches in the repo.
async fn branches_get_all(&self) -> Result<Vec<BranchName>, branch::Error>;
/// Returns the contents of the file.
async fn file_contents_get(
&self,
branch: &BranchName,
file_path: &str,
) -> Result<String, file::Error>;
/// Assesses the relative positions of the main, next and dev branch and updates their
/// positions as needed.
async fn branches_validate_positions(
&self,
repository: OpenRepository,
repo_config: RepoConfig,
) -> validation::Result;
/// Moves a branch to a new commit.
fn branch_reset(
&self,
repository: &OpenRepository,
branch_name: BranchName,
to_commit: git::GitRef,
force: git::push::Force,
) -> git::push::Result;
/// Checks the results of any (e.g. CI) status checks for the commit.
async fn commit_status(&self, commit: &git::Commit) -> git::commit::Status;
/// Clones a repo to disk.
fn repo_clone(&self, gitdir: GitDir) -> Result<OpenRepository, git::repository::Error>;
}
#[derive(Clone, Debug)]
pub enum Forge {
Mock(mock_forge::MockForgeEnv),
@ -78,7 +38,7 @@ impl Forge {
}
}
impl std::ops::Deref for Forge {
type Target = dyn ForgeLike;
type Target = dyn git::ForgeLike;
fn deref(&self) -> &Self::Target {
match self {
Self::Mock(env) => env,
@ -90,65 +50,5 @@ impl std::ops::Deref for Forge {
}
}
pub mod branch {
#[derive(Debug, derive_more::Display)]
pub enum Error {
#[display("Branch not found: {}", 0)]
NotFound(git_next_config::BranchName),
#[display("Unable to find any branches")]
NoneFound,
}
impl std::error::Error for Error {}
}
pub mod file {
#[derive(Debug, derive_more::Display)]
pub enum Error {
#[display("File not found: {}", 0)]
NotFound(String),
#[display("Unable to parse file contents")]
ParseContent,
#[display("Unable to decode from base64")]
DecodeFromBase64,
#[display("Unable to decoce from UTF-8")]
DecodeFromUtf8,
#[display("Unknown file encoding: {}", 0)]
UnknownEncoding(String),
#[display("Not a file: {}", 0)]
NotFile(String),
#[display("Unknown error (status: {})", 0)]
Unknown(String),
}
impl std::error::Error for Error {}
}
pub mod validation {
use git_next_config::BranchName;
use git_next_git as git;
pub type Result = core::result::Result<Positions, Error>;
pub struct Positions {
pub main: git::Commit,
pub next: git::Commit,
pub dev: git::Commit,
pub dev_commit_history: Vec<git::Commit>,
}
#[derive(Debug, derive_more::Display)]
pub enum Error {
Network(Box<kxio::network::NetworkError>),
#[display("Failed to Reset Branch {branch} to {commit}")]
FailedToResetBranch {
branch: BranchName,
commit: git::Commit,
},
BranchReset(BranchName),
BranchHasNoCommits(BranchName),
DevBranchNotBasedOn(BranchName),
}
impl std::error::Error for Error {}
}
#[cfg(test)]
pub mod tests;

View file

@ -2,11 +2,9 @@
#![cfg(not(tarpaulin_include))]
use git::OpenRepository;
use git_next_config::{BranchName, GitDir, RepoConfig};
use git_next_config as config;
use git_next_git as git;
use crate::{branch, file, validation};
struct MockForge;
#[derive(Clone, Debug)]
pub struct MockForgeEnv;
@ -16,35 +14,35 @@ impl MockForgeEnv {
}
}
#[async_trait::async_trait]
impl super::ForgeLike for MockForgeEnv {
impl git::ForgeLike for MockForgeEnv {
fn name(&self) -> String {
"mock".to_string()
}
async fn branches_get_all(&self) -> Result<Vec<BranchName>, branch::Error> {
async fn branches_get_all(&self) -> Result<Vec<config::BranchName>, git::branch::Error> {
todo!()
}
async fn file_contents_get(
&self,
_branch: &BranchName,
_branch: &config::BranchName,
_file_path: &str,
) -> Result<String, file::Error> {
) -> Result<String, git::file::Error> {
todo!()
}
async fn branches_validate_positions(
&self,
_repository: OpenRepository,
_repo_config: RepoConfig,
) -> validation::Result {
_repository: git::OpenRepository,
_repo_config: config::RepoConfig,
) -> git::validation::Result {
todo!()
}
fn branch_reset(
&self,
_repository: &OpenRepository,
_branch_name: BranchName,
_repository: &git::OpenRepository,
_branch_name: config::BranchName,
_to_commit: git::GitRef,
_force: git::push::Force,
) -> git::push::Result {
@ -55,7 +53,10 @@ impl super::ForgeLike for MockForgeEnv {
todo!()
}
fn repo_clone(&self, _gitdir: GitDir) -> Result<OpenRepository, git::repository::Error> {
fn repo_clone(
&self,
_gitdir: config::GitDir,
) -> Result<OpenRepository, git::repository::Error> {
todo!()
}
}

View file

@ -1,11 +1,11 @@
//
use assert2::let_assert;
use git_next_config::{self as config, ForgeType, RepoConfigSource};
use kxio::network::{MockNetwork, StatusCode};
use git_next_config as config;
use git_next_git as git;
use kxio::network::{MockNetwork, StatusCode};
use super::*;
#[test]
@ -18,9 +18,12 @@ fn test_name() {
let repo_details = git::common::repo_details(
1,
git::Generation::new(),
config::common::forge_details(1, ForgeType::MockForge),
Some(config::common::repo_config(1, RepoConfigSource::Repo)),
GitDir::new(fs.base()),
config::common::forge_details(1, config::ForgeType::MockForge),
Some(config::common::repo_config(
1,
config::RepoConfigSource::Repo,
)),
config::GitDir::new(fs.base()),
);
let forge = Forge::new_forgejo(repo_details, net, repo);
assert_eq!(forge.name(), "forgejo");
@ -46,9 +49,12 @@ async fn test_branches_get() {
let repo_details = git::common::repo_details(
1,
git::Generation::new(),
config::common::forge_details(1, ForgeType::MockForge),
Some(config::common::repo_config(1, RepoConfigSource::Repo)),
GitDir::new(fs.base()),
config::common::forge_details(1, config::ForgeType::MockForge),
Some(config::common::repo_config(
1,
config::RepoConfigSource::Repo,
)),
config::GitDir::new(fs.base()),
);
let forge = Forge::new_forgejo(repo_details, net.clone(), repo);
@ -58,5 +64,5 @@ async fn test_branches_get() {
let_assert!(Some(requests) = net.mocked_requests());
assert_eq!(requests.len(), 1);
assert_eq!(branches, vec![BranchName::new("string")]);
assert_eq!(branches, vec![config::BranchName::new("string")]);
}

View file

@ -17,7 +17,7 @@ tracing = { workspace = true }
# git
# # gix = { workspace = true }
gix = { workspace = true }
# async-trait = { workspace = true }
async-trait = { workspace = true }
# fs/network
kxio = { workspace = true }

8
crates/git/src/branch.rs Normal file
View file

@ -0,0 +1,8 @@
#[derive(Debug, derive_more::Display)]
pub enum Error {
#[display("Branch not found: {}", 0)]
NotFound(git_next_config::BranchName),
#[display("Unable to find any branches")]
NoneFound,
}
impl std::error::Error for Error {}

18
crates/git/src/file.rs Normal file
View file

@ -0,0 +1,18 @@
#[derive(Debug, derive_more::Display)]
pub enum Error {
#[display("File not found: {}", 0)]
NotFound(String),
#[display("Unable to parse file contents")]
ParseContent,
#[display("Unable to decode from base64")]
DecodeFromBase64,
#[display("Unable to decoce from UTF-8")]
DecodeFromUtf8,
#[display("Unknown file encoding: {}", 0)]
UnknownEncoding(String),
#[display("Not a file: {}", 0)]
NotFile(String),
#[display("Unknown error (status: {})", 0)]
Unknown(String),
}
impl std::error::Error for Error {}

View file

@ -0,0 +1,43 @@
use crate as git;
use git_next_config as config;
#[async_trait::async_trait]
pub trait ForgeLike {
fn name(&self) -> String;
/// Returns a list of all branches in the repo.
async fn branches_get_all(&self) -> Result<Vec<config::BranchName>, git::branch::Error>;
/// Returns the contents of the file.
async fn file_contents_get(
&self,
branch: &config::BranchName,
file_path: &str,
) -> Result<String, git::file::Error>;
/// Assesses the relative positions of the main, next and dev branch and updates their
/// positions as needed.
async fn branches_validate_positions(
&self,
repository: git::OpenRepository,
repo_config: config::RepoConfig,
) -> git::validation::Result;
/// Moves a branch to a new commit.
fn branch_reset(
&self,
repository: &git::OpenRepository,
branch_name: config::BranchName,
to_commit: git::GitRef,
force: git::push::Force,
) -> git::push::Result;
/// Checks the results of any (e.g. CI) status checks for the commit.
async fn commit_status(&self, commit: &git::Commit) -> git::commit::Status;
/// Clones a repo to disk.
fn repo_clone(
&self,
gitdir: config::GitDir,
) -> Result<git::OpenRepository, git::repository::Error>;
}

View file

@ -1,7 +1,10 @@
//
pub mod branch;
pub mod commit;
pub mod common;
pub mod fetch;
pub mod file;
mod forge_like;
mod generation;
mod git_ref;
mod git_remote;
@ -9,11 +12,13 @@ pub mod push;
mod repo_details;
pub mod repository;
pub mod validate;
pub mod validation;
#[cfg(test)]
mod tests;
pub use commit::Commit;
pub use forge_like::ForgeLike;
pub use generation::Generation;
pub use git_ref::GitRef;
pub use git_remote::GitRemote;

View file

@ -0,0 +1,25 @@
use crate as git;
use git_next_config::BranchName;
pub type Result = core::result::Result<Positions, Error>;
pub struct Positions {
pub main: git::Commit,
pub next: git::Commit,
pub dev: git::Commit,
pub dev_commit_history: Vec<git::Commit>,
}
#[derive(Debug, derive_more::Display)]
pub enum Error {
Network(Box<kxio::network::NetworkError>),
#[display("Failed to Reset Branch {branch} to {commit}")]
FailedToResetBranch {
branch: BranchName,
commit: git::Commit,
},
BranchReset(BranchName),
BranchHasNoCommits(BranchName),
DevBranchNotBasedOn(BranchName),
}
impl std::error::Error for Error {}

View file

@ -1,6 +1,8 @@
use actix::prelude::*;
use git_next_forge as forge;
use git_next_git::RepoDetails;
use git_next_git as git;
use tracing::{error, info};
use crate::load;
@ -9,7 +11,7 @@ use super::{LoadedConfig, RepoActor};
/// Loads the [RepoConfig] from the `.git-next.toml` file in the repository
#[tracing::instrument(skip_all, fields(branch = %repo_details.branch))]
pub async fn load(repo_details: RepoDetails, addr: Addr<RepoActor>, forge: forge::Forge) {
pub async fn load(repo_details: git::RepoDetails, addr: Addr<RepoActor>, forge: forge::Forge) {
info!("Loading .git-next.toml from repo");
let repo_config = match load::load(&repo_details, &forge).await {
Ok(repo_config) => repo_config,

View file

@ -10,47 +10,43 @@ mod tests;
use std::time::Duration;
use actix::prelude::*;
use git::OpenRepository;
use git_next_config::{server::Webhook, ForgeType, RepoConfig, RepoConfigSource};
use git_next_forge as forge;
use git_next_git as git;
use kxio::network::Network;
use tracing::{debug, info, warn, Instrument};
// use crate::{actors::repo::webhook::WebhookAuth, config::Webhook, gitforge};
use crate::webhook::WebhookAuth;
use self::webhook::WebhookId;
#[derive(Debug, derive_more::Display)]
#[display("{}:{}:{}", generation, details.forge.forge_name(), details.repo_alias)]
pub struct RepoActor {
generation: git::Generation,
message_token: MessageToken,
details: git::RepoDetails,
webhook: Webhook,
webhook_id: Option<WebhookId>, // INFO: if [None] then no webhook is configured
webhook_auth: Option<WebhookAuth>, // INFO: if [None] then no webhook is configured
webhook: git_next_config::server::Webhook,
webhook_id: Option<webhook::WebhookId>, // INFO: if [None] then no webhook is configured
webhook_auth: Option<webhook::WebhookAuth>, // INFO: if [None] then no webhook is configured
last_main_commit: Option<git::Commit>,
last_next_commit: Option<git::Commit>,
last_dev_commit: Option<git::Commit>,
repository: Option<OpenRepository>,
repository: Option<git::OpenRepository>,
net: Network,
forge: forge::Forge,
}
impl RepoActor {
pub fn new(
details: git::RepoDetails,
webhook: Webhook,
webhook: git_next_config::server::Webhook,
generation: git::Generation,
net: Network,
repo: git::Repository,
) -> Self {
let forge = match details.forge.forge_type() {
#[cfg(feature = "forgejo")]
ForgeType::ForgeJo => forge::Forge::new_forgejo(details.clone(), net.clone(), repo),
ForgeType::MockForge => forge::Forge::new_mock(),
git_next_config::ForgeType::ForgeJo => {
forge::Forge::new_forgejo(details.clone(), net.clone(), repo)
}
git_next_config::ForgeType::MockForge => forge::Forge::new_mock(),
};
debug!(?forge, "new");
Self {
@ -133,7 +129,7 @@ impl Handler<LoadConfigFromRepo> for RepoActor {
#[derive(Message)]
#[rtype(result = "()")]
struct LoadedConfig(RepoConfig);
struct LoadedConfig(git_next_config::RepoConfig);
impl Handler<LoadedConfig> for RepoActor {
type Result = ();
#[tracing::instrument(name = "RepoActor::LoadedConfig", skip_all, fields(repo = %self.details, branches = %msg.0))]
@ -191,7 +187,7 @@ impl Handler<ValidateRepo> for RepoActor {
.branches_validate_positions(repository, repo_config)
.await
{
Ok(forge::validation::Positions {
Ok(git::validation::Positions {
main,
next,
dev,
@ -265,7 +261,7 @@ impl Handler<StartMonitoring> for RepoActor {
#[derive(Message)]
#[rtype(result = "()")]
pub struct WebhookRegistered(WebhookId, WebhookAuth);
pub struct WebhookRegistered(webhook::WebhookId, webhook::WebhookAuth);
impl Handler<WebhookRegistered> for RepoActor {
type Result = ();
#[tracing::instrument(name = "RepoActor::WebhookRegistered", skip_all, fields(repo = %self.details, webhook_id = %msg.0))]
@ -296,8 +292,10 @@ impl Handler<AdvanceMainTo> for RepoActor {
async move {
branch::advance_main(msg.0, &repo_config, &forge, &repository).await;
match repo_config.source() {
RepoConfigSource::Repo => addr.do_send(LoadConfigFromRepo),
RepoConfigSource::Server => addr.do_send(ValidateRepo { message_token }),
git_next_config::RepoConfigSource::Repo => addr.do_send(LoadConfigFromRepo),
git_next_config::RepoConfigSource::Server => {
addr.do_send(ValidateRepo { message_token })
}
}
}
.in_current_span()

View file

@ -1,27 +1,34 @@
use git_next_config::{self as config, BranchName, RepoConfig};
use git_next_config as config;
use git_next_forge as forge;
use git_next_git::RepoDetails;
use git_next_git as git;
use tracing::error;
pub async fn load(details: &RepoDetails, forge: &forge::Forge) -> Result<RepoConfig, Error> {
pub async fn load(
details: &git::RepoDetails,
forge: &forge::Forge,
) -> Result<config::RepoConfig, Error> {
let contents = forge
.file_contents_get(&details.branch, ".git-next.toml")
.await?;
let config = RepoConfig::load(&contents)?;
let config = config::RepoConfig::load(&contents)?;
let config = validate(config, forge).await?;
Ok(config)
}
#[derive(Debug, derive_more::From, derive_more::Display)]
pub enum Error {
File(forge::file::Error),
File(git::file::Error),
Config(config::server::Error),
Toml(toml::de::Error),
Forge(forge::branch::Error),
BranchNotFound(BranchName),
Forge(git::branch::Error),
BranchNotFound(config::BranchName),
}
pub async fn validate(config: RepoConfig, forge: &forge::Forge) -> Result<RepoConfig, Error> {
pub async fn validate(
config: config::RepoConfig,
forge: &forge::Forge,
) -> Result<config::RepoConfig, Error> {
let branches = forge.branches_get_all().await.map_err(|e| {
error!(?e, "Failed to list branches");
Error::Forge(e)