diff --git a/docs/gha.md b/docs/gha.md index 92bcad19..6de7671c 100644 --- a/docs/gha.md +++ b/docs/gha.md @@ -71,10 +71,11 @@ Any and all settings which affect the behavior of the generative plugin should b - `githubWorkflowUseSbtThinClient` : `Boolean` – Controls whether or not the `--client` option will be added to `sbt` command invocations, accelerating build times (default: `true` for sbt ≥ 1.4, `false` otherwise) - `githubWorkflowIncludeClean` : `Boolean` – Controls whether to include the clean.yml file (default: `true`) - `githubWorkflowDependencyPatterns` : `Seq[String]` – A list of file globs which dictate where dependency information is stored. This is conventionally just `**/*.sbt` and `project/build.properties`. If you store dependency information in some *other* file (for example, `project/Versions.scala`), then you should add a glob which matches that file in this setting. This is used for determining the appropriate cache keys for the Ivy and Coursier caches. -- `githubWorkflowTargetBranches` : `Seq[String]` – A list of globs which will match branches and tags for `push` and `pull-request` event types to trigger the **ci.yml** workflow. Defaults to `[*]`. -- `githubWorkflowTargetTags` : `Seq[String]` – A list of globs which will match tags and tags for `push` event types to trigger the **ci.yml** workflow. Defaults to `[]`. -- `githubWorkflowTargetPaths` : `Paths` – Paths which will match modified files for `push` and `pull_request` event types to trigger the **ci.yml** workflow. May be `Paths.None`, `Paths.Include(patterns)`, or `Paths.Ignore(patterns)`. `Paths.Include` may include negative patterns. Defaults to `Paths.None`. -- `githubWorkflowPREventTypes` : `Seq[PREventType]` – A list of event types which will be used to determine which Pull Request events trigger the **ci.yml** workflow. This follows GitHub's defaults: `[opened, synchronize, reopened]`. +- `githubWorkflowTriggers`: WorkflowTriggers – Specifify the push, pull_request, and merge_group triggers in the on: section of the ci.yml workflow. By default this is derived from githubWorkflowTargetBranches, githubWorkflowTargetTags, githubWorkflowTargetPaths, and githubWorkflowPREventTypes. Setting it explicitly takes precedence, and those four keys are then ignored. This is the only way to express triggers they can't, such as a merge_group trigger (for GitHub merge queues) or branches-ignore/paths-ignore filters. Constructed via WorkflowTriggers, PushTrigger, PullRequestTrigger, and MergeGroupTrigger (with MergeGroupEventType for merge-group activity types). +- `githubWorkflowTargetBranches` : `Seq[String]` – A list of globs which will match branches and tags for `push` and `pull-request` event types to trigger the **ci.yml** workflow. Defaults to `[*]`. (Ignored if githubWorkflowTriggers is set directly.) +- `githubWorkflowTargetTags` : `Seq[String]` – A list of globs which will match tags and tags for `push` event types to trigger the **ci.yml** workflow. Defaults to `[]`. (Ignored if githubWorkflowTriggers is set directly.) +- `githubWorkflowTargetPaths` : `Paths` – Paths which will match modified files for `push` and `pull_request` event types to trigger the **ci.yml** workflow. May be `Paths.None`, `Paths.Include(patterns)`, or `Paths.Ignore(patterns)`. `Paths.Include` may include negative patterns. Defaults to `Paths.None`. (Ignored if githubWorkflowTriggers is set directly.) +- `githubWorkflowPREventTypes` : `Seq[PREventType]` – A list of event types which will be used to determine which Pull Request events trigger the **ci.yml** workflow. This follows GitHub's defaults: `[opened, synchronize, reopened]`. (Ignored if githubWorkflowTriggers is set directly.) - `githubWorkflowArtifactUpload` : `Boolean` – Controls whether or not to upload target directories in the event that multiple jobs are running sequentially. Can be set on a per-project basis. Defaults to `true`. - `githubWorkflowJobSetup` : `Seq[WorkflowStep]` – The automatically-generated checkout, setup, and cache steps which are common to all jobs which touch the build (default: autogenerated) - `githubWorkflowEnv` : `Map[String, String]` – An environment which is global to the entire **ci.yml** workflow. Defaults to `Map("GITHUB_TOKEN" -> "${{ secrets.GITHUB_TOKEN }}")` since it's so commonly needed. diff --git a/github-actions/src/main/scala/org/typelevel/sbt/gha/GenerativeKeys.scala b/github-actions/src/main/scala/org/typelevel/sbt/gha/GenerativeKeys.scala index 3ddcfc3d..a8fd95dc 100644 --- a/github-actions/src/main/scala/org/typelevel/sbt/gha/GenerativeKeys.scala +++ b/github-actions/src/main/scala/org/typelevel/sbt/gha/GenerativeKeys.scala @@ -91,6 +91,9 @@ trait GenerativeKeys { lazy val githubWorkflowDependencyPatterns = settingKey[Seq[String]]( "A list of file globes within the project which affect dependency information (default: [**/*.sbt, project/build.properties])") + lazy val githubWorkflowTriggers = settingKey[WorkflowTriggers]( + "The triggers to use for the workflow. The default is derived from githubWorkflowTargetBranches, githubWorkflowTargetTags, githubWorkflowTargetPaths, githubWorkflowPREventTypes. " + + "Setting this directly means the individual keys (githubWorkflowTargetBranches, etc.) are ignored.") lazy val githubWorkflowTargetBranches = settingKey[Seq[String]]( "A list of branch patterns on which to trigger push and PR builds (default: [*])") lazy val githubWorkflowTargetTags = settingKey[Seq[String]]( diff --git a/github-actions/src/main/scala/org/typelevel/sbt/gha/GenerativePlugin.scala b/github-actions/src/main/scala/org/typelevel/sbt/gha/GenerativePlugin.scala index 0ef9ff3d..7b67e0e7 100644 --- a/github-actions/src/main/scala/org/typelevel/sbt/gha/GenerativePlugin.scala +++ b/github-actions/src/main/scala/org/typelevel/sbt/gha/GenerativePlugin.scala @@ -31,6 +31,21 @@ object GenerativePlugin extends AutoPlugin { type WorkflowJob = org.typelevel.sbt.gha.WorkflowJob val WorkflowJob = org.typelevel.sbt.gha.WorkflowJob + type WorkflowTriggers = org.typelevel.sbt.gha.WorkflowTriggers + val WorkflowTriggers = org.typelevel.sbt.gha.WorkflowTriggers + + type PushTrigger = org.typelevel.sbt.gha.PushTrigger + val PushTrigger = org.typelevel.sbt.gha.PushTrigger + + type PullRequestTrigger = org.typelevel.sbt.gha.PullRequestTrigger + val PullRequestTrigger = org.typelevel.sbt.gha.PullRequestTrigger + + type MergeGroupTrigger = org.typelevel.sbt.gha.MergeGroupTrigger + val MergeGroupTrigger = org.typelevel.sbt.gha.MergeGroupTrigger + + type MergeGroupEventType = org.typelevel.sbt.gha.MergeGroupEventType + val MergeGroupEventType = org.typelevel.sbt.gha.MergeGroupEventType + type Concurrency = org.typelevel.sbt.gha.Concurrency val Concurrency = org.typelevel.sbt.gha.Concurrency @@ -147,6 +162,52 @@ object GenerativePlugin extends AutoPlugin { } } + def compileMergeGroupEventType(tpe: MergeGroupEventType): String = + tpe match { + case MergeGroupEventType.ChecksRequested => "checks_requested" + } + + private def whenNonEmpty(items: List[String])(f: List[String] => String): String = + if (items.isEmpty) "" else f(items) + + private def compilePushOrPullRequestTrigger(trigger: PushOrPullRequestTrigger): String = { + val branches = whenNonEmpty(trigger.branches)(b => s"\n branches:${compileList(b, 3)}") + val branchesIgnore = + whenNonEmpty(trigger.branchesIgnore)(b => s"\n branches-ignore:${compileList(b, 3)}") + val paths = whenNonEmpty(trigger.paths)(p => s"\n paths:${compileList(p, 3)}") + val pathsIgnore = + whenNonEmpty(trigger.pathsIgnore)(p => s"\n paths-ignore:${compileList(p, 3)}") + s"$branches$branchesIgnore$paths$pathsIgnore" + } + + def compilePullRequestTrigger(pull: PullRequestTrigger): String = { + val base = compilePushOrPullRequestTrigger(pull) + val types = + whenNonEmpty(pull.types.map(compilePREventType))(t => s"\n types:${compileList(t, 3)}") + s"$base$types" + } + + def compilePushTrigger(push: PushTrigger): String = { + val base = compilePushOrPullRequestTrigger(push) + val tags = whenNonEmpty(push.tags)(t => s"\n tags:${compileList(t, 3)}") + val tagsIgnore = + whenNonEmpty(push.tagsIgnore)(t => s"\n tags-ignore:${compileList(t, 3)}") + s"$base$tags$tagsIgnore" + } + + def compileMergeGroupTrigger(merge: MergeGroupTrigger): String = + whenNonEmpty(merge.types.map(compileMergeGroupEventType))(t => + s"\n types:${compileList(t, 3)}") + + def compileWorkflowTrigger(trigger: WorkflowTriggers): String = { + val pullRequest = + trigger.pullRequest.fold("")(t => s"\n pull_request:${compilePullRequestTrigger(t)}") + val push = trigger.push.fold("")(t => s"\n push:${compilePushTrigger(t)}") + val mergeGroup = + trigger.mergeGroup.fold("")(t => s"\n merge_group:${compileMergeGroupTrigger(t)}") + s"on:$pullRequest$push$mergeGroup" + } + def compileRef(ref: Ref): String = ref match { case Ref.Branch(name) => s"refs/heads/$name" case Ref.Tag(name) => s"refs/tags/$name" @@ -590,6 +651,23 @@ ${indent(job.steps.map(compileStep(_, sbt, job.sbtStepPreamble, declareShell = d env: Map[String, String], concurrency: Option[Concurrency], jobs: List[WorkflowJob], + sbt: String): String = + compileWorkflow( + name, + createTriggers(branches, tags, paths, prEventTypes), + permissions, + env, + concurrency, + jobs, + sbt) + + def compileWorkflow( + name: String, + triggers: WorkflowTriggers, + permissions: Option[Permissions], + env: Map[String, String], + concurrency: Option[Concurrency], + jobs: List[WorkflowJob], sbt: String): String = { val renderedPermissionsPre = compilePermissions(permissions) @@ -608,29 +686,6 @@ ${indent(job.steps.map(compileStep(_, sbt, job.sbtStepPreamble, declareShell = d val renderedConcurrency = concurrency.map(compileConcurrency).map("\n" + _ + "\n\n").getOrElse("") - val renderedTypesPre = prEventTypes.map(compilePREventType).mkString("[", ", ", "]") - val renderedTypes = - if (prEventTypes.sortBy(_.toString) == PREventType.Defaults) - "" - else - "\n" + indent("types: " + renderedTypesPre, 2) - - val renderedTags = - if (tags.isEmpty) - "" - else - s""" - tags: [${tags.map(wrap).mkString(", ")}]""" - - val renderedPaths = paths match { - case Paths.None => - "" - case Paths.Include(paths) => - "\n" + indent(s"""paths: [${paths.map(wrap).mkString(", ")}]""", 2) - case Paths.Ignore(paths) => - "\n" + indent(s"""paths-ignore: [${paths.map(wrap).mkString(", ")}]""", 2) - } - s"""# This file was automatically generated by sbt-github-actions using the # githubWorkflowGenerate task. You should add and commit this file to # your git repository. It goes without saying that you shouldn't edit @@ -640,17 +695,47 @@ ${indent(job.steps.map(compileStep(_, sbt, job.sbtStepPreamble, declareShell = d name: ${wrap(name)} -on: - pull_request: - branches: [${branches.map(wrap).mkString(", ")}]$renderedTypes$renderedPaths - push: - branches: [${branches.map(wrap).mkString(", ")}]$renderedTags$renderedPaths +${compileWorkflowTrigger(triggers)} ${renderedPerm}${renderedEnv}${renderedConcurrency}jobs: ${indent(jobs.map(compileJob(_, sbt)).mkString("\n\n"), 1)} """ } + private def createTriggers( + branches: List[String], + tags: List[String], + paths: Paths, + prEventTypes: List[PREventType]): WorkflowTriggers = { + val (pathsInclude, pathsIgnore) = paths match { + case Paths.Include(ps) => (ps, Nil) + case Paths.Ignore(ps) => (Nil, ps) + case Paths.None => (Nil, Nil) + } + + val types = { + if (prEventTypes.sortBy(_.toString) == PREventType.Defaults) Nil + else prEventTypes + } + + WorkflowTriggers( + push = Some( + PushTrigger( + branches = branches, + tags = tags, + paths = pathsInclude, + pathsIgnore = pathsIgnore + )), + pullRequest = Some( + PullRequestTrigger( + branches = branches, + types = types, + paths = pathsInclude, + pathsIgnore = pathsIgnore + )) + ) + } + val settingDefaults = Seq( githubWorkflowSbtCommand := "sbt", githubWorkflowIncludeClean := true, @@ -676,6 +761,13 @@ ${indent(jobs.map(compileJob(_, sbt)).mkString("\n\n"), 1)} githubWorkflowPublishPostamble := Seq(), githubWorkflowPublish := Seq( WorkflowStep.Sbt(List("+publish"), name = Some("Publish project"))), + + githubWorkflowTriggers := createTriggers( + githubWorkflowTargetBranches.value.toList, + githubWorkflowTargetTags.value.toList, + githubWorkflowTargetPaths.value, + githubWorkflowPREventTypes.value.toList + ), githubWorkflowPublishTargetBranches := Seq(RefPredicate.Equals(Ref.Branch("main"))), githubWorkflowPublishCond := None, githubWorkflowPublishTimeoutMinutes := None, @@ -914,10 +1006,7 @@ ${indent(jobs.map(compileJob(_, sbt)).mkString("\n\n"), 1)} private val generateCiContents = Def task { compileWorkflow( "Continuous Integration", - githubWorkflowTargetBranches.value.toList, - githubWorkflowTargetTags.value.toList, - githubWorkflowTargetPaths.value, - githubWorkflowPREventTypes.value.toList, + githubWorkflowTriggers.value, githubWorkflowPermissions.value, githubWorkflowEnv.value, githubWorkflowConcurrency.value, diff --git a/github-actions/src/main/scala/org/typelevel/sbt/gha/MergeGroupEventType.scala b/github-actions/src/main/scala/org/typelevel/sbt/gha/MergeGroupEventType.scala new file mode 100644 index 00000000..37d625fa --- /dev/null +++ b/github-actions/src/main/scala/org/typelevel/sbt/gha/MergeGroupEventType.scala @@ -0,0 +1,23 @@ +/* + * Copyright 2022 Typelevel + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.typelevel.sbt.gha + +sealed abstract class MergeGroupEventType + +object MergeGroupEventType { + case object ChecksRequested extends MergeGroupEventType +} diff --git a/github-actions/src/main/scala/org/typelevel/sbt/gha/MergeGroupTrigger.scala b/github-actions/src/main/scala/org/typelevel/sbt/gha/MergeGroupTrigger.scala new file mode 100644 index 00000000..55f8a817 --- /dev/null +++ b/github-actions/src/main/scala/org/typelevel/sbt/gha/MergeGroupTrigger.scala @@ -0,0 +1,35 @@ +/* + * Copyright 2022 Typelevel + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.typelevel.sbt.gha + +sealed abstract class MergeGroupTrigger { + def types: List[MergeGroupEventType] + + def withTypes(types: List[MergeGroupEventType]): MergeGroupTrigger +} + +object MergeGroupTrigger { + def apply(types: List[MergeGroupEventType] = Nil): MergeGroupTrigger = + Impl(types) + + private final case class Impl(types: List[MergeGroupEventType]) extends MergeGroupTrigger { + override def withTypes(types: List[MergeGroupEventType]): MergeGroupTrigger = + copy(types = types) + + override def productPrefix = "MergeGroupTrigger" + } +} diff --git a/github-actions/src/main/scala/org/typelevel/sbt/gha/PullRequestTrigger.scala b/github-actions/src/main/scala/org/typelevel/sbt/gha/PullRequestTrigger.scala new file mode 100644 index 00000000..2e9b9d58 --- /dev/null +++ b/github-actions/src/main/scala/org/typelevel/sbt/gha/PullRequestTrigger.scala @@ -0,0 +1,55 @@ +/* + * Copyright 2022 Typelevel + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.typelevel.sbt.gha + +sealed abstract class PullRequestTrigger extends PushOrPullRequestTrigger { + def types: List[PREventType] + + def withTypes(types: List[PREventType]): PullRequestTrigger +} + +object PullRequestTrigger { + def apply( + branches: List[String] = Nil, + branchesIgnore: List[String] = Nil, + paths: List[String] = Nil, + pathsIgnore: List[String] = Nil, + types: List[PREventType] = Nil + ): PullRequestTrigger = + Impl(branches, branchesIgnore, paths, pathsIgnore, types) + + private final case class Impl( + branches: List[String], + branchesIgnore: List[String], + paths: List[String], + pathsIgnore: List[String], + types: List[PREventType]) + extends PullRequestTrigger { + + override def withBranches(branches: List[String]): PullRequestTrigger = + copy(branches = branches) + override def withBranchesIgnore(branchesIgnore: List[String]): PullRequestTrigger = + copy(branchesIgnore = branchesIgnore) + override def withPaths(paths: List[String]): PullRequestTrigger = copy(paths = paths) + override def withPathsIgnore(pathsIgnore: List[String]): PullRequestTrigger = + copy(pathsIgnore = pathsIgnore) + override def withTypes(types: List[PREventType]): PullRequestTrigger = + copy(types = types) + + override def productPrefix = "PullRequestTrigger" + } +} diff --git a/github-actions/src/main/scala/org/typelevel/sbt/gha/PushOrPullRequestTrigger.scala b/github-actions/src/main/scala/org/typelevel/sbt/gha/PushOrPullRequestTrigger.scala new file mode 100644 index 00000000..a1ca7e56 --- /dev/null +++ b/github-actions/src/main/scala/org/typelevel/sbt/gha/PushOrPullRequestTrigger.scala @@ -0,0 +1,29 @@ +/* + * Copyright 2022 Typelevel + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.typelevel.sbt.gha + +trait PushOrPullRequestTrigger { + def branches: List[String] + def branchesIgnore: List[String] + def paths: List[String] + def pathsIgnore: List[String] + + def withBranches(branches: List[String]): PushOrPullRequestTrigger + def withBranchesIgnore(branchesIgnore: List[String]): PushOrPullRequestTrigger + def withPaths(paths: List[String]): PushOrPullRequestTrigger + def withPathsIgnore(pathsIgnore: List[String]): PushOrPullRequestTrigger +} diff --git a/github-actions/src/main/scala/org/typelevel/sbt/gha/PushTrigger.scala b/github-actions/src/main/scala/org/typelevel/sbt/gha/PushTrigger.scala new file mode 100644 index 00000000..3d6233fc --- /dev/null +++ b/github-actions/src/main/scala/org/typelevel/sbt/gha/PushTrigger.scala @@ -0,0 +1,58 @@ +/* + * Copyright 2022 Typelevel + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.typelevel.sbt.gha + +sealed abstract class PushTrigger extends PushOrPullRequestTrigger { + def tags: List[String] + def tagsIgnore: List[String] + + def withTags(tags: List[String]): PushTrigger + def withTagsIgnore(tagsIgnore: List[String]): PushTrigger +} + +object PushTrigger { + def apply( + branches: List[String] = Nil, + branchesIgnore: List[String] = Nil, + tags: List[String] = Nil, + tagsIgnore: List[String] = Nil, + paths: List[String] = Nil, + pathsIgnore: List[String] = Nil): PushTrigger = + Impl(branches, branchesIgnore, tags, tagsIgnore, paths, pathsIgnore) + + private final case class Impl( + branches: List[String], + branchesIgnore: List[String], + tags: List[String], + tagsIgnore: List[String], + paths: List[String], + pathsIgnore: List[String]) + extends PushTrigger { + + override def withBranches(branches: List[String]): PushTrigger = copy(branches = branches) + override def withBranchesIgnore(branchesIgnore: List[String]): PushTrigger = + copy(branchesIgnore = branchesIgnore) + override def withTags(tags: List[String]): PushTrigger = copy(tags = tags) + override def withTagsIgnore(tagsIgnore: List[String]): PushTrigger = + copy(tagsIgnore = tagsIgnore) + override def withPaths(paths: List[String]): PushTrigger = copy(paths = paths) + override def withPathsIgnore(pathsIgnore: List[String]): PushTrigger = + copy(pathsIgnore = pathsIgnore) + + override def productPrefix = "PushTrigger" + } +} diff --git a/github-actions/src/main/scala/org/typelevel/sbt/gha/WorkflowTriggers.scala b/github-actions/src/main/scala/org/typelevel/sbt/gha/WorkflowTriggers.scala new file mode 100644 index 00000000..f747f109 --- /dev/null +++ b/github-actions/src/main/scala/org/typelevel/sbt/gha/WorkflowTriggers.scala @@ -0,0 +1,50 @@ +/* + * Copyright 2022 Typelevel + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.typelevel.sbt.gha + +sealed abstract class WorkflowTriggers { + def push: Option[PushTrigger] + def pullRequest: Option[PullRequestTrigger] + def mergeGroup: Option[MergeGroupTrigger] + + def withPush(push: Option[PushTrigger]): WorkflowTriggers + def withPullRequest(pullRequest: Option[PullRequestTrigger]): WorkflowTriggers + def withMergeGroup(mergeGroup: Option[MergeGroupTrigger]): WorkflowTriggers +} + +object WorkflowTriggers { + def apply( + push: Option[PushTrigger] = None, + pullRequest: Option[PullRequestTrigger] = None, + mergeGroup: Option[MergeGroupTrigger] = None): WorkflowTriggers = + Impl(push, pullRequest, mergeGroup) + + private final case class Impl( + push: Option[PushTrigger], + pullRequest: Option[PullRequestTrigger], + mergeGroup: Option[MergeGroupTrigger]) + extends WorkflowTriggers { + + override def withPush(push: Option[PushTrigger]): WorkflowTriggers = copy(push = push) + override def withPullRequest(pullRequest: Option[PullRequestTrigger]): WorkflowTriggers = + copy(pullRequest = pullRequest) + override def withMergeGroup(mergeGroup: Option[MergeGroupTrigger]): WorkflowTriggers = + copy(mergeGroup = mergeGroup) + + override def productPrefix = "WorkflowTriggers" + } +}