Skip to content

Commit b111662

Browse files
committed
Empty Commit
1 parent 4871b70 commit b111662

8 files changed

Lines changed: 210 additions & 50 deletions

File tree

File renamed without changes.
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
name: Generate Diff
2+
3+
on:
4+
pull_request:
5+
branches:
6+
- "main"
7+
paths:
8+
- "src/**"
9+
- Cargo.toml
10+
11+
jobs:
12+
build:
13+
runs-on: ubuntu-latest
14+
permissions:
15+
contents: read
16+
pull-requests: write
17+
18+
steps:
19+
- uses: actions/checkout@v4
20+
with:
21+
path: pull-request
22+
23+
- uses: actions/checkout@v4
24+
with:
25+
ref: main
26+
path: main
27+
28+
- name: Generate Diff
29+
run: |
30+
docker build . -t image
31+
docker run \
32+
--network=host \
33+
-v /var/run/docker.sock:/var/run/docker.sock \
34+
-v $(pwd)/main:/base-branch \
35+
-v $(pwd)/pull-request:/target-branch \
36+
-v $(pwd)/output:/output \
37+
image
38+
39+
- name: Post diff as comment
40+
run: |
41+
gh pr comment ${{ github.event.number }} --repo ${{ github.repository }} --body-file output/diff.md --edit-last || \
42+
gh pr comment ${{ github.event.number }} --repo ${{ github.repository }} --body-file output/diff.md
43+
env:
44+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "argocd-diff-preview"
3-
version = "0.0.3"
3+
version = "0.0.9"
44
edition = "2021"
55

66
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

Dockerfile_ARM64

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ COPY ./src ./src
1717

1818
# install kind
1919
RUN apt-get update && apt-get install -y curl
20-
RUN curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.22.0/kind-linux-arm64
20+
RUN curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.23.0/kind-linux-arm64
2121
RUN chmod +x ./kind
2222

2323
# Install kubectl

src/diff.rs

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
use log::{debug, info};
2+
use regex::Regex;
23
use std::fs;
34
use std::{error::Error, process::Output};
45

5-
use crate::utils::run_command;
6+
use crate::utils::{check_if_folder_exists, run_command};
67
use crate::Branch;
78

89
pub async fn generate_diff(
@@ -134,3 +135,41 @@ fn print_diff(summary: &str, diff: &str) -> String {
134135
.trim_start()
135136
.to_string()
136137
}
138+
139+
fn check_if_folder_contains_git_repo(branch: &Branch) -> bool {
140+
check_if_folder_exists(&format!("{}/.git", branch.folder()))
141+
}
142+
143+
pub async fn get_repo_name(branch: Branch) -> Option<String> {
144+
if !check_if_folder_contains_git_repo(&branch) {
145+
return None;
146+
}
147+
148+
let repo_url_regex = Regex::new(r"[:/](?P<repo>[^/]+/[^/]+)\.git").unwrap();
149+
let repo_name = run_command("git remote get-url origin", Some(branch.folder()))
150+
.await
151+
.ok()?
152+
.stdout;
153+
154+
let repo_name = String::from_utf8_lossy(&repo_name);
155+
156+
match repo_url_regex.captures(repo_name.as_ref()) {
157+
Some(capture) => {
158+
let repo_name = capture.name("repo").unwrap().as_str();
159+
Some(repo_name.trim().to_string())
160+
}
161+
None => None,
162+
}
163+
}
164+
165+
pub async fn get_branch_name(branch: Branch) -> Option<String> {
166+
if !check_if_folder_contains_git_repo(&branch) {
167+
return None;
168+
}
169+
170+
let branch_name = run_command("git rev-parse --abbrev-ref HEAD", Some(branch.folder()))
171+
.await
172+
.ok()?
173+
.stdout;
174+
Some(String::from_utf8_lossy(&branch_name).trim().to_string())
175+
}

src/extract.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,15 @@ use log::{debug, error, info};
88
use crate::utils::run_command;
99
use crate::{apply_manifest, apps_file, Branch};
1010

11-
static ERROR_MESSAGES: [&str; 7] = [
11+
static ERROR_MESSAGES: [&str; 8] = [
1212
"helm template .",
1313
"authentication required",
1414
"authentication failed",
1515
"path does not exist",
1616
"error converting YAML to JSON",
1717
"Unknown desc = `helm template .",
1818
"Unknown desc = Unable to resolve",
19+
"is not a valid chart repository or cannot be reached",
1920
];
2021

2122
static TIMEOUT_MESSAGES: [&str; 4] = [

src/main.rs

Lines changed: 121 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::{
66
process::{Command, Output},
77
};
88

9-
use log::{debug, error, info};
9+
use log::{debug, error, info, warn};
1010
use std::path::PathBuf;
1111
use structopt::StructOpt;
1212

@@ -50,17 +50,17 @@ struct Opt {
5050
#[structopt(long, env)]
5151
argocd_version: Option<String>,
5252

53-
/// Base branch name
54-
#[structopt(short, long, default_value = "main", env)]
55-
base_branch: String,
53+
/// Base branch name. If not provided, it will be auto-detected from .git folder in base-branch folder
54+
#[structopt(short, long, env)]
55+
base_branch: Option<String>,
5656

57-
/// Target branch name
57+
/// Target branch name. If not provided, it will be auto-detected from .git folder in target-branch folder
5858
#[structopt(short, long, env)]
59-
target_branch: String,
59+
target_branch: Option<String>,
6060

61-
/// Git Repository. Format: OWNER/REPO
62-
#[structopt(long = "repo", env)]
63-
repo: String,
61+
/// Git Repository. Format: OWNER/REPO. If not provided, it will be auto-detected from .git folder in base-branch folder
62+
#[structopt(long, env)]
63+
repo: Option<String>,
6464

6565
/// Output folder where the diff will be saved
6666
#[structopt(short, long, default_value = "./output", env)]
@@ -90,6 +90,15 @@ enum Branch {
9090
Target,
9191
}
9292

93+
impl Branch {
94+
fn folder(&self) -> &str {
95+
match self {
96+
Branch::Base => "base-branch",
97+
Branch::Target => "target-branch",
98+
}
99+
}
100+
}
101+
93102
impl std::fmt::Display for Branch {
94103
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
95104
match self {
@@ -106,9 +115,6 @@ fn apps_file(branch: &Branch) -> &'static str {
106115
}
107116
}
108117

109-
const BASE_BRANCH_FOLDER: &str = "base-branch";
110-
const TARGET_BRANCH_FOLDER: &str = "target-branch";
111-
112118
#[tokio::main]
113119
async fn main() -> Result<(), Box<dyn Error>> {
114120
let opt = Opt::from_args();
@@ -133,19 +139,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
133139
.filter(|f| !f.trim().is_empty())
134140
.map(|f| Regex::new(&f).unwrap());
135141

136-
let base_branch_name = opt.base_branch;
137-
let target_branch_name = opt.target_branch;
138-
let repo = opt.repo;
139-
let diff_ignore = opt.diff_ignore.filter(|f| !f.trim().is_empty());
140-
let timeout = opt.timeout;
141-
let output_folder = opt.output_folder.as_str();
142-
let secrets_folder = opt.secrets_folder.as_str();
143-
let line_count = opt.line_count;
144-
let argocd_version = opt
145-
.argocd_version
146-
.as_deref()
147-
.filter(|f| !f.trim().is_empty());
148-
let max_diff_length = opt.max_diff_length;
142+
info!("✨ Running with:");
149143

150144
// select local cluster tool
151145
let tool = match opt.local_cluster_tool {
@@ -159,19 +153,28 @@ async fn main() -> Result<(), Box<dyn Error>> {
159153
}
160154
};
161155

162-
let repo_regex = Regex::new(r"^[a-zA-Z0-9-]+/[a-zA-Z0-9-]+$").unwrap();
163-
if !repo_regex.is_match(&repo) {
164-
error!("❌ Invalid repository format. Please use OWNER/REPO");
165-
panic!("Invalid repository format");
166-
}
167-
168-
info!("✨ Running with:");
169156
info!("✨ - local-cluster-tool: {:?}", tool);
170-
info!("✨ - base-branch: {}", base_branch_name);
171-
info!("✨ - target-branch: {}", target_branch_name);
157+
158+
let (repo_name, base_branch_name, target_branch_name) = repo_and_branch_config(
159+
opt.repo,
160+
opt.base_branch,
161+
opt.target_branch,
162+
)
163+
.await;
164+
165+
let diff_ignore = opt.diff_ignore.filter(|f| !f.trim().is_empty());
166+
let timeout = opt.timeout;
167+
let output_folder = opt.output_folder.as_str();
168+
let secrets_folder = opt.secrets_folder.as_str();
169+
let line_count = opt.line_count;
170+
let argocd_version = opt
171+
.argocd_version
172+
.as_deref()
173+
.filter(|f| !f.trim().is_empty());
174+
let max_diff_length = opt.max_diff_length;
175+
172176
info!("✨ - secrets-folder: {}", secrets_folder);
173177
info!("✨ - output-folder: {}", output_folder);
174-
info!("✨ - repo: {}", repo);
175178
info!("✨ - timeout: {} seconds", timeout);
176179
if let Some(a) = file_regex.clone() {
177180
info!("✨ - file-regex: {}", a.as_str());
@@ -189,18 +192,18 @@ async fn main() -> Result<(), Box<dyn Error>> {
189192
info!("✨ - max-diff-length: {}", a);
190193
}
191194

192-
if !check_if_folder_exists(&BASE_BRANCH_FOLDER) {
195+
if !check_if_folder_exists(&Branch::Base.folder()) {
193196
error!(
194197
"❌ Base branch folder does not exist: {}",
195-
BASE_BRANCH_FOLDER
198+
Branch::Base.folder()
196199
);
197200
panic!("Base branch folder does not exist");
198201
}
199202

200-
if !check_if_folder_exists(&TARGET_BRANCH_FOLDER) {
203+
if !check_if_folder_exists(&Branch::Target.folder()) {
201204
error!(
202205
"❌ Target branch folder does not exist: {}",
203-
TARGET_BRANCH_FOLDER
206+
Branch::Target.folder()
204207
);
205208
panic!("Target branch folder does not exist");
206209
}
@@ -224,15 +227,18 @@ async fn main() -> Result<(), Box<dyn Error>> {
224227
}
225228

226229
// remove .git from repo
227-
let repo = repo.trim_end_matches(".git");
228-
let base_apps =
229-
parsing::get_applications(&BASE_BRANCH_FOLDER, &base_branch_name, &file_regex, &repo)
230-
.await?;
230+
let base_apps = parsing::get_applications(
231+
&Branch::Base.folder(),
232+
&base_branch_name,
233+
&file_regex,
234+
&repo_name,
235+
)
236+
.await?;
231237
let target_apps = parsing::get_applications(
232-
&TARGET_BRANCH_FOLDER,
238+
&Branch::Target.folder(),
233239
&target_branch_name,
234240
&file_regex,
235-
&repo,
241+
&repo_name,
236242
)
237243
.await?;
238244

@@ -311,3 +317,73 @@ fn apply_folder(folder_name: &str) -> Result<u64, String> {
311317
}
312318
Ok(count)
313319
}
320+
321+
async fn repo_and_branch_config(
322+
base_repo_option: Option<String>,
323+
base_branch_name_option: Option<String>,
324+
target_branch_name_option: Option<String>,
325+
) -> (String, String, String) {
326+
let repo_regex = Regex::new(r"^[a-zA-Z0-9-]+/[a-zA-Z0-9-]+$").unwrap();
327+
328+
let repo_name = match (
329+
base_repo_option,
330+
diff::get_repo_name(Branch::Base).await,
331+
) {
332+
(Some(r), _) if repo_regex.is_match(&r) => {
333+
info!("✨ - repo: {}", r);
334+
r
335+
}
336+
(Some(_), _) => {
337+
error!("❌ Invalid repository format. Please use OWNER/REPO");
338+
panic!("Invalid repository format");
339+
}
340+
(None, Some(r)) => {
341+
info!("✨ - repo: {} (Auto Detected)", r);
342+
r
343+
}
344+
_ => {
345+
warn!("🚨 Failed to autodetect repository from .git folder");
346+
error!("❌ Please provide the repository with --repo in the format OWNER/REPO");
347+
panic!("Repository not provided and not autodetected in in .git folder")
348+
}
349+
};
350+
351+
let base_branch_name = match (
352+
base_branch_name_option,
353+
diff::get_branch_name(Branch::Base).await,
354+
) {
355+
(Some(b), _) => {
356+
info!("✨ - base-branch: {}", b);
357+
b
358+
}
359+
(None, Some(b)) => {
360+
info!("✨ - base-branch: {} (Auto Detected)", b);
361+
b
362+
}
363+
_ => {
364+
warn!("🚨 Failed to autodetect base-branch name from .git folder");
365+
error!("❌ Please provide the base branch name with --base-branch");
366+
panic!("Base branch name not provided and not found in git remotes")
367+
}
368+
};
369+
370+
let target_branch_name = match (
371+
target_branch_name_option,
372+
diff::get_branch_name(Branch::Target).await,
373+
) {
374+
(Some(b), _) => {
375+
info!("✨ - target-branch: {}", b);
376+
b
377+
}
378+
(None, Some(b)) => {
379+
info!("✨ - base-branch: {} (Auto Detected)", b);
380+
b
381+
}
382+
_ => {
383+
warn!("🚨 Failed to autodetect target-branch name from .git folder");
384+
error!("❌ Please provide the target branch name with --target-branch");
385+
panic!("Target branch name not provided and not found in git remotes")
386+
}
387+
};
388+
(repo_name, base_branch_name, target_branch_name)
389+
}

0 commit comments

Comments
 (0)