Skip to content

Commit b84da76

Browse files
authored
chore(dsl)!: write to file in workflow builder (#1429)
Part of #1208. Moving to a more declarative approach, so that there's no need to call the function explicitly - in practice, one always needs to call it, unless doing something awkward.
1 parent fc066b1 commit b84da76

File tree

15 files changed

+332
-367
lines changed

15 files changed

+332
-367
lines changed

.github/workflows/end-to-end-tests.main.kts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import io.github.typesafegithub.workflows.dsl.JobBuilder
2424
import io.github.typesafegithub.workflows.dsl.expressions.Contexts
2525
import io.github.typesafegithub.workflows.dsl.expressions.expr
2626
import io.github.typesafegithub.workflows.dsl.workflow
27-
import io.github.typesafegithub.workflows.yaml.writeToFile
2827
import io.github.typesafegithub.workflows.updates.reportAvailableUpdates
2928
import java.time.Instant
3029

@@ -251,6 +250,4 @@ workflow(
251250
""".trimIndent(),
252251
)
253252
}
254-
}.also { workflow ->
255-
workflow.reportAvailableUpdates()
256-
}.writeToFile()
253+
}.reportAvailableUpdates()

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ build
99

1010
# Created in unit tests - easier and more readable to ignore it rather than adjust the test.
1111
/.github/workflows/.yaml
12+
.github/workflows/some_workflow.yaml
1213

1314
# Action bindings are generated by CI each time, and locally we should regenerate it as often as possible.
14-
/.github/workflows/generated
15+
/.github/workflows/generated

docs/user-guide/getting_started.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,9 @@ names with your own.
2323
--8<-- "GettingStartedSnippets.kt:getting-started-2"
2424
--8<-- "GettingStartedSnippets.kt:getting-started-3"
2525
```
26-
Explanation: first, we create a workflow with the DSL provided by this library. The reason it needs source
26+
This way we create a workflow with the DSL provided by this library. The reason it needs source
2727
file path is to be able to generate consistency checks, to ensure that both source and target files are in sync.
28-
You'll see it in a moment in the generated file. What's written to the `workflow` variable is an object of type
29-
`io.github.typesafegithub.workflows.domain.Workflow`, it's not a YAML yet. However, a call to `writeToFile()`
30-
extension function does the final piece of job.
28+
You'll see it in a moment in the generated file.
3129
4. Generate the YAML by calling the above script:
3230
```
3331
.github/workflows/hello_world_workflow.main.kts

github-workflows-kt/api/github-workflows-kt.api

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1899,9 +1899,10 @@ public final class io/github/typesafegithub/workflows/dsl/JobBuilder : io/github
18991899
}
19001900

19011901
public final class io/github/typesafegithub/workflows/dsl/WorkflowBuilder {
1902-
public fun <init> (Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/nio/file/Path;Ljava/lang/String;Lio/github/typesafegithub/workflows/domain/Concurrency;Ljava/lang/String;Ljava/util/Map;Lkotlin/jvm/functions/Function1;Ljava/util/List;Ljava/util/Map;Ljava/util/Map;)V
1903-
public synthetic fun <init> (Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/nio/file/Path;Ljava/lang/String;Lio/github/typesafegithub/workflows/domain/Concurrency;Ljava/lang/String;Ljava/util/Map;Lkotlin/jvm/functions/Function1;Ljava/util/List;Ljava/util/Map;Ljava/util/Map;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
1902+
public fun <init> (Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/nio/file/Path;Ljava/lang/String;Lio/github/typesafegithub/workflows/domain/Concurrency;Ljava/nio/file/Path;Ljava/lang/String;Ljava/util/Map;Lkotlin/jvm/functions/Function1;Ljava/util/List;Ljava/util/Map;Ljava/util/Map;)V
1903+
public synthetic fun <init> (Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/nio/file/Path;Ljava/lang/String;Lio/github/typesafegithub/workflows/domain/Concurrency;Ljava/nio/file/Path;Ljava/lang/String;Ljava/util/Map;Lkotlin/jvm/functions/Function1;Ljava/util/List;Ljava/util/Map;Ljava/util/Map;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
19041904
public final fun build ()Lio/github/typesafegithub/workflows/domain/Workflow;
1905+
public final fun getGitRootDir ()Ljava/nio/file/Path;
19051906
public final fun job ([Lkotlin/Unit;Ljava/lang/String;Ljava/lang/String;Lio/github/typesafegithub/workflows/domain/RunnerType;Ljava/util/List;Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;Ljava/lang/Integer;Lio/github/typesafegithub/workflows/domain/Concurrency;Lio/github/typesafegithub/workflows/domain/Container;Lio/github/typesafegithub/workflows/domain/Environment;Ljava/util/Map;Lio/github/typesafegithub/workflows/domain/JobOutputs;Lkotlin/jvm/functions/Function1;)Lio/github/typesafegithub/workflows/domain/Job;
19061907
public final fun job ([Lkotlin/Unit;Ljava/lang/String;Ljava/lang/String;Lio/github/typesafegithub/workflows/domain/RunnerType;Ljava/util/List;Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;Ljava/lang/Integer;Lio/github/typesafegithub/workflows/domain/Concurrency;Lio/github/typesafegithub/workflows/domain/Container;Lio/github/typesafegithub/workflows/domain/Environment;Ljava/util/Map;Lkotlin/jvm/functions/Function1;)Lio/github/typesafegithub/workflows/domain/Job;
19071908
public static synthetic fun job$default (Lio/github/typesafegithub/workflows/dsl/WorkflowBuilder;[Lkotlin/Unit;Ljava/lang/String;Ljava/lang/String;Lio/github/typesafegithub/workflows/domain/RunnerType;Ljava/util/List;Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;Ljava/lang/Integer;Lio/github/typesafegithub/workflows/domain/Concurrency;Lio/github/typesafegithub/workflows/domain/Container;Lio/github/typesafegithub/workflows/domain/Environment;Ljava/util/Map;Lio/github/typesafegithub/workflows/domain/JobOutputs;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lio/github/typesafegithub/workflows/domain/Job;
@@ -1910,8 +1911,8 @@ public final class io/github/typesafegithub/workflows/dsl/WorkflowBuilder {
19101911

19111912
public final class io/github/typesafegithub/workflows/dsl/WorkflowBuilderKt {
19121913
public static final fun toBuilder (Lio/github/typesafegithub/workflows/domain/Workflow;)Lio/github/typesafegithub/workflows/dsl/WorkflowBuilder;
1913-
public static final fun workflow ([Lkotlin/Unit;Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/nio/file/Path;Ljava/lang/String;Lio/github/typesafegithub/workflows/domain/Concurrency;Ljava/lang/String;Ljava/util/Map;Lkotlin/jvm/functions/Function1;Ljava/util/Map;Ljava/util/Map;Lkotlin/jvm/functions/Function1;)Lio/github/typesafegithub/workflows/domain/Workflow;
1914-
public static synthetic fun workflow$default ([Lkotlin/Unit;Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/nio/file/Path;Ljava/lang/String;Lio/github/typesafegithub/workflows/domain/Concurrency;Ljava/lang/String;Ljava/util/Map;Lkotlin/jvm/functions/Function1;Ljava/util/Map;Ljava/util/Map;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lio/github/typesafegithub/workflows/domain/Workflow;
1914+
public static final fun workflow ([Lkotlin/Unit;Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/nio/file/Path;Ljava/lang/String;Lio/github/typesafegithub/workflows/domain/Concurrency;Ljava/lang/String;Ljava/util/Map;Lkotlin/jvm/functions/Function1;Ljava/util/Map;ZLjava/nio/file/Path;Lio/github/typesafegithub/workflows/yaml/Preamble;Lkotlin/jvm/functions/Function1;Ljava/util/Map;Lkotlin/jvm/functions/Function1;)Lio/github/typesafegithub/workflows/domain/Workflow;
1915+
public static synthetic fun workflow$default ([Lkotlin/Unit;Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Ljava/nio/file/Path;Ljava/lang/String;Lio/github/typesafegithub/workflows/domain/Concurrency;Ljava/lang/String;Ljava/util/Map;Lkotlin/jvm/functions/Function1;Ljava/util/Map;ZLjava/nio/file/Path;Lio/github/typesafegithub/workflows/yaml/Preamble;Lkotlin/jvm/functions/Function1;Ljava/util/Map;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lio/github/typesafegithub/workflows/domain/Workflow;
19151916
}
19161917

19171918
public final class io/github/typesafegithub/workflows/dsl/expressions/Contexts : io/github/typesafegithub/workflows/dsl/expressions/contexts/FunctionsContext {
@@ -3147,11 +3148,6 @@ public final class io/github/typesafegithub/workflows/yaml/Preamble$WithOriginal
31473148
public fun <init> (Ljava/lang/String;)V
31483149
}
31493150

3150-
public final class io/github/typesafegithub/workflows/yaml/ToYamlKt {
3151-
public static final fun writeToFile (Lio/github/typesafegithub/workflows/domain/Workflow;ZLjava/nio/file/Path;Lio/github/typesafegithub/workflows/yaml/Preamble;Lkotlin/jvm/functions/Function1;)V
3152-
public static synthetic fun writeToFile$default (Lio/github/typesafegithub/workflows/domain/Workflow;ZLjava/nio/file/Path;Lio/github/typesafegithub/workflows/yaml/Preamble;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
3153-
}
3154-
31553151
public final class io/github/typesafegithub/workflows/yaml/TriggersToYamlKt {
31563152
public static final fun toMap (Lio/github/typesafegithub/workflows/domain/triggers/Trigger;)Ljava/util/Map;
31573153
public static final fun triggerName (Lio/github/typesafegithub/workflows/domain/triggers/Trigger;)Ljava/lang/String;

github-workflows-kt/src/main/kotlin/io/github/typesafegithub/workflows/dsl/JobBuilder.kt

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@ import io.github.typesafegithub.workflows.domain.Shell
1616
import io.github.typesafegithub.workflows.domain.actions.Action
1717
import io.github.typesafegithub.workflows.domain.contexts.Contexts
1818
import io.github.typesafegithub.workflows.dsl.expressions.expr
19+
import io.github.typesafegithub.workflows.internal.relativeToAbsolute
1920
import kotlinx.serialization.Contextual
20-
import kotlin.io.path.name
21+
import kotlin.io.path.invariantSeparatorsPathString
2122

2223
@Suppress("LongParameterList")
2324
@GithubActionsDsl
@@ -133,14 +134,15 @@ public class JobBuilder<OUTPUT : JobOutputs>(
133134
}
134135

135136
val id = "step-${job.steps.size}"
137+
val sourceFilePath =
138+
workflowBuilder.gitRootDir?.let {
139+
sourceFile.relativeToAbsolute(it).invariantSeparatorsPathString
140+
}
136141
val newStep =
137142
KotlinLogicStep(
138143
id = id,
139144
name = name,
140-
// Because of the current architecture, it's hard to make this command work properly if the sourceFile
141-
// isn't in .github/workflows directory. It's the most common use case, though, so for now this
142-
// simplified implementation is used.
143-
command = "GHWKT_RUN_STEP='${this.id}:$id' '.github/workflows/${sourceFile.name}'",
145+
command = "GHWKT_RUN_STEP='${this.id}:$id' '$sourceFilePath'",
144146
logic = logic,
145147
env = env + mapOf("GHWKT_GITHUB_CONTEXT_JSON" to "${'$'}{{ toJSON(github) }}"),
146148
condition =

github-workflows-kt/src/main/kotlin/io/github/typesafegithub/workflows/dsl/WorkflowBuilder.kt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,12 @@ import io.github.typesafegithub.workflows.domain.Permission
1010
import io.github.typesafegithub.workflows.domain.RunnerType
1111
import io.github.typesafegithub.workflows.domain.Workflow
1212
import io.github.typesafegithub.workflows.domain.triggers.Trigger
13+
import io.github.typesafegithub.workflows.shared.internal.findGitRoot
14+
import io.github.typesafegithub.workflows.yaml.Preamble
15+
import io.github.typesafegithub.workflows.yaml.writeToFile
1316
import kotlinx.serialization.Contextual
1417
import java.nio.file.Path
18+
import kotlin.io.path.absolute
1519

1620
@GithubActionsDsl
1721
@Suppress("LongParameterList", "FunctionParameterNaming", "ConstructorParameterNaming")
@@ -22,6 +26,7 @@ public class WorkflowBuilder(
2226
sourceFile: Path?,
2327
targetFileName: String?,
2428
concurrency: Concurrency? = null,
29+
public val gitRootDir: Path? = null,
2530
yamlConsistencyJobCondition: String? = null,
2631
yamlConsistencyJobEnv: Map<String, String> = mapOf(),
2732
yamlConsistencyJobAdditionalSteps: (JobBuilder<JobOutputs.EMPTY>.() -> Unit)? = null,
@@ -171,6 +176,10 @@ public fun workflow(
171176
yamlConsistencyJobEnv: Map<String, String> = mapOf(),
172177
yamlConsistencyJobAdditionalSteps: (JobBuilder<JobOutputs.EMPTY>.() -> Unit)? = null,
173178
permissions: Map<Permission, Mode>? = null,
179+
addConsistencyCheck: Boolean = sourceFile != null,
180+
gitRootDir: Path? = sourceFile?.absolute()?.findGitRoot(),
181+
preamble: Preamble? = null,
182+
getenv: (String) -> String? = { System.getenv(it) },
174183
_customArguments: Map<String, @Contextual Any> = mapOf(),
175184
block: WorkflowBuilder.() -> Unit,
176185
): Workflow {
@@ -187,6 +196,7 @@ public fun workflow(
187196
targetFileName = targetFileName,
188197
permissions = permissions,
189198
concurrency = concurrency,
199+
gitRootDir = gitRootDir,
190200
yamlConsistencyJobCondition = yamlConsistencyJobCondition,
191201
yamlConsistencyJobEnv = yamlConsistencyJobEnv,
192202
yamlConsistencyJobAdditionalSteps = yamlConsistencyJobAdditionalSteps,
@@ -200,6 +210,14 @@ public fun workflow(
200210
workflowBuilder.workflow.jobs.requireUniqueJobIds()
201211

202212
return workflowBuilder.build()
213+
.also {
214+
it.writeToFile(
215+
addConsistencyCheck = addConsistencyCheck,
216+
gitRootDir = gitRootDir,
217+
preamble = preamble,
218+
getenv = getenv,
219+
)
220+
}
203221
}
204222

205223
private fun List<Job<*>>.requireUniqueJobIds() {

github-workflows-kt/src/main/kotlin/io/github/typesafegithub/workflows/yaml/ToYaml.kt

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,11 @@ import io.github.typesafegithub.workflows.domain.contexts.Contexts
1111
import io.github.typesafegithub.workflows.domain.contexts.GithubContext
1212
import io.github.typesafegithub.workflows.dsl.toBuilder
1313
import io.github.typesafegithub.workflows.internal.relativeToAbsolute
14-
import io.github.typesafegithub.workflows.shared.internal.findGitRoot
1514
import io.github.typesafegithub.workflows.yaml.Preamble.Just
1615
import io.github.typesafegithub.workflows.yaml.Preamble.WithOriginalAfter
1716
import io.github.typesafegithub.workflows.yaml.Preamble.WithOriginalBefore
1817
import kotlinx.serialization.json.Json
1918
import java.nio.file.Path
20-
import kotlin.io.path.absolute
2119
import kotlin.io.path.invariantSeparatorsPathString
2220

2321
/**
@@ -34,11 +32,11 @@ import kotlin.io.path.invariantSeparatorsPathString
3432
* @param preamble Allows customizing the comment at the beginning of the generated YAML by either passing an extra
3533
* string, or replacing the whole preamble.
3634
*/
37-
public fun Workflow.writeToFile(
38-
addConsistencyCheck: Boolean = sourceFile != null,
39-
gitRootDir: Path? = sourceFile?.absolute()?.findGitRoot(),
40-
preamble: Preamble? = null,
41-
getenv: (String) -> String? = { System.getenv(it) },
35+
internal fun Workflow.writeToFile(
36+
addConsistencyCheck: Boolean,
37+
gitRootDir: Path?,
38+
preamble: Preamble?,
39+
getenv: (String) -> String?,
4240
) {
4341
val runStepEnvVar = getenv("GHWKT_RUN_STEP")
4442

0 commit comments

Comments
 (0)