WIP: Adding support for git subtree
This commit is contained in:
		@@ -4,21 +4,22 @@
 | 
			
		||||
name: zot
 | 
			
		||||
repository: zot-git
 | 
			
		||||
extensions:
 | 
			
		||||
  - name: Add VPA
 | 
			
		||||
    source_dir: ../extensions/vpa
 | 
			
		||||
    target_dir: templates/gs-vpa
 | 
			
		||||
  - name: Add values for CI
 | 
			
		||||
    source_dir: ../extensions/ci-values
 | 
			
		||||
    target_dir: ci
 | 
			
		||||
  #- name: Add VPA
 | 
			
		||||
  #  source_dir: ../extensions/vpa
 | 
			
		||||
  #  target_dir: templates/gs-vpa
 | 
			
		||||
  #- name: Add values for CI
 | 
			
		||||
  #  source_dir: ../extensions/ci-values
 | 
			
		||||
  #  target_dir: ci
 | 
			
		||||
variables:
 | 
			
		||||
  target_repo: zot-app
 | 
			
		||||
patches:
 | 
			
		||||
  - name: team annotation
 | 
			
		||||
  - name: set home
 | 
			
		||||
  - name: set engine
 | 
			
		||||
  - name: yamlfmt
 | 
			
		||||
  #- name: team annotation
 | 
			
		||||
  #- name: set home
 | 
			
		||||
  #- name: set engine
 | 
			
		||||
  #- name: yamlfmt
 | 
			
		||||
  - name: Git patch
 | 
			
		||||
    git:
 | 
			
		||||
      path: ../patches/git/zot.patch
 | 
			
		||||
      ref: d43aaea7bc0e21edb5cc391d4eb47866a5a94aba
 | 
			
		||||
mirrors:
 | 
			
		||||
  - apps-git
 | 
			
		||||
 
 | 
			
		||||
@@ -8,6 +8,7 @@ include:
 | 
			
		||||
    path: ./charts/gitops-server.yaml
 | 
			
		||||
  - kind: Charts
 | 
			
		||||
    path: ./charts/external-secrets-operator.yaml
 | 
			
		||||
 | 
			
		||||
patches:
 | 
			
		||||
  - name: yamlfmt
 | 
			
		||||
    custom_command:
 | 
			
		||||
@@ -40,6 +41,7 @@ repositories:
 | 
			
		||||
      url: https://github.com/project-zot/helm-charts.git
 | 
			
		||||
      git_ref: zot-0.1.42
 | 
			
		||||
      path: charts
 | 
			
		||||
      subtree: true
 | 
			
		||||
  - name: weave
 | 
			
		||||
    helm:
 | 
			
		||||
      url: https://helm.gitops.weave.works
 | 
			
		||||
@@ -50,7 +52,7 @@ mirrors:
 | 
			
		||||
  - name: apps-git
 | 
			
		||||
    git:
 | 
			
		||||
      url: git@git.badhouseplants.net:allanger/{{ variables.target_repo }}.git
 | 
			
		||||
      git_dir: app-{{ name }}-git
 | 
			
		||||
      git_dir: app-{{ name }}
 | 
			
		||||
      branch: upgrade-{{ name }}-to-{{ version }}
 | 
			
		||||
      path: helm/{{ name }}
 | 
			
		||||
      commit: |-
 | 
			
		||||
 
 | 
			
		||||
@@ -109,13 +109,10 @@ index ac7f0f0..9730e9c 100644
 | 
			
		||||
 replicaCount: 1
 | 
			
		||||
 image:
 | 
			
		||||
-  repository: ghcr.io/project-zot/zot-linux-amd64
 | 
			
		||||
-  pullPolicy: IfNotPresent
 | 
			
		||||
-  # Overrides the image tag whose default is the chart appVersion.
 | 
			
		||||
-  tag: "v2.0.0"
 | 
			
		||||
+  registry: gsoci.azurecr.io
 | 
			
		||||
+  image: dummy/zot-linux
 | 
			
		||||
+  pullPolicy: Always
 | 
			
		||||
+  tag: ""
 | 
			
		||||
+  repository: ghcr.io/project-zot/zot-linux-amd64-bla
 | 
			
		||||
   pullPolicy: IfNotPresent
 | 
			
		||||
   # Overrides the image tag whose default is the chart appVersion.
 | 
			
		||||
   tag: "v2.0.0"
 | 
			
		||||
 serviceAccount:
 | 
			
		||||
   # Specifies whether a service account should be created
 | 
			
		||||
   create: true
 | 
			
		||||
 
 | 
			
		||||
@@ -47,7 +47,7 @@ struct Args {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn exec(args: Args) -> Result<(), Box<dyn Error>> {
 | 
			
		||||
    let prerequisites = vec![args.helm_bin, args.git_bin, args.yq_bin];
 | 
			
		||||
    let prerequisites = vec![args.helm_bin, args.git_bin.clone(), args.yq_bin];
 | 
			
		||||
    check_prerequisites(prerequisites)?;
 | 
			
		||||
    let workdir_path = helmzoo_lib::workdir::setup_workdir(args.workdir)?;
 | 
			
		||||
    let mut config: Config = read_config(args.config.clone())?;
 | 
			
		||||
@@ -72,7 +72,7 @@ fn exec(args: Args) -> Result<(), Box<dyn Error>> {
 | 
			
		||||
                patches
 | 
			
		||||
                    .into_iter()
 | 
			
		||||
                    .try_for_each(|patch| -> Result<(), Box<dyn Error>> {
 | 
			
		||||
                        patch.apply(chart_path.clone(), config.patches.clone())
 | 
			
		||||
                        patch.apply(chart_path.clone(), config.patches.clone(), workdir_path.clone(), args.git_bin.clone())
 | 
			
		||||
                    })?
 | 
			
		||||
            }
 | 
			
		||||
            config
 | 
			
		||||
 
 | 
			
		||||
@@ -46,6 +46,7 @@ impl Target for GitMirror {
 | 
			
		||||
            Some(dir) => template::render(dir.clone(), &chart_local)?,
 | 
			
		||||
            None => general_purpose::STANDARD_NO_PAD.encode(self.url.clone()),
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        let git_instance = Git {
 | 
			
		||||
            url: template::render(self.url.clone(), &chart_local)?,
 | 
			
		||||
            repo_path: repo_path.clone(),
 | 
			
		||||
 
 | 
			
		||||
@@ -1,12 +1,11 @@
 | 
			
		||||
use std::{
 | 
			
		||||
    fs::{self, read_dir, remove_dir_all, File, OpenOptions},
 | 
			
		||||
    io::Write,
 | 
			
		||||
    path::{Path, PathBuf},
 | 
			
		||||
    path::{Path, PathBuf}, process::exit,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
use helmzoo_lib::{
 | 
			
		||||
    cli::{cli_exec, cli_exec_from_dir},
 | 
			
		||||
    output::message_info,
 | 
			
		||||
    cli::{cli_exec, cli_exec_from_dir}, git::{CheckoutOptions, Git, GitOptions}, output::message_info, workdir
 | 
			
		||||
};
 | 
			
		||||
use serde::{Deserialize, Serialize};
 | 
			
		||||
 | 
			
		||||
@@ -26,6 +25,12 @@ pub(crate) struct RegexpPatch {
 | 
			
		||||
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
 | 
			
		||||
pub(crate) struct GitPatch {
 | 
			
		||||
    path: String,
 | 
			
		||||
    #[serde(alias = "ref")]
 | 
			
		||||
    git_ref: Option<String>,    
 | 
			
		||||
    #[serde(skip)]
 | 
			
		||||
    workdir: String,
 | 
			
		||||
    #[serde(skip)]
 | 
			
		||||
    git_bin: String
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
 | 
			
		||||
@@ -62,18 +67,20 @@ impl Patch {
 | 
			
		||||
        &self,
 | 
			
		||||
        chart_local_path: String,
 | 
			
		||||
        global_patches: Option<Vec<Patch>>,
 | 
			
		||||
        workdir: String,
 | 
			
		||||
        git_bin: String,
 | 
			
		||||
    ) -> Result<(), Box<dyn std::error::Error>> {
 | 
			
		||||
        let patch_action: Box<dyn PatchInterface>;
 | 
			
		||||
        if self.is_ref() {
 | 
			
		||||
            let patch_ref = self.get_ref(global_patches)?;
 | 
			
		||||
            patch_action = Box::from(patch_action_from_definition(patch_ref)?);
 | 
			
		||||
            patch_action = Box::from(patch_action_from_definition(patch_ref, workdir.clone(), git_bin.clone())?);
 | 
			
		||||
        } else {
 | 
			
		||||
            patch_action = Box::from(patch_action_from_definition(self.clone())?);
 | 
			
		||||
            patch_action = Box::from(patch_action_from_definition(self.clone(), workdir.clone(), git_bin.clone())?);
 | 
			
		||||
        }
 | 
			
		||||
        patch_action.apply(chart_local_path)
 | 
			
		||||
    }
 | 
			
		||||
    pub(crate) fn get_path(&self) -> String {
 | 
			
		||||
        match patch_action_from_definition(self.clone()) {
 | 
			
		||||
        match patch_action_from_definition(self.clone(), String::new(), String::new()) {
 | 
			
		||||
            Ok(patch) => patch.get_path(),
 | 
			
		||||
            Err(_) => "".to_string(),
 | 
			
		||||
        }
 | 
			
		||||
@@ -235,12 +242,34 @@ impl PatchInterface for RegexpPatch {
 | 
			
		||||
 | 
			
		||||
impl PatchInterface for GitPatch {
 | 
			
		||||
    fn apply(&self, chart_local_path: String) -> Result<(), Box<dyn std::error::Error>> {
 | 
			
		||||
        if !is_git_repo(chart_local_path.clone()) {
 | 
			
		||||
        let git_instance = Git {
 | 
			
		||||
            url: chart_local_path.clone(),
 | 
			
		||||
            repo_path: chart_local_path.clone(),
 | 
			
		||||
        };
 | 
			
		||||
        let path = format!("{}", chart_local_path);
 | 
			
		||||
        let is_git_repo = is_git_repo(path.clone());
 | 
			
		||||
        if !is_git_repo {
 | 
			
		||||
            init_git_repo(chart_local_path.clone())?;
 | 
			
		||||
        };
 | 
			
		||||
        let cmd = "git rev-parse --abbrev-ref HEAD".to_string();
 | 
			
		||||
        let current_ref = cli_exec_from_dir(cmd, path)?;
 | 
			
		||||
        let git_opts = GitOptions::new(self.git_bin.clone(), None);
 | 
			
		||||
        if let Some(git_ref) = self.git_ref.clone() {
 | 
			
		||||
            let checkout_options = CheckoutOptions {
 | 
			
		||||
                create: false,
 | 
			
		||||
                git_ref: git_ref.clone(),
 | 
			
		||||
            };
 | 
			
		||||
            git_instance.checkout(git_opts, checkout_options)?;
 | 
			
		||||
        }
 | 
			
		||||
        let cmd = format!("git -C {} apply {}", chart_local_path, self.path);
 | 
			
		||||
        cli_exec(cmd)?;
 | 
			
		||||
        remove_dir_all(chart_local_path + "/.git")?;
 | 
			
		||||
 | 
			
		||||
        if let Some(git_ref) = self.git_ref.clone() {
 | 
			
		||||
            exit(1);
 | 
			
		||||
        }
 | 
			
		||||
        if !is_git_repo{
 | 
			
		||||
            remove_dir_all(chart_local_path + "/.git")?;
 | 
			
		||||
        }
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -273,6 +302,8 @@ impl PatchInterface for CustomCommandPatch {
 | 
			
		||||
 | 
			
		||||
fn patch_action_from_definition(
 | 
			
		||||
    patch: Patch,
 | 
			
		||||
    workdir: String,
 | 
			
		||||
    git_bin: String,
 | 
			
		||||
) -> Result<Box<dyn PatchInterface>, Box<dyn std::error::Error>> {
 | 
			
		||||
    if let Some(regexp) = patch.regexp {
 | 
			
		||||
        Ok(Box::new(RegexpPatch { path: regexp.path }))
 | 
			
		||||
@@ -285,6 +316,9 @@ fn patch_action_from_definition(
 | 
			
		||||
                    None => git.path.clone(),
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            git_ref: git.git_ref.clone(),
 | 
			
		||||
            workdir: workdir.clone(),
 | 
			
		||||
            git_bin: git_bin.clone(),
 | 
			
		||||
        }));
 | 
			
		||||
    } else if let Some(custom_command) = patch.custom_command {
 | 
			
		||||
        return Ok(Box::new(CustomCommandPatch {
 | 
			
		||||
@@ -301,7 +335,7 @@ fn patch_action_from_definition(
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn is_git_repo(path: String) -> bool {
 | 
			
		||||
    let dot_git_path = path + ".git";
 | 
			
		||||
    let dot_git_path = path + "/.git";
 | 
			
		||||
    Path::new(dot_git_path.as_str()).exists()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,8 @@
 | 
			
		||||
use std::error::Error;
 | 
			
		||||
use std::{error::Error, fmt::format};
 | 
			
		||||
 | 
			
		||||
use serde::{Deserialize, Serialize};
 | 
			
		||||
 | 
			
		||||
use crate::cli::{cli_exec, cli_exec_from_dir};
 | 
			
		||||
use crate::cli::{cli_exec, cli_exec_from_dir, is_path_relative};
 | 
			
		||||
 | 
			
		||||
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
 | 
			
		||||
pub struct GitOptions {
 | 
			
		||||
@@ -46,6 +46,10 @@ pub struct Git {
 | 
			
		||||
 | 
			
		||||
impl Git {
 | 
			
		||||
    pub fn new(url: String, repo_path: String) -> Self {
 | 
			
		||||
        let repo_path = match is_path_relative(repo_path.clone()) {
 | 
			
		||||
            true => format!("./{}", repo_path),
 | 
			
		||||
            false => todo!(),
 | 
			
		||||
        };
 | 
			
		||||
        Self { url, repo_path }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -90,8 +94,9 @@ impl Git {
 | 
			
		||||
            let _ = self.exec(cmd, git_opts.workdir.clone())?;
 | 
			
		||||
        }
 | 
			
		||||
        let cmd = format!(
 | 
			
		||||
            "{} diff --staged --quiet || {} -C {} commit -m \"{}\"",
 | 
			
		||||
            git_opts.bin, git_opts.bin, self.repo_path, opts.message
 | 
			
		||||
            "{} -C {} diff --staged --quiet || {} -C {} commit -m \"{}\"",
 | 
			
		||||
            git_opts.bin, self.repo_path,
 | 
			
		||||
            git_opts.bin, self.repo_path, opts.message
 | 
			
		||||
        );
 | 
			
		||||
        match self.exec(cmd, git_opts.workdir.clone()) {
 | 
			
		||||
            Ok(_) => Ok(()),
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,7 @@ use crate::git::GitOptions;
 | 
			
		||||
use crate::{cli::cli_exec, helm::repository::Version};
 | 
			
		||||
use std::error::Error;
 | 
			
		||||
use std::fs::{self, rename};
 | 
			
		||||
use std::process::exit;
 | 
			
		||||
 | 
			
		||||
use base64::{engine::general_purpose, Engine};
 | 
			
		||||
use serde::Deserialize;
 | 
			
		||||
@@ -19,6 +20,7 @@ pub struct GitRepo {
 | 
			
		||||
    #[serde(alias = "ref")]
 | 
			
		||||
    pub git_ref: String,
 | 
			
		||||
    pub path: String,
 | 
			
		||||
    pub subtree: bool,
 | 
			
		||||
    #[serde(default = "default_git_bin")]
 | 
			
		||||
    pub(crate) git_bin: String,
 | 
			
		||||
}
 | 
			
		||||
@@ -40,7 +42,7 @@ impl RepositoryImpl for GitRepo {
 | 
			
		||||
            git_ref: self.git_ref.clone(),
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        git_instance.checkout(git_opts, checkout_opts)?;
 | 
			
		||||
        git_instance.checkout(git_opts.clone(), checkout_opts)?;
 | 
			
		||||
 | 
			
		||||
        let old_dir_name = format!(
 | 
			
		||||
            "{}/{}/{}/{}",
 | 
			
		||||
@@ -56,13 +58,29 @@ impl RepositoryImpl for GitRepo {
 | 
			
		||||
        match serde_yaml::from_str::<Version>(&helm_stdout) {
 | 
			
		||||
            Ok(res) => {
 | 
			
		||||
                new_dir_name = format!("{}/{}-{}", workdir_path, chart.name.clone(), res.version);
 | 
			
		||||
                rename(old_dir_name, new_dir_name.clone())?;
 | 
			
		||||
                match self.subtree {
 | 
			
		||||
                    true => {
 | 
			
		||||
                        let cmd = format!("git subtree split --prefix {}/{} -b helmule-subtree-split", self.path, chart.name.clone());
 | 
			
		||||
                        cli_exec_from_dir(cmd, format!("{}/{}", workdir_path.clone(), repo_name))?;
 | 
			
		||||
                        let checkout_opts = CheckoutOptions{
 | 
			
		||||
                            create: false,
 | 
			
		||||
                            git_ref: "helmule-subtree-split".to_string(),
 | 
			
		||||
                        };
 | 
			
		||||
                        git_instance.checkout(git_opts.clone(), checkout_opts)?;
 | 
			
		||||
                        let old_dir_name = format!("{}/{}", workdir_path.clone(), repo_name);
 | 
			
		||||
                        rename(old_dir_name, new_dir_name.clone())?;
 | 
			
		||||
                    },
 | 
			
		||||
                    false => {
 | 
			
		||||
                        rename(old_dir_name, new_dir_name.clone())?;
 | 
			
		||||
                                // Cleaning up
 | 
			
		||||
                        fs::remove_dir_all(format!("{}/{}", workdir_path, repo_name))?;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                };
 | 
			
		||||
            }
 | 
			
		||||
            Err(err) => return Err(Box::from(err)),
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        // Cleaning up
 | 
			
		||||
        fs::remove_dir_all(format!("{}/{}", workdir_path, repo_name))?;
 | 
			
		||||
 | 
			
		||||
        // Get the version
 | 
			
		||||
        let cmd = "helm show chart . | yq '.version'".to_string();
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user