Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 33 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
21 changes: 17 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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.
Expand Down
16 changes: 7 additions & 9 deletions deps.edn
Original file line number Diff line number Diff line change
Expand Up @@ -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"]}
Comment thread
tooooolong marked this conversation as resolved.

;; 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"]}}}
File renamed without changes.
5 changes: 2 additions & 3 deletions project.clj
Original file line number Diff line number Diff line change
Expand Up @@ -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"})
Loading