Public hook for appending commands to the "Check headers and formatting" lint step

Open
#888 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
3/5
Estimated time
1-2 days
Newbie friendliness
68/100
Issue type
Feature
Clarity
Clearly specified
Activity status
Quiet
Tech stack
scala

Research direction

Start at the githubWorkflowBuild rendering and the WorkflowStep.Sbt command construction described in the issue. Add the public tlCiLintCommands setting so its values are appended to the existing "Check headers and formatting" commands, then verify that += additions compose and remain in the generated Test job.

Written by the indexing model from the issue text.

Description

Problem

sbt-typelevel's generated Test job emits a step named "Check headers and formatting" that runs sbt commands like:

sbt '++ ${{ matrix.scala }}' headerCheckAll scalafmtCheckAll 'project /' scalafmtSbtCheck

Plugins and projects that contribute additional lint-style checks (custom formatters, schema validators, license linters, etc.) want to fold their check into this same step so it runs alongside the existing ones — same matrix cell, same conditions, same "lint failures show up here" semantics. There's no first-class way to do that today; the only option is a fragile rewrite of githubWorkflowBuild:

ThisBuild / githubWorkflowBuild ~= {
  _.map {
    case step: WorkflowStep.Sbt if step.name == Some("Check headers and formatting") =>
      step.withCommands(step.commands :+ "myLintCheckAll")
    case other => other
  }
}

This is nine lines per plugin, repeats the magic step-name string at every call site, and breaks if upstream renames the step or splits it. It also doesn't compose: two plugins both rewriting githubWorkflowBuild need to be careful about order and not stomping each other.

Proposed shape

A public setting that's just a list of extra commands appended into the existing lint step:

val tlCiLintCommands = settingKey[Seq[String]](
  "Additional sbt commands appended to the 'Check headers and formatting' step"
)

// existing default rendering becomes something like:
WorkflowStep.Sbt(
  List(
    s"$$ $${{ matrix.scala }}",
    "headerCheckAll",
    "scalafmtCheckAll",
    "project /",
    "scalafmtSbtCheck",
  ) ++ tlCiLintCommands.value,
  name = Some("Check headers and formatting"),
  cond = ...,
)

User code becomes one line:

ThisBuild / tlCiLintCommands += "smithyFmtCheckAll"

…and plugins can opt projects in by default:

override def projectSettings = Seq(
  tlCiLintCommands += "smithyFmtCheckAll",
)

+='d sequences compose naturally across plugins and project settings, so there's no ordering footgun.

Why it's worth doing

  • Removes a copy-paste recipe from documentation. We currently tell SmithyFormatPlugin users (in polyvariant/smithy-trait-codegen-scala) to write the nine-line githubWorkflowBuild ~= { … } snippet by hand — every reader has to understand step matching, WorkflowStep.Sbt, and withCommands just to bolt one task onto CI.
  • Plays nicely with autoplugins. A plugin that wants to opt projects into a check on CI can do so transparently via projectSettings, with users' explicit additions composing on top.
  • The current pattern is brittle to upstream changes (step name, step splitting) — a named setting decouples user code from the rendering layout.

Happy to send a PR if the shape lands.

Dominant language
Scala
Stars
185
Forks
62
PR merge metrics
No merged PRs in 30d

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from typelevel/sbt-typelevel

All issues in typelevel/sbt-typelevel

Similar issues

More Scala issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.