-
Notifications
You must be signed in to change notification settings - Fork 161
Expand file tree
/
Copy pathclassify-changes.sc
More file actions
executable file
·80 lines (66 loc) · 3.14 KB
/
Copy pathclassify-changes.sc
File metadata and controls
executable file
·80 lines (66 loc) · 3.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#!/usr/bin/env -S scala-cli shebang
//> using scala 3
//> using toolkit default
//> using options -Werror -Wunused:all
//> using file ./pr-classify-lib/Env.scala
//> using file ./pr-classify-lib/EnvNames.scala
//> using file ./pr-classify-lib/Category.scala
//> using file ./pr-classify-lib/KeyValueFile.scala
//> using file ./pr-classify-lib/GitHubOutput.scala
// Classifies changed files into categories for CI job filtering.
// Inputs (env vars):
// EVENT_NAME - GitHub event name (pull_request, push, ...).
// BASE_REF - Base ref of the PR (used to compute the diff).
// CHANGED_FILES_OVERRIDE - Optional newline-separated list of changed files.
// When set, overrides the git-diff-based detection.
// CLASSIFY_OUTPUT_FILE - Optional path of a KEY=VALUE file to also write
// category results into (in addition to $GITHUB_OUTPUT).
// Outputs:
// - `${category}=true|false` to $GITHUB_OUTPUT for every category,
// - a Markdown summary table to $GITHUB_STEP_SUMMARY,
// - and the same KEY=VALUE pairs to $CLASSIFY_OUTPUT_FILE when set.
import prclassify.*
enum ChangeSet:
case All
case Specific(files: Seq[String])
def splitLines(s: String): Seq[String] =
s.linesIterator.map(_.trim).filter(_.nonEmpty).toIndexedSeq
val eventName = Env.opt(EnvNames.EventName).getOrElse("")
val changeSet: ChangeSet =
if eventName != "pull_request" then
println(s"Non-PR event ($eventName), setting all categories to true")
ChangeSet.All
else
Env.opt(EnvNames.ChangedFilesOverride) match
case Some(list) =>
ChangeSet.Specific(splitLines(list))
case None =>
val baseRef = Env.required(EnvNames.BaseRef)
val result = os.proc("git", "diff", "--name-only", s"origin/$baseRef...HEAD")
.call(check = false, mergeErrIntoOut = false, stderr = os.Inherit)
if result.exitCode != 0 then
System.err.println("::warning::Failed to compute diff, running all jobs")
println("Diff computation failed, setting all categories to true")
ChangeSet.All
else ChangeSet.Specific(splitLines(result.out.text()))
val activeCategories: Set[Category] = changeSet match
case ChangeSet.All => Category.values.toSet
case ChangeSet.Specific(files) => files.iterator.flatMap(Category.forPath).toSet
println("Change categories:")
Category.ordered.foreach(c => println(s" ${c.key}=${activeCategories.contains(c)}"))
val entries: Seq[(String, String)] =
Category.ordered.map(c => c.key -> activeCategories.contains(c).toString)
entries.foreach((k, v) => GitHubOutput.writeScalar(k, v))
Env.opt(EnvNames.ClassifyOutputFile).foreach: path =>
KeyValueFile.appendAll(Env.toAbsolutePath(path), entries)
val categoryRows = Category.ordered
.map(c => s"| ${c.key} | ${activeCategories.contains(c)} |")
.mkString("\n")
// categoryRows lines start with `|` (stripMargin's margin marker), so
// concatenate them after the stripped template instead of interpolating.
GitHubOutput.writeSummary(
s"""## Change categories
|| Category | Changed |
||----------|---------|
|""".stripMargin + categoryRows
)