diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c0e8e48..54e3c39 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,6 +7,9 @@ name: CI tags: - v[0-9]+.[0-9]+.[0-9]+ pull_request: null +concurrency: + group: CI-${{ github.ref }} + cancel-in-progress: ${{ !startsWith(github.ref, 'refs/tags/') }} jobs: verify-gate: name: verify-gate @@ -43,6 +46,7 @@ jobs: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: "0" + fetch-tags: "true" - name: Setup JDK 25 uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5.6.0 with: @@ -51,6 +55,32 @@ jobs: - uses: sbt/setup-sbt@6444f4c8111de4b9059c3975def104b03cfaa5f0 # v1.5.2 with: disk-cache: "false" + - name: Resolve cache epoch + id: cache-epoch + run: | + set -euo pipefail + tag_match='v*' + if git remote get-url origin >/dev/null 2>&1; then + remote_count=$(git ls-remote --tags --refs origin "$tag_match" 2>/dev/null | wc -l | tr -d ' ') + local_count=$(git tag -l "$tag_match" | wc -l | tr -d ' ') + if [ "$remote_count" -gt 0 ] && [ "$local_count" -lt "$remote_count" ]; then + echo "::warning title=zipx cache epoch::Local tags ($local_count) fewer than origin ($remote_count). Epoch may be stale; checkout must use fetch-depth: 0 and fetch-tags: true." + fi + fi + if [[ "${GITHUB_REF:-}" == refs/tags/v* ]]; then + release="${GITHUB_REF#refs/tags/v}" + epoch="$release" + elif tag=$(git describe --tags --abbrev=0 --match "$tag_match" 2>/dev/null); then + release="${tag#v}" + epoch="${release}-ci" + else + echo "::warning title=zipx cache epoch::No tags matching '$tag_match' found; using epoch 0.0.0." + release="0.0.0" + epoch="0.0.0" + fi + echo "epoch=$epoch" >> "$GITHUB_OUTPUT" + echo "release=$release" >> "$GITHUB_OUTPUT" + - name: Cache sbt uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: @@ -59,11 +89,11 @@ jobs: ~/.cache/sbt ~/.cache/coursier target - key: ubuntu-latest-jdk25-sbt-0.0.0-ci-${{ github.run_id }}-test + key: ubuntu-latest-jdk25-sbt-${{ steps.cache-epoch.outputs.epoch }}-${{ github.run_id }}-test restore-keys: | - ubuntu-latest-jdk25-sbt-0.0.0-ci-${{ github.run_id }}- - ubuntu-latest-jdk25-sbt-0.0.0-ci- - ubuntu-latest-jdk25-sbt-0.0.0- + ubuntu-latest-jdk25-sbt-${{ steps.cache-epoch.outputs.epoch }}-${{ github.run_id }}- + ubuntu-latest-jdk25-sbt-${{ steps.cache-epoch.outputs.epoch }}- + ubuntu-latest-jdk25-sbt-${{ steps.cache-epoch.outputs.release }}- ubuntu-latest-jdk25-sbt- - name: test run: sbt 'specularSite' @@ -77,6 +107,7 @@ jobs: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: "0" + fetch-tags: "true" - name: Setup JDK 25 uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5.6.0 with: @@ -85,6 +116,32 @@ jobs: - uses: sbt/setup-sbt@6444f4c8111de4b9059c3975def104b03cfaa5f0 # v1.5.2 with: disk-cache: "false" + - name: Resolve cache epoch + id: cache-epoch + run: | + set -euo pipefail + tag_match='v*' + if git remote get-url origin >/dev/null 2>&1; then + remote_count=$(git ls-remote --tags --refs origin "$tag_match" 2>/dev/null | wc -l | tr -d ' ') + local_count=$(git tag -l "$tag_match" | wc -l | tr -d ' ') + if [ "$remote_count" -gt 0 ] && [ "$local_count" -lt "$remote_count" ]; then + echo "::warning title=zipx cache epoch::Local tags ($local_count) fewer than origin ($remote_count). Epoch may be stale; checkout must use fetch-depth: 0 and fetch-tags: true." + fi + fi + if [[ "${GITHUB_REF:-}" == refs/tags/v* ]]; then + release="${GITHUB_REF#refs/tags/v}" + epoch="$release" + elif tag=$(git describe --tags --abbrev=0 --match "$tag_match" 2>/dev/null); then + release="${tag#v}" + epoch="${release}-ci" + else + echo "::warning title=zipx cache epoch::No tags matching '$tag_match' found; using epoch 0.0.0." + release="0.0.0" + epoch="0.0.0" + fi + echo "epoch=$epoch" >> "$GITHUB_OUTPUT" + echo "release=$release" >> "$GITHUB_OUTPUT" + - name: Cache sbt uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: @@ -93,11 +150,11 @@ jobs: ~/.cache/sbt ~/.cache/coursier target - key: ubuntu-latest-jdk25-sbt-0.0.0-ci-${{ github.run_id }}-fmt + key: ubuntu-latest-jdk25-sbt-${{ steps.cache-epoch.outputs.epoch }}-${{ github.run_id }}-fmt restore-keys: | - ubuntu-latest-jdk25-sbt-0.0.0-ci-${{ github.run_id }}- - ubuntu-latest-jdk25-sbt-0.0.0-ci- - ubuntu-latest-jdk25-sbt-0.0.0- + ubuntu-latest-jdk25-sbt-${{ steps.cache-epoch.outputs.epoch }}-${{ github.run_id }}- + ubuntu-latest-jdk25-sbt-${{ steps.cache-epoch.outputs.epoch }}- + ubuntu-latest-jdk25-sbt-${{ steps.cache-epoch.outputs.release }}- ubuntu-latest-jdk25-sbt- - name: fmt run: sbt 'scalafmtCheckAll' @@ -109,6 +166,7 @@ jobs: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: "0" + fetch-tags: "true" - name: Setup JDK 25 uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5.6.0 with: @@ -117,6 +175,32 @@ jobs: - uses: sbt/setup-sbt@6444f4c8111de4b9059c3975def104b03cfaa5f0 # v1.5.2 with: disk-cache: "false" + - name: Resolve cache epoch + id: cache-epoch + run: | + set -euo pipefail + tag_match='v*' + if git remote get-url origin >/dev/null 2>&1; then + remote_count=$(git ls-remote --tags --refs origin "$tag_match" 2>/dev/null | wc -l | tr -d ' ') + local_count=$(git tag -l "$tag_match" | wc -l | tr -d ' ') + if [ "$remote_count" -gt 0 ] && [ "$local_count" -lt "$remote_count" ]; then + echo "::warning title=zipx cache epoch::Local tags ($local_count) fewer than origin ($remote_count). Epoch may be stale; checkout must use fetch-depth: 0 and fetch-tags: true." + fi + fi + if [[ "${GITHUB_REF:-}" == refs/tags/v* ]]; then + release="${GITHUB_REF#refs/tags/v}" + epoch="$release" + elif tag=$(git describe --tags --abbrev=0 --match "$tag_match" 2>/dev/null); then + release="${tag#v}" + epoch="${release}-ci" + else + echo "::warning title=zipx cache epoch::No tags matching '$tag_match' found; using epoch 0.0.0." + release="0.0.0" + epoch="0.0.0" + fi + echo "epoch=$epoch" >> "$GITHUB_OUTPUT" + echo "release=$release" >> "$GITHUB_OUTPUT" + - name: Cache sbt uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: @@ -125,11 +209,11 @@ jobs: ~/.cache/sbt ~/.cache/coursier target - key: ubuntu-latest-jdk25-sbt-0.0.0-ci-${{ github.run_id }}-publish + key: ubuntu-latest-jdk25-sbt-${{ steps.cache-epoch.outputs.epoch }}-${{ github.run_id }}-publish restore-keys: | - ubuntu-latest-jdk25-sbt-0.0.0-ci-${{ github.run_id }}- - ubuntu-latest-jdk25-sbt-0.0.0-ci- - ubuntu-latest-jdk25-sbt-0.0.0- + ubuntu-latest-jdk25-sbt-${{ steps.cache-epoch.outputs.epoch }}-${{ github.run_id }}- + ubuntu-latest-jdk25-sbt-${{ steps.cache-epoch.outputs.epoch }}- + ubuntu-latest-jdk25-sbt-${{ steps.cache-epoch.outputs.release }}- ubuntu-latest-jdk25-sbt- - name: publish run: sbt 'hubJS/publish; root/publish' diff --git a/build.sbt b/build.sbt index f7a4877..49b2082 100644 --- a/build.sbt +++ b/build.sbt @@ -1,8 +1,8 @@ val scala3Version = "3.8.4" val zioVersion = "2.1.26" val zioHttpVersion = "3.11.3" -val ascentVersion = "0.1.0" -val specularVersion = "0.9.0" +val ascentVersion = "0.3.1" +val specularVersion = "0.10.1" ThisBuild / scalaVersion := scala3Version ThisBuild / organization := "rocks.earlyeffect" diff --git a/project/plugins.sbt b/project/plugins.sbt index 1df0957..3ea3253 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,7 +1,4 @@ addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.22.0") -addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.6.1") +addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.6.2") addSbtPlugin("rocks.earlyeffect" % "sbt-dynver-ci" % "0.2.2") -addSbtPlugin("rocks.earlyeffect" % "sbt-zipx" % "0.0.10") - -// zipx bundles sbt-remote-cache; compiler-interface is on both sbt-2.x and zinc-1.x schemes. -libraryDependencySchemes += "org.scala-sbt" % "compiler-interface" % "always" +addSbtPlugin("rocks.earlyeffect" % "sbt-zipx" % "0.0.12") diff --git a/src/main/scala/earlyeffect/hub/BuildHub.scala b/src/main/scala/earlyeffect/hub/BuildHub.scala index f3235ef..93d221f 100644 --- a/src/main/scala/earlyeffect/hub/BuildHub.scala +++ b/src/main/scala/earlyeffect/hub/BuildHub.scala @@ -22,7 +22,7 @@ object BuildHub extends ZIOAppDefault: private val FallbackSpecular = ProjectMeta( name = "specular", organization = "rocks.earlyeffect", - version = "0.7.3", + version = "0.10.1", scalaVersion = "3.8.4", title = Some("Specular"), description = Some("Code-first tests-as-docs site generator for Scala."), @@ -92,9 +92,22 @@ object BuildHub extends ZIOAppDefault: _ <- EarlyEffectTheme.writeLogo(out) _ <- injectFavicon(out) _ <- Console.printLine(s"Wrote hub → $out (${result.pages.size} files)") - yield ()).provideLayer(Client.default ++ EarlyEffectTheme.layers) + yield ()).provideLayer(Client.default ++ hubLayers) end run + /** EE chalkboard theme with a wider catalog so the landing fills like project docs content. */ + private val hubLayers = + Theme.fromTokens( + EarlyEffectTheme.tokens.copy( + extraCss = EarlyEffectTheme.tokens.extraCss + + """ + |.specular-site-Theme-Catalog { + | max-width: min(72rem, calc(100% - 3rem)); + |} + |""".stripMargin + ) + ) >>> DocsSite.themedStack + private def copyStaticAssets(out: Path): Task[Unit] = ZIO.attempt { val srcDir = Paths.get("images")