Skip to content

Commit e9c0a3e

Browse files
committed
trustpub: Implement extract_workflow_filename() fn
1 parent fae6984 commit e9c0a3e

File tree

2 files changed

+111
-0
lines changed

2 files changed

+111
-0
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
pub mod validation;
2+
mod workflows;
23

34
pub const GITHUB_ISSUER_URL: &str = "https://token.actions.githubusercontent.com";
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
use std::sync::LazyLock;
2+
3+
/// Extracts the workflow filename from a GitHub workflow reference.
4+
///
5+
/// In other words, it turns e.g. `rust-lang/regex/.github/workflows/ci.yml@refs/heads/main`
6+
/// into `ci.yml`, or `None` if the reference is in an unexpected format.
7+
#[allow(unused)]
8+
pub(crate) fn extract_workflow_filename(workflow_ref: &str) -> Option<&str> {
9+
static WORKFLOW_REF_RE: LazyLock<regex::Regex> =
10+
LazyLock::new(|| regex::Regex::new(r"([^/]+\.(yml|yaml))(@.+)").unwrap());
11+
12+
WORKFLOW_REF_RE
13+
.captures(workflow_ref)
14+
.and_then(|caps| caps.get(1))
15+
.map(|m| m.as_str())
16+
}
17+
18+
#[cfg(test)]
19+
mod tests {
20+
#[test]
21+
fn test_extract_workflow_filename() {
22+
let test_cases = [
23+
// Well-formed workflow refs, including exceedingly obnoxious ones
24+
// with `@` or extra suffixes or `git` refs that look like workflows.
25+
(
26+
"foo/bar/.github/workflows/basic.yml@refs/heads/main",
27+
Some("basic.yml"),
28+
),
29+
(
30+
"foo/bar/.github/workflows/basic.yaml@refs/heads/main",
31+
Some("basic.yaml"),
32+
),
33+
(
34+
"foo/bar/.github/workflows/has-dash.yml@refs/heads/main",
35+
Some("has-dash.yml"),
36+
),
37+
(
38+
"foo/bar/.github/workflows/has--dashes.yml@refs/heads/main",
39+
Some("has--dashes.yml"),
40+
),
41+
(
42+
"foo/bar/.github/workflows/has--dashes-.yml@refs/heads/main",
43+
Some("has--dashes-.yml"),
44+
),
45+
(
46+
"foo/bar/.github/workflows/has.period.yml@refs/heads/main",
47+
Some("has.period.yml"),
48+
),
49+
(
50+
"foo/bar/.github/workflows/has..periods.yml@refs/heads/main",
51+
Some("has..periods.yml"),
52+
),
53+
(
54+
"foo/bar/.github/workflows/has..periods..yml@refs/heads/main",
55+
Some("has..periods..yml"),
56+
),
57+
(
58+
"foo/bar/.github/workflows/has_underscore.yml@refs/heads/main",
59+
Some("has_underscore.yml"),
60+
),
61+
(
62+
"foo/bar/.github/workflows/nested@evil.yml@refs/heads/main",
63+
Some("nested@evil.yml"),
64+
),
65+
(
66+
"foo/bar/.github/workflows/nested.yml@evil.yml@refs/heads/main",
67+
Some("nested.yml@evil.yml"),
68+
),
69+
(
70+
"foo/bar/.github/workflows/extra@nested.yml@evil.yml@refs/heads/main",
71+
Some("extra@nested.yml@evil.yml"),
72+
),
73+
(
74+
"foo/bar/.github/workflows/extra.yml@nested.yml@evil.yml@refs/heads/main",
75+
Some("extra.yml@nested.yml@evil.yml"),
76+
),
77+
(
78+
"foo/bar/.github/workflows/basic.yml@refs/heads/misleading@branch.yml",
79+
Some("basic.yml"),
80+
),
81+
(
82+
"foo/bar/.github/workflows/basic.yml@refs/heads/bad@branch@twomatches.yml",
83+
Some("basic.yml"),
84+
),
85+
(
86+
"foo/bar/.github/workflows/foo.yml.yml@refs/heads/main",
87+
Some("foo.yml.yml"),
88+
),
89+
(
90+
"foo/bar/.github/workflows/foo.yml.foo.yml@refs/heads/main",
91+
Some("foo.yml.foo.yml"),
92+
),
93+
// Malformed workflow refs.
94+
(
95+
"foo/bar/.github/workflows/basic.wrongsuffix@refs/heads/main",
96+
None,
97+
),
98+
("foo/bar/.github/workflows/@refs/heads/main", None),
99+
("foo/bar/.github/workflows/nosuffix@refs/heads/main", None),
100+
("foo/bar/.github/workflows/.yml@refs/heads/main", None),
101+
("foo/bar/.github/workflows/.yaml@refs/heads/main", None),
102+
("foo/bar/.github/workflows/main.yml", None),
103+
];
104+
105+
for (input, expected) in test_cases {
106+
let result = super::extract_workflow_filename(input);
107+
assert_eq!(result, expected, "Input: {input}");
108+
}
109+
}
110+
}

0 commit comments

Comments
 (0)