Skip to content
Snippets Groups Projects
Verified Commit f21e7cf8 authored by Rafael Epplée's avatar Rafael Epplée
Browse files

Automatically set package source ci template

parent 6ffbbff7
Branches buildbot
No related tags found
No related merge requests found
Pipeline #123002 passed
......@@ -7,5 +7,7 @@ GITLAB_TOKEN=
GITLAB_DOMAIN=gitlab.archlinux.org
GITLAB_PACKAGES_GROUP=packaging-buildbtw-dev/packages
RUN_BUILDS_ON_GITLAB=false
# Specifying this will result in changes to the settings of all packages in the group defined by `GITLAB_PACKAGES_GROUP`.
# GITLAB_PACKAGES_CI_CONFIG=.gitlab-ci.yml@packaging-buildbtw-dev/gitlab-ci-templates
DATABASE_URL="sqlite:buildbtw_server.sqlite"
\ No newline at end of file
......@@ -50,8 +50,13 @@ pub struct Gitlab {
/// Requires gitlab token to be specified.
// TODO: make this an enum BuildDispatch {Gitlab, Local} and move it
// out of the `Gitlab` struct
#[arg(long, env, required = false)]
#[arg(long, env, required = false, default_value = "false")]
pub run_builds_on_gitlab: bool,
/// Update package source CI settings to point to the specified CI configuration file.
/// Specifying this will result in changes to the settings of all packages in the group defined by `gitlab_packages_group`.
/// See https://gitlab.archlinux.org/help/ci/pipelines/settings.md#specify-a-custom-cicd-configuration-file
#[arg(long, env, required = false)]
pub gitlab_packages_ci_config: Option<String>,
}
#[derive(Debug, Clone, Subcommand)]
......
......@@ -4,7 +4,7 @@ use ::gitlab::{AsyncGitlab, GitlabBuilder};
use anyhow::{Context, Result};
use buildbtw::{
build_set_graph::{self, schedule_next_build_in_graph},
gitlab::fetch_all_source_repo_changes,
gitlab::{fetch_all_source_repo_changes, set_all_projects_ci_config},
iteration::{new_build_set_iteration_is_needed, NewBuildIterationResult},
BuildNamespaceStatus, PackageBuildStatus,
};
......@@ -40,6 +40,8 @@ pub async fn start(
if let Some(args) = &gitlab_args {
fetch_source_repo_changes_in_loop(pool.clone(), args.clone()).await?;
update_project_ci_settings_in_loop(args.clone()).await?;
}
update_and_build_all_namespaces_in_loop(pool.clone(), gitlab_args).await?;
......@@ -138,6 +140,32 @@ pub async fn fetch_source_repo_changes_in_loop(
Ok(())
}
pub async fn update_project_ci_settings_in_loop(gitlab_args: args::Gitlab) -> Result<()> {
let client = new_gitlab_client(&gitlab_args.clone()).await?;
let Some(ci_config_path) = gitlab_args.gitlab_packages_ci_config else {
return Ok(());
};
tokio::spawn(async move {
loop {
match set_all_projects_ci_config(
&client,
&gitlab_args.gitlab_packages_group,
ci_config_path.clone(),
)
.await
{
Ok(_) => {}
Err(e) => tracing::info!("{e:?}"),
}
tokio::time::sleep(tokio::time::Duration::from_secs(60 * 10)).await;
}
});
Ok(())
}
async fn create_new_namespace_iteration_if_needed(
pool: &SqlitePool,
namespace: &BuildNamespace,
......
use anyhow::{anyhow, Context, Result};
use gitlab::{api::AsyncQuery, AsyncGitlab};
use gitlab::{
api::{groups::projects::GroupProjectsOrderBy, AsyncQuery},
AsyncGitlab,
};
use graphql_client::GraphQLQuery;
use regex::Regex;
use serde::{Deserialize, Serialize};
......@@ -196,6 +199,71 @@ pub async fn get_pipeline_status(
Ok(response.status)
}
#[derive(Deserialize, Debug)]
struct ProjectCiConfig {
id: u64,
ci_config_path: String,
}
async fn get_all_projects_ci_configs(
client: &AsyncGitlab,
package_group: &str,
) -> Result<Vec<ProjectCiConfig>> {
let endpoint = gitlab::api::groups::projects::GroupProjects::builder()
.group(package_group)
.order_by(GroupProjectsOrderBy::Path)
.build()
.unwrap();
let projects: Vec<ProjectCiConfig> = gitlab::api::paged(endpoint, gitlab::api::Pagination::All)
.query_async(client)
.await?;
Ok(projects)
}
pub async fn set_all_projects_ci_config(
client: &AsyncGitlab,
package_group: &str,
ci_config_path: String,
) -> Result<()> {
tracing::info!("Fetching CI config path for all projects in the {package_group} group...");
let projects = get_all_projects_ci_configs(client, package_group).await?;
tracing::info!(
"Updating CI config path for {} projects where necessary...",
projects.len()
);
let mut results: Vec<Result<()>> = Vec::new();
for project in projects {
if project.ci_config_path == ci_config_path {
continue;
}
results.push(set_project_ci_config(client, project.id, &ci_config_path).await);
}
tracing::info!("Changed CI config path for {} projects", results.len());
results.into_iter().collect()
}
pub async fn set_project_ci_config(
client: &AsyncGitlab,
project_path: u64,
ci_config_path: &str,
) -> Result<()> {
let endpoint = gitlab::api::projects::EditProject::builder()
.project(project_path)
.ci_config_path(ci_config_path)
.build()?;
gitlab::api::ignore(endpoint)
.query_async(client)
.await
.context("Error updating gitlab project config")?;
Ok(())
}
/// Convert arbitrary project names to GitLab valid path names.
///
/// GitLab has several limitations on project and group names and also maintains
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment