diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 59f55ce..846eba2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -11,6 +11,10 @@ jobs: runs-on: ubuntu-latest permissions: contents: read + env: + CLOJARS_USERNAME: tooooolong + CLOJARS_PASSWORD: ${{ secrets.CLOJARS_DEPLOY_TOKEN }} + CLOJARS_TOKEN_SCOPE: org.clojars.tooooolong/* steps: - uses: actions/checkout@v4 @@ -62,8 +66,34 @@ jobs: - name: Verify version in project.clj run: head -1 project.clj + - name: Verify project coordinates match token scope + run: | + python3 - <<'PYEOF' + import os + import re + import sys + + text = open("project.clj").read() + match = re.search(r'defproject\s+([^\s"]+)\s+"([^"]+)"', text) + if not match: + print("Unable to parse defproject coordinates from project.clj", file=sys.stderr) + sys.exit(1) + + coordinates = match.group(1) + scope = os.environ["CLOJARS_TOKEN_SCOPE"] + scope_prefix = scope[:-1] if scope.endswith("*") else scope + + print("Release coordinates:", coordinates) + print("Configured token scope:", scope) + + if not coordinates.startswith(scope_prefix): + print( + "CLOJARS_DEPLOY_TOKEN scope does not allow deploying these coordinates. " + "Mint a token for the current project coordinates or migrate the published coordinates first.", + file=sys.stderr, + ) + sys.exit(1) + PYEOF + - name: Deploy to Clojars - env: - CLOJARS_USERNAME: ${{ secrets.CLOJARS_USERNAME }} - CLOJARS_PASSWORD: ${{ secrets.CLOJARS_PASSWORD }} run: lein deploy clojars diff --git a/README.md b/README.md index 70957d6..5cfd53a 100644 --- a/README.md +++ b/README.md @@ -258,12 +258,24 @@ deploys to [Clojars](https://clojars.org) automatically when you push a `v*` tag ### Prerequisites -Add two repository secrets in **Settings → Secrets and variables → Actions**: +Add this repository secret in **Settings → Secrets and variables → Actions**: | Secret | Value | |--------|-------| -| `CLOJARS_USERNAME` | Your Clojars username | -| `CLOJARS_PASSWORD` | A Clojars [deploy token](https://clojars.org/tokens) (not your password) | +| `CLOJARS_DEPLOY_TOKEN` | A Clojars [deploy token](https://clojars.org/tokens) for the publishing account | + +The workflow uses the fixed Clojars username `tooooolong`; the token replaces the +password when deploying. + +The release workflow also checks that the token scope matches the project +coordinates in `project.clj` before running `lein deploy`. + +This repository still publishes the coordinates `tooooolong/clojure-cobertura-coverage`. +If your token is scoped only to `org.clojars.tooooolong/*`, Clojars will reject the +deploy until you either: + +1. mint a token whose scope includes `tooooolong/clojure-cobertura-coverage`, or +2. deliberately migrate the published coordinates to `org.clojars.tooooolong/...` ### Steps to release @@ -280,7 +292,8 @@ git push origin v0.2.0 The workflow will: 1. Extract the version from the tag (`v0.2.0` → `0.2.0`) 2. Patch `project.clj` with that version in the ephemeral CI workspace -3. Run `lein deploy clojars` +3. Verify the configured token scope can publish the current coordinates +4. Run `lein deploy clojars` The `project.clj` in the repository always stays at the **development version** (`0.1.0`). Bump it manually before tagging if you want the version shown in editor tooling to match. diff --git a/deps.edn b/deps.edn index 1ceb6df..56e1d5e 100644 --- a/deps.edn +++ b/deps.edn @@ -6,37 +6,35 @@ :aliases {;; Run tests with: clj -M:test ;; - ;; Uses clojure.main -e to evaluate an inline test runner — no extra - ;; dependencies required. Exits non-zero when any test fails or errors. + ;; The example namespace lives under dev/ so it is NOT packaged in the + ;; published JAR. Adjust the require and run-tests call for your own project. :test - {:extra-paths ["test"] + {:extra-paths ["dev" "test"] :main-opts ["-e" "(require 'example.core-test 'clojure.test)(let [r (clojure.test/run-tests 'example.core-test)](System/exit (if (pos? (+ (:fail r) (:error r))) 1 0)))"]} ;; Run cloverage with the Cobertura XML reporter: ;; clj -M:coverage ;; - ;; Limit which namespaces are instrumented with --ns-regex (remove or - ;; adjust when using this reporter in your own project). + ;; The example namespace lives under dev/ and is only used for + ;; demonstration. Adjust --ns-regex for your own project. :coverage - {:extra-paths ["test"] + {:extra-paths ["dev" "test"] :extra-deps {cloverage/cloverage {:mvn/version "1.2.4"}} :main-opts ["-m" "cloverage.coverage" "--custom-report" "cloverage.coverage.cobertura/report" "--ns-regex" "^example\\..*" "--test-ns-regex" "^example\\..*-test$" - "--fail-threshold" "0" "--output" "target/coverage"]} ;; Same as :coverage but also generates the built-in HTML report: ;; clj -M:coverage-html :coverage-html - {:extra-paths ["test"] + {:extra-paths ["dev" "test"] :extra-deps {cloverage/cloverage {:mvn/version "1.2.4"}} :main-opts ["-m" "cloverage.coverage" "--custom-report" "cloverage.coverage.cobertura/report" "--html" "--ns-regex" "^example\\..*" "--test-ns-regex" "^example\\..*-test$" - "--fail-threshold" "0" "--output" "target/coverage"]}}} diff --git a/src/example/core.clj b/dev/example/core.clj similarity index 100% rename from src/example/core.clj rename to dev/example/core.clj diff --git a/project.clj b/project.clj index 97c3601..369d703 100644 --- a/project.clj +++ b/project.clj @@ -6,12 +6,11 @@ :dependencies [[org.clojure/clojure "1.10.0"] [org.clojure/data.xml "0.2.0-alpha10"] [cloverage "1.2.4"]] - :profiles {:dev {:plugins [[lein-cloverage "1.2.4"]]}} + :profiles {:dev {:source-paths ["dev"] + :plugins [[lein-cloverage "1.2.4"]]}} :deploy-repositories [["clojars" {:url "https://clojars.org/repo" :username :env/clojars_username :password :env/clojars_password :sign-releases false}]] - ;; Run coverage only on the example namespace to demonstrate the reporter. - ;; Remove or adjust :ns-regex when using this reporter in your own project. :cloverage {:ns-regex [#"^example\..*"] :output "target/coverage"})