Skip to content

Commit fac5434

Browse files
committed
Add support calling reusable workflow
1 parent 793c0c0 commit fac5434

File tree

4 files changed

+234
-9
lines changed

4 files changed

+234
-9
lines changed

src/main/scala/sbtghactions/GenerativePlugin.scala

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,12 @@ object GenerativePlugin extends AutoPlugin {
187187
s"concurrency: ${wrap(concurrency.group)}"
188188
}
189189

190+
def compileSecrets(secrets: Secrets): String =
191+
secrets match {
192+
case Secrets.Inherit => "secrets: inherit"
193+
case Secrets.Explicit(secretMap) => compileEnv(secretMap, "secrets")
194+
}
195+
190196
def compileEnvironment(environment: JobEnvironment): String =
191197
environment.url match {
192198
case Some(url) =>
@@ -485,22 +491,42 @@ ${indent(rendered.mkString("\n"), 1)}"""
485491

486492
val declareShell = job.oses.exists(_.contains("windows"))
487493

488-
val runsOn = if (job.runsOnExtraLabels.isEmpty)
489-
s"$${{ matrix.os }}"
490-
else
491-
job.runsOnExtraLabels.mkString(s"""[ "$${{ matrix.os }}", """, ", ", " ]" )
494+
val runsOn = job match {
495+
case jobWithSteps: WorkflowJob.Steps if jobWithSteps.runsOnExtraLabels.isEmpty =>
496+
"runs-on: ${{ matrix.os }}"
497+
case jobWithSteps: WorkflowJob.Steps =>
498+
jobWithSteps.runsOnExtraLabels.mkString(s"""runs-on: [ "$${{ matrix.os }}", """, ", ", " ]")
499+
case _ =>
500+
""
501+
}
492502

493503
val renderedFailFast = job.matrixFailFast.fold("")("\n fail-fast: " + _)
494504

505+
val renderedSteps = job match {
506+
case jobWithSteps: WorkflowJob.Steps =>
507+
"\nsteps:\n" +
508+
indent(jobWithSteps.steps.map(compileStep(_, sbt, jobWithSteps.sbtStepPreamble, declareShell = declareShell)).mkString("\n\n"), 1)
509+
case _ =>
510+
""
511+
}
512+
513+
val renderedUses = job match {
514+
case uses: WorkflowJob.Use =>
515+
val renderedSecrets =
516+
uses.secrets.map(compileSecrets).map("\n" + _).getOrElse("")
517+
518+
s"uses: ${uses.ref}${renderedSecrets}${renderParams(uses.params)}"
519+
case _ =>
520+
""
521+
}
522+
495523
val body = s"""name: ${wrap(job.name)}${renderedNeeds}${renderedCond}
496524
strategy:${renderedFailFast}
497525
matrix:
498526
os:${compileList(job.oses, 3)}
499527
scala:${compileList(job.scalas, 3)}
500528
java:${compileList(job.javas.map(_.render), 3)}${renderedMatrices}
501-
runs-on: ${runsOn}${renderedEnvironment}${renderedContainer}${renderedTimeout}${renderedPerm}${renderedEnv}${renderedConcurrency}
502-
steps:
503-
${indent(job.steps.map(compileStep(_, sbt, job.sbtStepPreamble, declareShell = declareShell)).mkString("\n\n"), 1)}"""
529+
${runsOn}${renderedEnvironment}${renderedContainer}${renderedTimeout}${renderedPerm}${renderedEnv}${renderedConcurrency}${renderedSteps}${renderedUses}"""
504530

505531
s"${job.id}:\n${indent(body, 1)}"
506532
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
* Copyright 2020-2021 Daniel Spiewak
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package sbtghactions
18+
19+
sealed trait Secrets extends Product with Serializable
20+
21+
object Secrets {
22+
case object Inherit extends Secrets
23+
case class Explicit(secrets: Map[String, String]) extends Secrets
24+
}

src/main/scala/sbtghactions/WorkflowJob.scala

Lines changed: 94 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,28 @@ package sbtghactions
1818

1919
import scala.concurrent.duration.FiniteDuration
2020

21-
final case class WorkflowJob(
21+
sealed abstract class WorkflowJob {
22+
def id: String
23+
def name: String
24+
def cond: Option[String]
25+
def permissions: Option[Permissions]
26+
def env: Map[String, String]
27+
def oses: List[String]
28+
def scalas: List[String]
29+
def javas: List[JavaSpec]
30+
def needs: List[String]
31+
def matrixFailFast: Option[Boolean]
32+
def matrixAdds: Map[String, List[String]]
33+
def matrixIncs: List[MatrixInclude]
34+
def matrixExcs: List[MatrixExclude]
35+
def container: Option[JobContainer]
36+
def environment: Option[JobEnvironment]
37+
def concurrency: Option[Concurrency]
38+
def timeout: Option[FiniteDuration]
39+
}
40+
41+
object WorkflowJob {
42+
def apply(
2243
id: String,
2344
name: String,
2445
steps: List[WorkflowStep],
@@ -38,4 +59,75 @@ final case class WorkflowJob(
3859
container: Option[JobContainer] = None,
3960
environment: Option[JobEnvironment] = None,
4061
concurrency: Option[Concurrency] = None,
41-
timeout: Option[FiniteDuration] = None)
62+
timeout: Option[FiniteDuration] = None
63+
): WorkflowJob =
64+
Steps(
65+
id,
66+
name,
67+
steps,
68+
sbtStepPreamble,
69+
cond,
70+
permissions,
71+
env,
72+
oses,
73+
scalas,
74+
javas,
75+
needs,
76+
matrixFailFast,
77+
matrixAdds,
78+
matrixIncs,
79+
matrixExcs,
80+
runsOnExtraLabels,
81+
container,
82+
environment,
83+
concurrency,
84+
timeout
85+
)
86+
87+
final case class Steps(
88+
id: String,
89+
name: String,
90+
steps: List[WorkflowStep],
91+
sbtStepPreamble: List[String] = List(),
92+
cond: Option[String] = None,
93+
permissions: Option[Permissions] = None,
94+
env: Map[String, String] = Map(),
95+
oses: List[String] = List("ubuntu-latest"),
96+
scalas: List[String] = List("2.13.10"),
97+
javas: List[JavaSpec] = List(JavaSpec.zulu("8")),
98+
needs: List[String] = List(),
99+
matrixFailFast: Option[Boolean] = None,
100+
matrixAdds: Map[String, List[String]] = Map(),
101+
matrixIncs: List[MatrixInclude] = List(),
102+
matrixExcs: List[MatrixExclude] = List(),
103+
runsOnExtraLabels: List[String] = List(),
104+
container: Option[JobContainer] = None,
105+
environment: Option[JobEnvironment] = None,
106+
concurrency: Option[Concurrency] = None,
107+
timeout: Option[FiniteDuration] = None
108+
) extends WorkflowJob
109+
110+
final case class Use(
111+
id: String,
112+
name: String,
113+
ref: String,
114+
params: Map[String, String] = Map.empty,
115+
secrets: Option[Secrets] = None,
116+
cond: Option[String] = None,
117+
permissions: Option[Permissions] = None,
118+
oses: List[String] = List("ubuntu-latest"),
119+
scalas: List[String] = List("2.13.10"),
120+
javas: List[JavaSpec] = List(JavaSpec.zulu("8")),
121+
needs: List[String] = List(),
122+
matrixFailFast: Option[Boolean] = None,
123+
matrixAdds: Map[String, List[String]] = Map(),
124+
matrixIncs: List[MatrixInclude] = List(),
125+
matrixExcs: List[MatrixExclude] = List(),
126+
concurrency: Option[Concurrency] = None,
127+
) extends WorkflowJob {
128+
override def env: Map[String, String] = Map.empty
129+
override def environment: Option[JobEnvironment] = None
130+
override def timeout: Option[FiniteDuration] = None
131+
override def container: Option[JobContainer] = None
132+
}
133+
}

src/test/scala/sbtghactions/GenerativePluginSpec.scala

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1092,6 +1092,89 @@ class GenerativePluginSpec extends Specification {
10921092
- name: Checkout current branch (fast)
10931093
uses: actions/checkout@v5"""
10941094
}
1095+
1096+
"compile a job which delegates to another via 'using'" in {
1097+
val results = compileJob(
1098+
WorkflowJob.Use(
1099+
"publish",
1100+
"Publish Release",
1101+
"./.github/workflows/dependant.yml"),
1102+
"csbt")
1103+
1104+
results mustEqual s"""publish:
1105+
name: Publish Release
1106+
strategy:
1107+
matrix:
1108+
os: [ubuntu-latest]
1109+
scala: [2.13.10]
1110+
java: [zulu@8]
1111+
uses: ./.github/workflows/dependant.yml"""
1112+
}
1113+
1114+
"compile a job which delegates to another via 'using', with parameters" in {
1115+
val results = compileJob(
1116+
WorkflowJob.Use(
1117+
"publish",
1118+
"Publish Release",
1119+
"sbt/sbt-github-actions/.github/workflows/dependant.yml@main",
1120+
Map("abc" -> "def")
1121+
),
1122+
"csbt")
1123+
1124+
results mustEqual s"""publish:
1125+
name: Publish Release
1126+
strategy:
1127+
matrix:
1128+
os: [ubuntu-latest]
1129+
scala: [2.13.10]
1130+
java: [zulu@8]
1131+
uses: sbt/sbt-github-actions/.github/workflows/dependant.yml@main
1132+
with:
1133+
abc: def"""
1134+
}
1135+
1136+
"compile a job which delegates to another via 'using', with inherited secrets" in {
1137+
val results = compileJob(
1138+
WorkflowJob.Use(
1139+
"publish",
1140+
"Publish Release",
1141+
"./.github/workflows/dependant.yml",
1142+
secrets = Some(Secrets.Inherit)
1143+
),
1144+
"csbt")
1145+
1146+
results mustEqual s"""publish:
1147+
name: Publish Release
1148+
strategy:
1149+
matrix:
1150+
os: [ubuntu-latest]
1151+
scala: [2.13.10]
1152+
java: [zulu@8]
1153+
uses: ./.github/workflows/dependant.yml
1154+
secrets: inherit"""
1155+
}
1156+
1157+
"compile a job which delegates to another via 'using', with explicit secrets" in {
1158+
val results = compileJob(
1159+
WorkflowJob.Use(
1160+
"publish",
1161+
"Publish Release",
1162+
"./.github/workflows/dependant.yml",
1163+
secrets = Some(Secrets.Explicit(Map("abc" -> "def")))
1164+
),
1165+
"csbt")
1166+
1167+
results mustEqual s"""publish:
1168+
name: Publish Release
1169+
strategy:
1170+
matrix:
1171+
os: [ubuntu-latest]
1172+
scala: [2.13.10]
1173+
java: [zulu@8]
1174+
uses: ./.github/workflows/dependant.yml
1175+
secrets:
1176+
abc: def"""
1177+
}
10951178
}
10961179

10971180
"predicate compilation" >> {

0 commit comments

Comments
 (0)