corgea-cli 1.8.0__tar.gz → 1.8.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. corgea_cli-1.8.2/.github/workflows/test.yml +26 -0
  2. {corgea_cli-1.8.0 → corgea_cli-1.8.2}/Cargo.lock +1 -1
  3. {corgea_cli-1.8.0 → corgea_cli-1.8.2}/Cargo.toml +1 -1
  4. {corgea_cli-1.8.0 → corgea_cli-1.8.2}/PKG-INFO +1 -1
  5. {corgea_cli-1.8.0 → corgea_cli-1.8.2}/src/authorize.rs +204 -20
  6. {corgea_cli-1.8.0 → corgea_cli-1.8.2}/src/main.rs +12 -6
  7. {corgea_cli-1.8.0 → corgea_cli-1.8.2}/src/scan.rs +12 -13
  8. {corgea_cli-1.8.0 → corgea_cli-1.8.2}/src/scanners/fortify.rs +2 -2
  9. corgea_cli-1.8.0/.github/workflows/homebrew-bump.yml +0 -45
  10. {corgea_cli-1.8.0 → corgea_cli-1.8.2}/.github/workflows/npm-publish.yml +0 -0
  11. {corgea_cli-1.8.0 → corgea_cli-1.8.2}/.github/workflows/release-binaries.yml +0 -0
  12. {corgea_cli-1.8.0 → corgea_cli-1.8.2}/.github/workflows/release.yml +0 -0
  13. {corgea_cli-1.8.0 → corgea_cli-1.8.2}/.github/workflows/update_docs..yml +0 -0
  14. {corgea_cli-1.8.0 → corgea_cli-1.8.2}/.gitignore +0 -0
  15. {corgea_cli-1.8.0 → corgea_cli-1.8.2}/LICENSE +0 -0
  16. {corgea_cli-1.8.0 → corgea_cli-1.8.2}/README.md +0 -0
  17. {corgea_cli-1.8.0 → corgea_cli-1.8.2}/bin/corgea.js +0 -0
  18. {corgea_cli-1.8.0 → corgea_cli-1.8.2}/build_release.sh +0 -0
  19. {corgea_cli-1.8.0 → corgea_cli-1.8.2}/package.json +0 -0
  20. {corgea_cli-1.8.0 → corgea_cli-1.8.2}/pyproject.toml +0 -0
  21. {corgea_cli-1.8.0 → corgea_cli-1.8.2}/scripts/npm/bundle-binaries.js +0 -0
  22. {corgea_cli-1.8.0 → corgea_cli-1.8.2}/src/cicd.rs +0 -0
  23. {corgea_cli-1.8.0 → corgea_cli-1.8.2}/src/config.rs +0 -0
  24. {corgea_cli-1.8.0 → corgea_cli-1.8.2}/src/inspect.rs +0 -0
  25. {corgea_cli-1.8.0 → corgea_cli-1.8.2}/src/list.rs +0 -0
  26. {corgea_cli-1.8.0 → corgea_cli-1.8.2}/src/log.rs +0 -0
  27. {corgea_cli-1.8.0 → corgea_cli-1.8.2}/src/scanners/blast.rs +0 -0
  28. {corgea_cli-1.8.0 → corgea_cli-1.8.2}/src/scanners/parsers/checkmarx.rs +0 -0
  29. {corgea_cli-1.8.0 → corgea_cli-1.8.2}/src/scanners/parsers/coverity.rs +0 -0
  30. {corgea_cli-1.8.0 → corgea_cli-1.8.2}/src/scanners/parsers/mod.rs +0 -0
  31. {corgea_cli-1.8.0 → corgea_cli-1.8.2}/src/scanners/parsers/sarif.rs +0 -0
  32. {corgea_cli-1.8.0 → corgea_cli-1.8.2}/src/scanners/parsers/semgrep.rs +0 -0
  33. {corgea_cli-1.8.0 → corgea_cli-1.8.2}/src/setup_hooks.rs +0 -0
  34. {corgea_cli-1.8.0 → corgea_cli-1.8.2}/src/targets.rs +0 -0
  35. {corgea_cli-1.8.0 → corgea_cli-1.8.2}/src/utils/api.rs +0 -0
  36. {corgea_cli-1.8.0 → corgea_cli-1.8.2}/src/utils/generic.rs +0 -0
  37. {corgea_cli-1.8.0 → corgea_cli-1.8.2}/src/utils/terminal.rs +0 -0
  38. {corgea_cli-1.8.0 → corgea_cli-1.8.2}/src/wait.rs +0 -0
@@ -0,0 +1,26 @@
1
+ name: Test
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ - master
8
+ pull_request:
9
+
10
+ jobs:
11
+ rust-tests:
12
+ runs-on: ubuntu-latest
13
+
14
+ steps:
15
+ - name: Checkout
16
+ uses: actions/checkout@v4
17
+
18
+ - name: Setup Rust
19
+ uses: dtolnay/rust-toolchain@stable
20
+
21
+ - name: Cache cargo
22
+ uses: Swatinem/rust-cache@v2
23
+
24
+
25
+ - name: Run unit tests
26
+ run: cargo test
@@ -311,7 +311,7 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
311
311
 
312
312
  [[package]]
313
313
  name = "corgea"
314
- version = "1.8.0"
314
+ version = "1.8.2"
315
315
  dependencies = [
316
316
  "chrono",
317
317
  "clap",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "corgea"
3
- version = "1.8.0"
3
+ version = "1.8.2"
4
4
  edition = "2021"
5
5
  readme = "README.md"
6
6
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: corgea-cli
3
- Version: 1.8.0
3
+ Version: 1.8.2
4
4
  Classifier: Development Status :: 5 - Production/Stable
5
5
  Classifier: Environment :: Console
6
6
  Classifier: Intended Audience :: Developers
@@ -137,32 +137,36 @@ async fn start_callback_server(
137
137
  };
138
138
 
139
139
  loop {
140
- let (stream, _) = listener.accept().await?;
141
- let io = TokioIo::new(stream);
142
- let auth_code_clone = auth_code.clone();
143
-
144
- let service = service_fn(move |req| {
145
- handle_callback(req, auth_code_clone.clone())
146
- });
147
-
148
- tokio::task::spawn(async move {
149
- if let Err(err) = hyper::server::conn::http1::Builder::new()
150
- .serve_connection(io, service)
151
- .await
152
- {
153
- eprintln!("Error serving connection: {:?}", err);
140
+ tokio::select! {
141
+ accept_result = listener.accept() => {
142
+ let (stream, _) = accept_result?;
143
+ let io = TokioIo::new(stream);
144
+ let auth_code_clone = auth_code.clone();
145
+
146
+ let service = service_fn(move |req| {
147
+ handle_callback(req, auth_code_clone.clone())
148
+ });
149
+
150
+ tokio::task::spawn(async move {
151
+ if let Err(err) = hyper::server::conn::http1::Builder::new()
152
+ .serve_connection(io, service)
153
+ .await
154
+ {
155
+ eprintln!("Error serving connection: {:?}", err);
156
+ }
157
+ });
154
158
  }
155
- });
156
-
157
- // Check if we got the code
159
+ _ = tokio::time::sleep(Duration::from_millis(100)) => {}
160
+ }
161
+
162
+ // Check if we got the code.
163
+ // We must do this outside of `accept()` blocking so we don't miss a code
164
+ // that was set by the request task after a single callback request.
158
165
  if let Ok(code_guard) = auth_code.lock() {
159
166
  if let Some(code) = code_guard.as_ref() {
160
167
  return Ok(code.clone());
161
168
  }
162
169
  }
163
-
164
- // Add a small delay to prevent busy waiting
165
- tokio::time::sleep(Duration::from_millis(100)).await;
166
170
  }
167
171
  }
168
172
 
@@ -523,3 +527,183 @@ fn parse_query_params(query: &str) -> HashMap<String, String> {
523
527
  }
524
528
 
525
529
 
530
+
531
+ #[cfg(test)]
532
+ mod tests {
533
+ use super::*;
534
+ use std::io::{Read, Write};
535
+ use std::net::{TcpListener as StdTcpListener, TcpStream};
536
+ use std::sync::mpsc;
537
+ use std::thread;
538
+ use std::time::Duration as StdDuration;
539
+ use tokio::runtime::Runtime;
540
+ use tokio::time::{timeout, Duration};
541
+
542
+ fn reserve_ephemeral_port() -> u16 {
543
+ let listener = StdTcpListener::bind("127.0.0.1:0").expect("failed to bind ephemeral port");
544
+ listener.local_addr().expect("failed to get local addr").port()
545
+ }
546
+
547
+ fn spawn_callback_server(
548
+ port: u16,
549
+ auth_code: Arc<Mutex<Option<String>>>,
550
+ ) -> mpsc::Receiver<Result<String, String>> {
551
+ let (tx, rx) = mpsc::channel();
552
+ thread::spawn(move || {
553
+ let runtime = Runtime::new().expect("failed to create tokio runtime");
554
+ let result = runtime
555
+ .block_on(start_callback_server(port, auth_code))
556
+ .map_err(|e| e.to_string());
557
+ tx.send(result).expect("failed to send callback result");
558
+ });
559
+
560
+ rx
561
+ }
562
+
563
+ fn send_http_get(port: u16, path: &str) -> (u16, String) {
564
+ let mut stream = None;
565
+
566
+ for _ in 0..50 {
567
+ match TcpStream::connect(("127.0.0.1", port)) {
568
+ Ok(s) => {
569
+ stream = Some(s);
570
+ break;
571
+ }
572
+ Err(_) => thread::sleep(StdDuration::from_millis(20)),
573
+ }
574
+ }
575
+
576
+ let mut stream = stream.expect("failed to connect to callback server");
577
+ let request = format!("GET {} HTTP/1.0\r\n\r\n", path);
578
+
579
+ stream
580
+ .write_all(request.as_bytes())
581
+ .expect("failed to write request");
582
+
583
+ let mut raw_response = String::new();
584
+ stream
585
+ .read_to_string(&mut raw_response)
586
+ .expect("failed to read response");
587
+
588
+ let mut sections = raw_response.splitn(2, "\r\n\r\n");
589
+ let headers = sections.next().expect("response headers missing");
590
+ let body = sections.next().unwrap_or_default().to_string();
591
+ let status_line = headers.lines().next().expect("status line missing");
592
+ let status = status_line
593
+ .split_whitespace()
594
+ .nth(1)
595
+ .expect("status code missing")
596
+ .parse::<u16>()
597
+ .expect("invalid status code");
598
+
599
+ (status, body)
600
+ }
601
+
602
+ #[test]
603
+ fn parse_query_params_decodes_values() {
604
+ let params = parse_query_params("code=a%20b&error_description=needs%2Blogin");
605
+
606
+ assert_eq!(params.get("code"), Some(&"a b".to_string()));
607
+ assert_eq!(params.get("error_description"), Some(&"needs+login".to_string()));
608
+ }
609
+
610
+ #[test]
611
+ fn parse_query_params_ignores_malformed_pairs() {
612
+ let params = parse_query_params("valid=ok&invalid&also_invalid=");
613
+
614
+ assert_eq!(params.get("valid"), Some(&"ok".to_string()));
615
+ assert_eq!(params.get("invalid"), None);
616
+ assert_eq!(params.get("also_invalid"), Some(&"".to_string()));
617
+ }
618
+
619
+ #[test]
620
+ fn port_is_available_reflects_current_port_usage() {
621
+ let listener = StdTcpListener::bind("127.0.0.1:0").expect("failed to bind ephemeral port");
622
+ let port = listener
623
+ .local_addr()
624
+ .expect("failed to get listener addr")
625
+ .port();
626
+
627
+ assert!(!port_is_available(port));
628
+ drop(listener);
629
+ assert!(port_is_available(port));
630
+ }
631
+
632
+ #[test]
633
+ fn find_available_port_skips_ports_that_are_in_use() {
634
+ let listener = StdTcpListener::bind("127.0.0.1:0").expect("failed to bind ephemeral port");
635
+ let occupied_port = listener
636
+ .local_addr()
637
+ .expect("failed to get listener addr")
638
+ .port();
639
+
640
+ let found_port = find_available_port(occupied_port).expect("should find an available port");
641
+
642
+ assert_ne!(found_port, occupied_port);
643
+ }
644
+
645
+ #[tokio::test]
646
+ async fn start_callback_server_returns_without_waiting_for_second_connection() {
647
+ let port = reserve_ephemeral_port();
648
+ let auth_code = Arc::new(Mutex::new(Some("test-code".to_string())));
649
+
650
+ let returned_code = timeout(
651
+ Duration::from_millis(300),
652
+ start_callback_server(port, auth_code),
653
+ )
654
+ .await
655
+ .expect("callback server timed out")
656
+ .expect("callback server should return code");
657
+
658
+ assert_eq!(returned_code, "test-code");
659
+ }
660
+
661
+ #[test]
662
+ fn start_callback_server_returns_bind_error_if_port_is_occupied() {
663
+ let listener = StdTcpListener::bind("127.0.0.1:0").expect("failed to bind ephemeral port");
664
+ let occupied_port = listener
665
+ .local_addr()
666
+ .expect("failed to get listener addr")
667
+ .port();
668
+
669
+ let runtime = Runtime::new().expect("failed to create runtime");
670
+ let result = runtime.block_on(start_callback_server(
671
+ occupied_port,
672
+ Arc::new(Mutex::new(None::<String>)),
673
+ ));
674
+
675
+ assert!(result.is_err());
676
+ let error = result.err().expect("expected bind error").to_string();
677
+ assert!(error.contains("Failed to bind"));
678
+ }
679
+
680
+ #[test]
681
+ fn callback_server_serves_waiting_error_and_success_pages_then_returns_code() {
682
+ let port = reserve_ephemeral_port();
683
+ let auth_code = Arc::new(Mutex::new(None::<String>));
684
+ let result_rx = spawn_callback_server(port, auth_code);
685
+
686
+ let (waiting_status, waiting_body) = send_http_get(port, "/");
687
+ assert_eq!(waiting_status, 200);
688
+ assert!(waiting_body.contains("Waiting for Authorization"));
689
+
690
+ let (error_status, error_body) = send_http_get(
691
+ port,
692
+ "/?error=access_denied&error_description=user%20cancelled",
693
+ );
694
+ assert_eq!(error_status, 400);
695
+ assert!(error_body.contains("Authorization Failed"));
696
+ assert!(error_body.contains("access_denied"));
697
+
698
+ let (success_status, success_body) = send_http_get(port, "/?code=abc123");
699
+ assert_eq!(success_status, 200);
700
+ assert!(success_body.contains("Successfully Signed In"));
701
+
702
+ let returned_code = result_rx
703
+ .recv_timeout(StdDuration::from_secs(2))
704
+ .expect("callback server should return in time")
705
+ .expect("callback server should return code");
706
+
707
+ assert_eq!(returned_code, "abc123");
708
+ }
709
+ }
@@ -52,6 +52,12 @@ enum Commands {
52
52
  Upload {
53
53
  /// Option path to JSON report to upload
54
54
  report: Option<String>,
55
+
56
+ #[arg(
57
+ long,
58
+ help = "The name of the Corgea project. Defaults to git repository name if found, otherwise to the current directory name."
59
+ )]
60
+ project_name: Option<String>,
55
61
  },
56
62
  /// Scan the current directory. Supports blast, semgrep and snyk.
57
63
  Scan {
@@ -236,18 +242,18 @@ fn main() {
236
242
  }
237
243
  }
238
244
  }
239
- Some(Commands::Upload { report }) => {
245
+ Some(Commands::Upload { report, project_name }) => {
240
246
  verify_token_and_exit_when_fail(&corgea_config);
241
247
  match report {
242
248
  Some(report) => {
243
249
  if report.ends_with(".fpr") {
244
- fortify_parse(&corgea_config, report);
250
+ fortify_parse(&corgea_config, report, project_name.clone());
245
251
  } else {
246
- scan::read_file_report(&corgea_config, report);
252
+ scan::read_file_report(&corgea_config, report, project_name.clone());
247
253
  }
248
254
  }
249
255
  None => {
250
- scan::read_stdin_report(&corgea_config);
256
+ scan::read_stdin_report(&corgea_config, project_name.clone());
251
257
  }
252
258
  }
253
259
  }
@@ -332,8 +338,8 @@ fn main() {
332
338
  }
333
339
  }
334
340
  match scanner {
335
- Scanner::Snyk => scan::run_snyk(&corgea_config),
336
- Scanner::Semgrep => scan::run_semgrep(&corgea_config),
341
+ Scanner::Snyk => scan::run_snyk(&corgea_config, project_name.clone()),
342
+ Scanner::Semgrep => scan::run_semgrep(&corgea_config, project_name.clone()),
337
343
  Scanner::Blast => scanners::blast::run(&corgea_config, fail_on.clone(), fail, only_uncommitted, scan_type.clone(), policy.clone(), out_format.clone(), out_file.clone(), target.clone(), project_name.clone())
338
344
  }
339
345
  }
@@ -51,7 +51,7 @@ pub struct ScanUploadResult {
51
51
  pub project_id: Option<String>,
52
52
  }
53
53
 
54
- pub fn run_semgrep(config: &Config) {
54
+ pub fn run_semgrep(config: &Config, project_name: Option<String>) {
55
55
  println!("Scanning with semgrep...");
56
56
  let base_command = "semgrep";
57
57
  let mut command = std::process::Command::new(base_command);
@@ -61,12 +61,12 @@ pub fn run_semgrep(config: &Config) {
61
61
 
62
62
  let output = run_command(&base_command.to_string(), command);
63
63
 
64
- if let Some(result) = parse_scan(config, output, true) {
64
+ if let Some(result) = parse_scan(config, output, true, project_name) {
65
65
  crate::wait::run(config, Some(result.scan_id), result.project_id);
66
66
  }
67
67
  }
68
68
 
69
- pub fn run_snyk(config: &Config) {
69
+ pub fn run_snyk(config: &Config, project_name: Option<String>) {
70
70
  println!("Scanning with snyk...");
71
71
  let base_command = "snyk";
72
72
  let mut command = std::process::Command::new(base_command);
@@ -76,19 +76,19 @@ pub fn run_snyk(config: &Config) {
76
76
 
77
77
  let output = run_command(&base_command.to_string(), command);
78
78
 
79
- if let Some(result) = parse_scan(config, output, true) {
79
+ if let Some(result) = parse_scan(config, output, true, project_name) {
80
80
  crate::wait::run(config, Some(result.scan_id), result.project_id);
81
81
  }
82
82
  }
83
83
 
84
- pub fn read_stdin_report(config: &Config) {
84
+ pub fn read_stdin_report(config: &Config, project_name: Option<String>) {
85
85
  let mut input = String::new();
86
86
  let _ = io::stdin().read_to_string(&mut input);
87
87
 
88
- let _ = parse_scan(config, input, false);
88
+ let _ = parse_scan(config, input, false, project_name);
89
89
  }
90
90
 
91
- pub fn read_file_report(config: &Config, file_path: &str) {
91
+ pub fn read_file_report(config: &Config, file_path: &str, project_name: Option<String>) {
92
92
  let input = match std::fs::read_to_string(file_path) {
93
93
  Ok(input) => input,
94
94
  Err(e) => {
@@ -97,10 +97,10 @@ pub fn read_file_report(config: &Config, file_path: &str) {
97
97
  }
98
98
  };
99
99
 
100
- let _ = parse_scan(config, input, false);
100
+ let _ = parse_scan(config, input, false, project_name);
101
101
  }
102
102
 
103
- pub fn parse_scan(config: &Config, input: String, save_to_file: bool) -> Option<ScanUploadResult> {
103
+ pub fn parse_scan(config: &Config, input: String, save_to_file: bool, project_name: Option<String>) -> Option<ScanUploadResult> {
104
104
  debug("Parsing the scan report");
105
105
 
106
106
  // Remove BOM (Byte Order Mark) if present
@@ -115,7 +115,7 @@ pub fn parse_scan(config: &Config, input: String, save_to_file: bool) -> Option<
115
115
  std::process::exit(0);
116
116
  }
117
117
 
118
- return upload_scan(config, parse_result.paths, parse_result.scanner, cleaned_input.to_string(), save_to_file);
118
+ return upload_scan(config, parse_result.paths, parse_result.scanner, cleaned_input.to_string(), save_to_file, project_name);
119
119
  }
120
120
 
121
121
  Err(error_message) => {
@@ -125,7 +125,7 @@ pub fn parse_scan(config: &Config, input: String, save_to_file: bool) -> Option<
125
125
  }
126
126
  }
127
127
 
128
- pub fn upload_scan(config: &Config, paths: Vec<String>, scanner: String, input: String, save_to_file: bool) -> Option<ScanUploadResult> {
128
+ pub fn upload_scan(config: &Config, paths: Vec<String>, scanner: String, input: String, save_to_file: bool, project_name: Option<String>) -> Option<ScanUploadResult> {
129
129
  let in_ci = running_in_ci();
130
130
  let ci_platform = which_ci();
131
131
  let github_env_vars = get_github_env_vars();
@@ -133,7 +133,6 @@ pub fn upload_scan(config: &Config, paths: Vec<String>, scanner: String, input:
133
133
  let run_id = Uuid::new_v4().to_string();
134
134
  let token = config.get_token();
135
135
  let base_url = config.get_url();
136
- let current_dir = std::env::current_dir().expect("Failed to get current directory");
137
136
  let project;
138
137
 
139
138
  if in_ci {
@@ -142,7 +141,7 @@ pub fn upload_scan(config: &Config, paths: Vec<String>, scanner: String, input:
142
141
  github_env_vars.get("GITHUB_REPOSITORY").expect("Failed to get GITHUB_REPOSITORY").to_string(),
143
142
  github_env_vars.get("GITHUB_PR").expect("Failed to get GITHUB_REPOSITORY").to_string())
144
143
  } else {
145
- project = current_dir.file_name().expect("Failed to get directory name").to_str().expect("Failed to convert OsStr to str").to_string();
144
+ project = utils::generic::determine_project_name(project_name.as_deref());
146
145
  }
147
146
  let repo_data = std::env::var("REPO_DATA").unwrap_or_else(|_| "".to_string()); //encoded data to forward.
148
147
 
@@ -9,7 +9,7 @@ use quick_xml::reader::Reader;
9
9
  use crate::Config;
10
10
  use crate::scan::upload_scan;
11
11
 
12
- pub fn parse(config: &Config, file_path: &str) {
12
+ pub fn parse(config: &Config, file_path: &str, project_name: Option<String>) {
13
13
  let temp_dir = match TempDir::new() {
14
14
  Ok(dir) => dir,
15
15
  Err(e) => {
@@ -48,7 +48,7 @@ pub fn parse(config: &Config, file_path: &str) {
48
48
  }
49
49
 
50
50
  let (scan_data, paths) = extract_file_path(outpath);
51
- let _scan_id = upload_scan(config, paths, "fortify".to_string(), scan_data, false);
51
+ let _scan_id = upload_scan(config, paths, "fortify".to_string(), scan_data, false, project_name);
52
52
  } else {
53
53
  println!("File 'audit.fvdl' not found in the archive");
54
54
  };
@@ -1,45 +0,0 @@
1
- name: Update Homebrew Formula
2
-
3
- on:
4
- release:
5
- types: [published]
6
-
7
- jobs:
8
- update-formula:
9
- runs-on: ubuntu-latest
10
- steps:
11
- - name: Checkout Repository
12
- uses: actions/checkout@v4
13
-
14
- - name: Get Latest PyPI Version
15
- id: get_version
16
- run: |
17
- VERSION=$(curl -s https://pypi.org/pypi/corgea-cli/json | jq -r .info.version)
18
- echo "Latest version: $VERSION"
19
- echo "version=$VERSION" >> $GITHUB_ENV
20
-
21
- - name: Get Latest Source Tarball URL
22
- id: get_tarball
23
- run: |
24
- URL=$(curl -s https://pypi.org/pypi/corgea-cli/json | jq -r '.urls[] | select(.packagetype=="sdist") | .url')
25
- echo "Tarball URL: $URL"
26
- echo "tarball_url=$URL" >> $GITHUB_ENV
27
-
28
- - name: Get SHA256 Hash
29
- id: get_sha
30
- run: |
31
- curl -o corgea-cli.tar.gz ${{ env.tarball_url }}
32
- SHA256=$(shasum -a 256 corgea-cli.tar.gz | awk '{print $1}')
33
- echo "SHA256: $SHA256"
34
- echo "sha256=$SHA256" >> $GITHUB_ENV
35
-
36
- - name: Update Homebrew Formula
37
- run: |
38
- brew bump-formula-pr --strict corgea-cli \
39
- --url=${{ env.tarball_url }} \
40
- --sha256=${{ env.sha256 }} \
41
- --no-browse \
42
- --no-fork \
43
- --force
44
- env:
45
- HOMEBREW_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes