[F] Fix default branch
This commit is contained in:
+92
-2
@@ -172,6 +172,19 @@ impl<'a> ProviderClient<'a> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_default_branch(
|
||||||
|
&self,
|
||||||
|
endpoint: &EndpointConfig,
|
||||||
|
repo_name: &str,
|
||||||
|
branch: &str,
|
||||||
|
) -> Result<()> {
|
||||||
|
dispatch_provider!(self.site.provider,
|
||||||
|
github => self.github_set_default_branch(endpoint, repo_name, branch),
|
||||||
|
gitlab => self.gitlab_set_default_branch(endpoint, repo_name, branch),
|
||||||
|
gitea_like => self.gitea_set_default_branch(endpoint, repo_name, branch),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn install_webhook(
|
pub fn install_webhook(
|
||||||
&self,
|
&self,
|
||||||
endpoint: &EndpointConfig,
|
endpoint: &EndpointConfig,
|
||||||
@@ -317,6 +330,17 @@ impl<'a> ProviderClient<'a> {
|
|||||||
self.delete(&url).map(|_| ())
|
self.delete(&url).map(|_| ())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn github_set_default_branch(
|
||||||
|
&self,
|
||||||
|
endpoint: &EndpointConfig,
|
||||||
|
repo_name: &str,
|
||||||
|
branch: &str,
|
||||||
|
) -> Result<()> {
|
||||||
|
let url = self.repo_url(endpoint, repo_name, "GitHub")?;
|
||||||
|
self.patch_json::<serde_json::Value>(&url, &json!({ "default_branch": branch }))
|
||||||
|
.map(|_| ())
|
||||||
|
}
|
||||||
|
|
||||||
fn github_install_webhook(
|
fn github_install_webhook(
|
||||||
&self,
|
&self,
|
||||||
endpoint: &EndpointConfig,
|
endpoint: &EndpointConfig,
|
||||||
@@ -441,7 +465,11 @@ impl<'a> ProviderClient<'a> {
|
|||||||
projects.push(project);
|
projects.push(project);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(projects.into_iter().map(Into::into).collect())
|
Ok(projects
|
||||||
|
.into_iter()
|
||||||
|
.filter(|project| !project.is_deletion_scheduled())
|
||||||
|
.map(Into::into)
|
||||||
|
.collect())
|
||||||
}
|
}
|
||||||
NamespaceKind::Org | NamespaceKind::Group => {
|
NamespaceKind::Org | NamespaceKind::Group => {
|
||||||
let encoded = urlencoding(&endpoint.namespace);
|
let encoded = urlencoding(&endpoint.namespace);
|
||||||
@@ -450,7 +478,12 @@ impl<'a> ProviderClient<'a> {
|
|||||||
self.site.api_base(),
|
self.site.api_base(),
|
||||||
encoded
|
encoded
|
||||||
);
|
);
|
||||||
self.paged_remote_repos::<GitlabProject>(&url)
|
Ok(self
|
||||||
|
.paged_get::<GitlabProject>(&url)?
|
||||||
|
.into_iter()
|
||||||
|
.filter(|project| !project.is_deletion_scheduled())
|
||||||
|
.map(Into::into)
|
||||||
|
.collect())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -502,6 +535,17 @@ impl<'a> ProviderClient<'a> {
|
|||||||
self.delete(&url).map(|_| ())
|
self.delete(&url).map(|_| ())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn gitlab_set_default_branch(
|
||||||
|
&self,
|
||||||
|
endpoint: &EndpointConfig,
|
||||||
|
repo_name: &str,
|
||||||
|
branch: &str,
|
||||||
|
) -> Result<()> {
|
||||||
|
let url = self.gitlab_project_url(endpoint, repo_name);
|
||||||
|
self.put_json::<serde_json::Value>(&url, &json!({ "default_branch": branch }))
|
||||||
|
.map(|_| ())
|
||||||
|
}
|
||||||
|
|
||||||
fn gitlab_group(&self, namespace: &str) -> Result<GitlabGroup> {
|
fn gitlab_group(&self, namespace: &str) -> Result<GitlabGroup> {
|
||||||
let url = format!("{}/groups/{}", self.site.api_base(), urlencoding(namespace));
|
let url = format!("{}/groups/{}", self.site.api_base(), urlencoding(namespace));
|
||||||
self.get_json(&url)
|
self.get_json(&url)
|
||||||
@@ -695,6 +739,17 @@ impl<'a> ProviderClient<'a> {
|
|||||||
self.delete(&url).map(|_| ())
|
self.delete(&url).map(|_| ())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn gitea_set_default_branch(
|
||||||
|
&self,
|
||||||
|
endpoint: &EndpointConfig,
|
||||||
|
repo_name: &str,
|
||||||
|
branch: &str,
|
||||||
|
) -> Result<()> {
|
||||||
|
let url = self.repo_url(endpoint, repo_name, "Gitea/Forgejo")?;
|
||||||
|
self.patch_json::<serde_json::Value>(&url, &json!({ "default_branch": branch }))
|
||||||
|
.map(|_| ())
|
||||||
|
}
|
||||||
|
|
||||||
fn gitea_install_webhook(
|
fn gitea_install_webhook(
|
||||||
&self,
|
&self,
|
||||||
endpoint: &EndpointConfig,
|
endpoint: &EndpointConfig,
|
||||||
@@ -1163,6 +1218,10 @@ struct GitlabProject {
|
|||||||
http_url_to_repo: String,
|
http_url_to_repo: String,
|
||||||
visibility: String,
|
visibility: String,
|
||||||
description: Option<String>,
|
description: Option<String>,
|
||||||
|
marked_for_deletion_at: Option<String>,
|
||||||
|
marked_for_deletion_on: Option<String>,
|
||||||
|
#[serde(default)]
|
||||||
|
pending_delete: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GitlabProject {
|
impl GitlabProject {
|
||||||
@@ -1190,6 +1249,37 @@ impl GitlabProject {
|
|||||||
.eq_ignore_ascii_case(other.project_path()),
|
.eq_ignore_ascii_case(other.project_path()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_deletion_scheduled(&self) -> bool {
|
||||||
|
self.pending_delete
|
||||||
|
|| self
|
||||||
|
.marked_for_deletion_at
|
||||||
|
.as_deref()
|
||||||
|
.is_some_and(|value| !value.is_empty())
|
||||||
|
|| self
|
||||||
|
.marked_for_deletion_on
|
||||||
|
.as_deref()
|
||||||
|
.is_some_and(|value| !value.is_empty())
|
||||||
|
|| is_gitlab_deletion_scheduled_path(&self.name)
|
||||||
|
|| self
|
||||||
|
.path
|
||||||
|
.as_deref()
|
||||||
|
.is_some_and(is_gitlab_deletion_scheduled_path)
|
||||||
|
|| self
|
||||||
|
.path_with_namespace
|
||||||
|
.as_deref()
|
||||||
|
.and_then(|path| path.rsplit('/').next())
|
||||||
|
.is_some_and(is_gitlab_deletion_scheduled_path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_gitlab_deletion_scheduled_path(path: &str) -> bool {
|
||||||
|
let Some((name, project_id)) = path.rsplit_once("-deletion_scheduled-") else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
!name.is_empty()
|
||||||
|
&& !project_id.is_empty()
|
||||||
|
&& project_id.bytes().all(|byte| byte.is_ascii_digit())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
|
|||||||
+45
@@ -38,6 +38,7 @@ use self::state::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
const CONFLICT_BRANCH_ROOT: &str = "refray/conflicts/";
|
const CONFLICT_BRANCH_ROOT: &str = "refray/conflicts/";
|
||||||
|
const DEFAULT_BRANCH: &str = "main";
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct SyncOptions {
|
pub struct SyncOptions {
|
||||||
@@ -842,6 +843,7 @@ fn sync_repo(
|
|||||||
let Some(refs) = check_remote_refs(context, repo_name, &remotes)? else {
|
let Some(refs) = check_remote_refs(context, repo_name, &remotes)? else {
|
||||||
return Ok(RepoSyncOutcome::default());
|
return Ok(RepoSyncOutcome::default());
|
||||||
};
|
};
|
||||||
|
set_default_branch_for_created_repos(context, repo_name, &created_repos, &refs)?;
|
||||||
refs
|
refs
|
||||||
} else {
|
} else {
|
||||||
initial_ref_state
|
initial_ref_state
|
||||||
@@ -857,6 +859,48 @@ fn sync_repo(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_default_branch_for_created_repos(
|
||||||
|
context: &RepoSyncContext<'_>,
|
||||||
|
repo_name: &str,
|
||||||
|
created_repos: &[EndpointRepo],
|
||||||
|
refs: &BTreeMap<String, RemoteRefState>,
|
||||||
|
) -> Result<()> {
|
||||||
|
if created_repos.is_empty() {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let targets = created_repos
|
||||||
|
.iter()
|
||||||
|
.filter(|repo| {
|
||||||
|
refs.get(&remote_name_for_endpoint_repo(repo))
|
||||||
|
.is_some_and(|refs| refs.branches.contains_key(DEFAULT_BRANCH))
|
||||||
|
})
|
||||||
|
.cloned()
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
crate::parallel::map(targets, context.jobs, |repo| {
|
||||||
|
crate::logln!(
|
||||||
|
" {} branch {} {}",
|
||||||
|
style("default").green().bold(),
|
||||||
|
style(DEFAULT_BRANCH).cyan(),
|
||||||
|
style(format!("on {}", repo.endpoint.label())).dim()
|
||||||
|
);
|
||||||
|
let site = context.config.site(&repo.endpoint.site).unwrap();
|
||||||
|
ProviderClient::new(site)?
|
||||||
|
.set_default_branch(&repo.endpoint, repo_name, DEFAULT_BRANCH)
|
||||||
|
.with_context(|| {
|
||||||
|
format!(
|
||||||
|
"failed to set default branch for {} on {}",
|
||||||
|
repo_name,
|
||||||
|
repo.endpoint.label()
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
Ok(())
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn sync_assumed_repo(
|
fn sync_assumed_repo(
|
||||||
context: &RepoSyncContext<'_>,
|
context: &RepoSyncContext<'_>,
|
||||||
repo_name: &str,
|
repo_name: &str,
|
||||||
@@ -972,6 +1016,7 @@ fn sync_assumed_repo(
|
|||||||
..RepoSyncOutcome::default()
|
..RepoSyncOutcome::default()
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
set_default_branch_for_created_repos(context, repo_name, &created_repos, &refs)?;
|
||||||
refs
|
refs
|
||||||
} else {
|
} else {
|
||||||
initial_ref_check.refs
|
initial_ref_check.refs
|
||||||
|
|||||||
+48
-3
@@ -380,9 +380,10 @@ namespace = "{}"
|
|||||||
git(&work, ["tag", "v1.0.0"])?;
|
git(&work, ["tag", "v1.0.0"])?;
|
||||||
let remote_url = source.authenticated_repo_url(&repo)?;
|
let remote_url = source.authenticated_repo_url(&repo)?;
|
||||||
self.git(&work, ["remote", "add", "origin", &remote_url])?;
|
self.git(&work, ["remote", "add", "origin", &remote_url])?;
|
||||||
self.git(
|
self.git_retry(
|
||||||
&work,
|
&work,
|
||||||
["push", "origin", "HEAD:main", "feature/github", "v1.0.0"],
|
["push", "origin", "HEAD:main", "feature/github", "v1.0.0"],
|
||||||
|
"initial seed push",
|
||||||
)?;
|
)?;
|
||||||
source.wait_branch(
|
source.wait_branch(
|
||||||
&repo,
|
&repo,
|
||||||
@@ -393,6 +394,7 @@ namespace = "{}"
|
|||||||
source.wait_repo_listed(&repo)?;
|
source.wait_repo_listed(&repo)?;
|
||||||
self.sync_repo(&repo, [])?;
|
self.sync_repo(&repo, [])?;
|
||||||
self.assert_branch_all_equal_after_optional_resync(&repo, MAIN_BRANCH)?;
|
self.assert_branch_all_equal_after_optional_resync(&repo, MAIN_BRANCH)?;
|
||||||
|
self.assert_default_branch_all_except(&repo, MAIN_BRANCH, &source.site_name)?;
|
||||||
self.assert_branch_all_equal(&repo, "feature/github")?;
|
self.assert_branch_all_equal(&repo, "feature/github")?;
|
||||||
self.assert_tag_all_equal(&repo, "v1.0.0")?;
|
self.assert_tag_all_equal(&repo, "v1.0.0")?;
|
||||||
|
|
||||||
@@ -699,7 +701,7 @@ namespace = "{}"
|
|||||||
)?;
|
)?;
|
||||||
let remote_url = provider.authenticated_repo_url(repo)?;
|
let remote_url = provider.authenticated_repo_url(repo)?;
|
||||||
self.git(&work, ["remote", "add", "origin", &remote_url])?;
|
self.git(&work, ["remote", "add", "origin", &remote_url])?;
|
||||||
self.git(&work, ["push", "origin", "HEAD:main"])?;
|
self.git_retry(&work, ["push", "origin", "HEAD:main"], "seed push")?;
|
||||||
provider.wait_branch(
|
provider.wait_branch(
|
||||||
repo,
|
repo,
|
||||||
MAIN_BRANCH,
|
MAIN_BRANCH,
|
||||||
@@ -726,7 +728,11 @@ namespace = "{}"
|
|||||||
for provider in &self.settings.providers {
|
for provider in &self.settings.providers {
|
||||||
let remote_url = provider.authenticated_repo_url(repo)?;
|
let remote_url = provider.authenticated_repo_url(repo)?;
|
||||||
self.git(&work, ["remote", "add", &provider.site_name, &remote_url])?;
|
self.git(&work, ["remote", "add", &provider.site_name, &remote_url])?;
|
||||||
self.git(&work, ["push", &provider.site_name, "HEAD:main"])?;
|
self.git_retry(
|
||||||
|
&work,
|
||||||
|
["push", &provider.site_name, "HEAD:main"],
|
||||||
|
"seed-all push",
|
||||||
|
)?;
|
||||||
provider.wait_branch(repo, MAIN_BRANCH, &sha)?;
|
provider.wait_branch(repo, MAIN_BRANCH, &sha)?;
|
||||||
provider.wait_repo_listed(repo)?;
|
provider.wait_repo_listed(repo)?;
|
||||||
provider.unprotect_branch(repo, MAIN_BRANCH)?;
|
provider.unprotect_branch(repo, MAIN_BRANCH)?;
|
||||||
@@ -787,6 +793,10 @@ namespace = "{}"
|
|||||||
assert_output_success(output, "git", &self.redactor)
|
assert_output_success(output, "git", &self.redactor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn git_retry<const N: usize>(&self, path: &Path, args: [&str; N], label: &str) -> Result<()> {
|
||||||
|
retry(label, || self.git(path, args))
|
||||||
|
}
|
||||||
|
|
||||||
fn set_repo_whitelist(&self, pattern: &str) -> Result<()> {
|
fn set_repo_whitelist(&self, pattern: &str) -> Result<()> {
|
||||||
let contents = fs::read_to_string(&self.config_path)
|
let contents = fs::read_to_string(&self.config_path)
|
||||||
.with_context(|| format!("failed to read {}", self.config_path.display()))?;
|
.with_context(|| format!("failed to read {}", self.config_path.display()))?;
|
||||||
@@ -1064,6 +1074,30 @@ namespace = "{}"
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn assert_default_branch_all_except(
|
||||||
|
&self,
|
||||||
|
repo: &str,
|
||||||
|
branch: &str,
|
||||||
|
excluded_site: &str,
|
||||||
|
) -> Result<()> {
|
||||||
|
retry("default branch metadata", || {
|
||||||
|
for provider in &self.settings.providers {
|
||||||
|
if provider.site_name == excluded_site {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let actual = provider.default_branch(repo)?;
|
||||||
|
if actual.as_deref() != Some(branch) {
|
||||||
|
bail!(
|
||||||
|
"expected default branch {branch} on {} for {repo}, got {:?}",
|
||||||
|
provider.site_name,
|
||||||
|
actual
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn assert_tag_all_equal(&self, repo: &str, tag: &str) -> Result<()> {
|
fn assert_tag_all_equal(&self, repo: &str, tag: &str) -> Result<()> {
|
||||||
retry("tag convergence", || {
|
retry("tag convergence", || {
|
||||||
let refs = self.refs_by_provider(repo)?;
|
let refs = self.refs_by_provider(repo)?;
|
||||||
@@ -1387,6 +1421,17 @@ impl ProviderAccount {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn default_branch(&self, repo: &str) -> Result<Option<String>> {
|
||||||
|
let value = self
|
||||||
|
.get_json::<Value>(&self.repo_api_url(repo))
|
||||||
|
.with_context(|| format!("failed to inspect {} default branch", self.site_name))?;
|
||||||
|
Ok(value
|
||||||
|
.get("default_branch")
|
||||||
|
.and_then(Value::as_str)
|
||||||
|
.filter(|branch| !branch.is_empty())
|
||||||
|
.map(ToOwned::to_owned))
|
||||||
|
}
|
||||||
|
|
||||||
fn wait_repo_present(&self, repo: &str) -> Result<()> {
|
fn wait_repo_present(&self, repo: &str) -> Result<()> {
|
||||||
retry("repo present", || {
|
retry("repo present", || {
|
||||||
if self.repo_exists(repo)? {
|
if self.repo_exists(repo)? {
|
||||||
|
|||||||
@@ -225,6 +225,42 @@ fn list_gitlab_user_repos_merges_authenticated_owned_projects() {
|
|||||||
handle.join().unwrap();
|
handle.join().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn list_gitlab_group_repos_ignores_deletion_scheduled_projects() {
|
||||||
|
let projects = r#"[
|
||||||
|
{"name":"active","path":"active","path_with_namespace":"maigolabs/active","http_url_to_repo":"https://gitlab.example.test/maigolabs/active.git","visibility":"private","description":null,"namespace":{"path":"maigolabs","full_path":"maigolabs"}},
|
||||||
|
{"name":"Kairos-deletion_scheduled-82068172","path":"Kairos-deletion_scheduled-82068172","path_with_namespace":"maigolabs/Kairos-deletion_scheduled-82068172","http_url_to_repo":"https://gitlab.example.test/maigolabs/Kairos-deletion_scheduled-82068172.git","visibility":"private","description":null,"namespace":{"path":"maigolabs","full_path":"maigolabs"}},
|
||||||
|
{"name":"marked-at","path":"marked-at","path_with_namespace":"maigolabs/marked-at","http_url_to_repo":"https://gitlab.example.test/maigolabs/marked-at.git","visibility":"private","description":null,"namespace":{"path":"maigolabs","full_path":"maigolabs"},"marked_for_deletion_at":"2026-05-17"},
|
||||||
|
{"name":"marked-on","path":"marked-on","path_with_namespace":"maigolabs/marked-on","http_url_to_repo":"https://gitlab.example.test/maigolabs/marked-on.git","visibility":"private","description":null,"namespace":{"path":"maigolabs","full_path":"maigolabs"},"marked_for_deletion_on":"2026-05-17"},
|
||||||
|
{"name":"pending","path":"pending","path_with_namespace":"maigolabs/pending","http_url_to_repo":"https://gitlab.example.test/maigolabs/pending.git","visibility":"private","description":null,"namespace":{"path":"maigolabs","full_path":"maigolabs"},"pending_delete":true}
|
||||||
|
]"#;
|
||||||
|
let (api_url, handle) = one_request_server("200 OK", projects, |request| {
|
||||||
|
assert!(
|
||||||
|
request.starts_with(
|
||||||
|
"GET /groups/maigolabs/projects?simple=true&include_subgroups=false&per_page=100 "
|
||||||
|
),
|
||||||
|
"request was {request}"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
let site = SiteConfig {
|
||||||
|
api_url: Some(api_url),
|
||||||
|
..site(ProviderKind::Gitlab, None)
|
||||||
|
};
|
||||||
|
|
||||||
|
let repos = ProviderClient::new(&site)
|
||||||
|
.unwrap()
|
||||||
|
.list_repos(&EndpointConfig {
|
||||||
|
site: "gitlab".to_string(),
|
||||||
|
kind: NamespaceKind::Group,
|
||||||
|
namespace: "maigolabs".to_string(),
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(repos.len(), 1);
|
||||||
|
assert_eq!(repos[0].name, "active");
|
||||||
|
handle.join().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn create_gitlab_repo_returns_existing_repo_when_path_is_taken() {
|
fn create_gitlab_repo_returns_existing_repo_when_path_is_taken() {
|
||||||
let existing = r#"{"name":"repo","path":"repo","path_with_namespace":"alice/repo","http_url_to_repo":"https://gitlab.example.test/alice/repo.git","visibility":"public","description":"existing","namespace":{"path":"alice","full_path":"alice"}}"#;
|
let existing = r#"{"name":"repo","path":"repo","path_with_namespace":"alice/repo","http_url_to_repo":"https://gitlab.example.test/alice/repo.git","visibility":"public","description":"existing","namespace":{"path":"alice","full_path":"alice"}}"#;
|
||||||
@@ -282,6 +318,82 @@ fn create_gitlab_repo_returns_existing_repo_when_path_is_taken() {
|
|||||||
handle.join().unwrap();
|
handle.join().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn set_github_default_branch_patches_repo() {
|
||||||
|
let (api_url, handle) = one_request_server("200 OK", "{}", |request| {
|
||||||
|
assert!(
|
||||||
|
request.starts_with("PATCH /repos/alice/repo "),
|
||||||
|
"request was {request}"
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
request.contains(r#""default_branch":"main""#),
|
||||||
|
"request was {request}"
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
request
|
||||||
|
.to_ascii_lowercase()
|
||||||
|
.contains("authorization: bearer secret"),
|
||||||
|
"request was {request}"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
let site = SiteConfig {
|
||||||
|
api_url: Some(api_url),
|
||||||
|
..site(ProviderKind::Github, None)
|
||||||
|
};
|
||||||
|
|
||||||
|
ProviderClient::new(&site)
|
||||||
|
.unwrap()
|
||||||
|
.set_default_branch(
|
||||||
|
&EndpointConfig {
|
||||||
|
site: "github".to_string(),
|
||||||
|
kind: NamespaceKind::User,
|
||||||
|
namespace: "alice".to_string(),
|
||||||
|
},
|
||||||
|
"repo",
|
||||||
|
"main",
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
handle.join().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn set_gitlab_default_branch_updates_project() {
|
||||||
|
let (api_url, handle) = one_request_server("200 OK", "{}", |request| {
|
||||||
|
assert!(
|
||||||
|
request.starts_with("PUT /projects/alice%2Frepo "),
|
||||||
|
"request was {request}"
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
request.contains(r#""default_branch":"main""#),
|
||||||
|
"request was {request}"
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
request
|
||||||
|
.to_ascii_lowercase()
|
||||||
|
.contains("private-token: secret"),
|
||||||
|
"request was {request}"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
let site = SiteConfig {
|
||||||
|
api_url: Some(api_url),
|
||||||
|
..site(ProviderKind::Gitlab, None)
|
||||||
|
};
|
||||||
|
|
||||||
|
ProviderClient::new(&site)
|
||||||
|
.unwrap()
|
||||||
|
.set_default_branch(
|
||||||
|
&EndpointConfig {
|
||||||
|
site: "gitlab".to_string(),
|
||||||
|
kind: NamespaceKind::User,
|
||||||
|
namespace: "alice".to_string(),
|
||||||
|
},
|
||||||
|
"repo",
|
||||||
|
"main",
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
handle.join().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn install_webhook_posts_github_hook_when_missing() {
|
fn install_webhook_posts_github_hook_when_missing() {
|
||||||
let (api_url, handle) = request_server(
|
let (api_url, handle) = request_server(
|
||||||
@@ -710,6 +822,44 @@ fn create_gitea_repo_returns_existing_repo_on_conflict() {
|
|||||||
handle.join().unwrap();
|
handle.join().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn set_gitea_default_branch_patches_repo() {
|
||||||
|
let (api_url, handle) = one_request_server("200 OK", "{}", |request| {
|
||||||
|
assert!(
|
||||||
|
request.starts_with("PATCH /repos/alice/repo "),
|
||||||
|
"request was {request}"
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
request.contains(r#""default_branch":"main""#),
|
||||||
|
"request was {request}"
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
request
|
||||||
|
.to_ascii_lowercase()
|
||||||
|
.contains("authorization: token secret"),
|
||||||
|
"request was {request}"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
let site = SiteConfig {
|
||||||
|
api_url: Some(api_url),
|
||||||
|
..site(ProviderKind::Gitea, None)
|
||||||
|
};
|
||||||
|
|
||||||
|
ProviderClient::new(&site)
|
||||||
|
.unwrap()
|
||||||
|
.set_default_branch(
|
||||||
|
&EndpointConfig {
|
||||||
|
site: "gitea".to_string(),
|
||||||
|
kind: NamespaceKind::User,
|
||||||
|
namespace: "alice".to_string(),
|
||||||
|
},
|
||||||
|
"repo",
|
||||||
|
"main",
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
handle.join().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn open_pull_request_posts_github_pull_when_missing() {
|
fn open_pull_request_posts_github_pull_when_missing() {
|
||||||
let (api_url, handle) = request_server(
|
let (api_url, handle) = request_server(
|
||||||
|
|||||||
Reference in New Issue
Block a user