• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2025 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 
15 use std::collections::HashMap;
16 use std::io::BufReader;
17 use std::path::PathBuf;
18 use std::process;
19 
20 use anyhow::{anyhow, Result};
21 use cliclack::{intro, outro, outro_cancel, spinner};
22 use serde::Deserialize;
23 
24 #[derive(Clone, Debug, Deserialize)]
25 pub struct BazelPrograms {
26     pub default: Vec<Vec<String>>,
27 }
28 
29 #[derive(Clone, Debug, Deserialize)]
30 pub struct BazelPresubmit {
31     pub remote_cache: bool,
32     pub upload_local_results: bool,
33     pub programs: HashMap<String, Vec<Vec<String>>>,
34 }
35 
36 #[derive(Clone, Debug, Deserialize)]
37 pub struct PigweedConfig {
38     pub bazel_presubmit: BazelPresubmit,
39 }
40 
41 #[derive(Clone, Debug, Deserialize)]
42 pub struct PigweedProject {
43     pub pw: PigweedConfig,
44 }
45 
load_project_config() -> Result<PigweedProject>46 fn load_project_config() -> Result<PigweedProject> {
47     let workspace_dir = std::env::var("BUILD_WORKSPACE_DIRECTORY")
48         .map_err(|_| anyhow!("BUILD_WORKSPACE_DIRECTORY not found.  Please run inside bazel."))?;
49     let path: PathBuf = [&workspace_dir, "pigweed.json"].iter().collect();
50     let reader = BufReader::new(std::fs::File::open(path)?);
51 
52     let project_config = serde_json::from_reader(reader)?;
53     Ok(project_config)
54 }
55 
run_bazel_presubmit(args: &Vec<String>) -> Result<()>56 fn run_bazel_presubmit(args: &Vec<String>) -> Result<()> {
57     let workspace_dir = std::env::var("BUILD_WORKSPACE_DIRECTORY")
58         .map_err(|_| anyhow!("BUILD_WORKSPACE_DIRECTORY not found.  Please run inside bazel."))?;
59     let spinner = spinner();
60     spinner.start(format!("Running {args:?}..."));
61     let output = process::Command::new("bazelisk")
62         .current_dir(workspace_dir)
63         .args(args.clone())
64         .output()?;
65 
66     if !output.status.success() {
67         return Err(anyhow!(
68             "{args:?} failed:\n{}",
69             String::from_utf8_lossy(&output.stderr)
70         ));
71     }
72     spinner.stop(format!("{args:?} success."));
73 
74     Ok(())
75 }
76 
run_presubmit() -> Result<()>77 fn run_presubmit() -> Result<()> {
78     intro("Running presubmits")?;
79 
80     let config =
81         load_project_config().map_err(|e| anyhow!("Failed to load project config: {e}"))?;
82 
83     let Some(kernel_program) = config.pw.bazel_presubmit.programs.get("kernel") else {
84         return Err(anyhow!("No `kernel` program in projects bazel_presubmit"));
85     };
86 
87     for args in kernel_program {
88         run_bazel_presubmit(args)?;
89     }
90 
91     outro("All presubmits succeeded")?;
92     Ok(())
93 }
94 
main()95 fn main() {
96     if let Err(e) = run_presubmit() {
97         outro_cancel(format!("{e}")).expect("outro succeeds");
98         std::process::exit(1);
99     }
100 }
101