Skip to content

Commit dea82fc

Browse files
authored
Merge pull request #72 from rust-lang/only-lint--github-from-the-root
only lint .github from the root
2 parents dee5bbe + c47da85 commit dea82fc

2 files changed

Lines changed: 44 additions & 3 deletions

File tree

.github/workflows/crabwatch.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,16 @@ jobs:
3434
-H "Accept: application/vnd.github.raw+json" > zizmor-default.yml
3535
3636
- name: Run zizmor
37+
# A missing or empty root .github directory has nothing to audit.
38+
if: ${{ hashFiles('.github/**') != '' }}
3739
uses: zizmorcore/zizmor-action@cc914d7f3750a2d13d75c7f184a1060aa0e9d482 # v0.6.4
3840
with:
3941
advanced-security: false
4042
config: zizmor-default.yml
43+
# Only lint the root .github directory.
44+
# Ignore nested .github directories because they can belong to
45+
# vendored projects or test fixtures.
46+
inputs: .github/
4147
# Don't fail on repositories without GitHub Actions workflows.
4248
fail-on-no-inputs: false
4349
persona: pedantic

src/scan.rs

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ pub struct ScanReport {
1717
pub outcome: ScanOutcome,
1818
}
1919

20-
fn zizmor_command(repo_path: &Path, config_path: &Path, github_token: &str) -> Command {
20+
fn zizmor_command(github_path: &Path, config_path: &Path, github_token: &str) -> Command {
2121
let mut command = Command::new("zizmor");
2222
command
2323
.env("ZIZMOR_GITHUB_TOKEN", github_token)
@@ -27,7 +27,7 @@ fn zizmor_command(repo_path: &Path, config_path: &Path, github_token: &str) -> C
2727
.arg("pedantic")
2828
// Fail on GitHub workflow syntax error.
2929
.arg("--strict-collection")
30-
.arg(repo_path);
30+
.arg(github_path);
3131
command
3232
}
3333

@@ -55,12 +55,28 @@ pub(crate) fn sync_zizmor_config(crabwatch_dir: &Path) -> anyhow::Result<PathBuf
5555
Ok(config_path)
5656
}
5757

58+
fn root_github_path(repo_path: &Path) -> anyhow::Result<Option<PathBuf>> {
59+
let github_path = repo_path.join(".github");
60+
let path = github_path
61+
.try_exists()
62+
.with_context(|| format!("failed to inspect GitHub directory at {github_path:?}"))?
63+
.then_some(github_path);
64+
Ok(path)
65+
}
66+
5867
pub async fn scan_workflows(
5968
repo_path: &Path,
6069
config_path: &Path,
6170
github_token: &str,
6271
) -> anyhow::Result<ScanReport> {
63-
let output = zizmor_command(repo_path, config_path, github_token)
72+
let Some(github_path) = root_github_path(repo_path)? else {
73+
return Ok(ScanReport {
74+
output: "no workflows to scan".to_string(),
75+
outcome: ScanOutcome::NoWorkflows,
76+
});
77+
};
78+
79+
let output = zizmor_command(&github_path, config_path, github_token)
6480
.output()
6581
.await;
6682

@@ -104,6 +120,25 @@ pub async fn scan_workflows(
104120
mod tests {
105121
use super::*;
106122

123+
#[tokio::test]
124+
async fn nested_workflows_without_root_github_are_not_scanned() {
125+
let repo = tempfile::tempdir().unwrap();
126+
let nested_workflows = repo.path().join("vendor/project/.github/workflows");
127+
std::fs::create_dir_all(&nested_workflows).unwrap();
128+
std::fs::write(
129+
nested_workflows.join("publish.yml"),
130+
"on: push\njobs:\n publish:\n runs-on: ubuntu-latest\n steps:\n - run: echo hello\n",
131+
)
132+
.unwrap();
133+
let config_dir = tempfile::tempdir().unwrap();
134+
let config_path = sync_zizmor_config(config_dir.path()).unwrap();
135+
136+
let report = scan_workflows(repo.path(), &config_path, "").await.unwrap();
137+
138+
assert_eq!(report.outcome, ScanOutcome::NoWorkflows);
139+
assert_eq!(report.output, "no workflows to scan");
140+
}
141+
107142
#[test]
108143
fn creates_config_and_keeps_identical_file() {
109144
// The first sync should create the directory and bundled config from scratch.

0 commit comments

Comments
 (0)