Skip to content

Commit

Permalink
ci: set SNAPSHOT_SUFFIX when not on main branch
Browse files Browse the repository at this point in the history
  • Loading branch information
jackdbd committed Oct 2, 2024
1 parent 97bdc71 commit 7e9cf32
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 86 deletions.
62 changes: 37 additions & 25 deletions .github/workflows/ci-cd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ env:
OPTIMIZATION_LEVEL: '-O2'
POD_ID: pod.jackdbd.jsoup
POD_NAME: pod-jackdbd-jsoup
# TODO: maybe create a snapshot build when the branch is not main (e.g. canary)
SNAPSHOT: "false"

jobs:
build-uberjar:
Expand All @@ -34,11 +32,24 @@ jobs:

outputs:
pod_version: ${{ steps.set_pod_version.outputs.pod_version }}
snapshot_suffix: ${{ steps.set_snapshot_suffix.outputs.snapshot_suffix }}

steps:
- name: 🛎️ Checkout
uses: actions/checkout@v4

- name: Set SNAPSHOT_SUFFIX (environment variable) and snapshot_suffix (job output)
id: set_snapshot_suffix
# https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/store-information-in-variables#default-environment-variables
run: |
if [ "${{ github.ref }}" != "refs/heads/main" ]; then
echo "SNAPSHOT_SUFFIX=${GITHUB_SHA}" >> $GITHUB_ENV
else
echo "SNAPSHOT_SUFFIX=" >> $GITHUB_ENV
fi
echo "snapshot_suffix=$SNAPSHOT_SUFFIX" >> $GITHUB_OUTPUT
echo "SNAPSHOT_SUFFIX is $SNAPSHOT_SUFFIX"
# https://github.com/marketplace/actions/github-action-for-graalvm
- name: 🔧 Setup GraalVM
uses: graalvm/setup-graalvm@v1
Expand Down Expand Up @@ -70,26 +81,30 @@ jobs:
key: cljdeps-${{ hashFiles('deps.edn', 'bb.edn') }}
restore-keys: cljdeps-

# TODO: At the moment POD_VERSION is correct only for "standard" builds,
# but not for "snapshot" builds.
# Problem: In build.clj I am using the clojure.tools.build.api/git-count-revs
# function to generate the snapshot version tag. But that only works in
# Clojure, not Babashka.
# Solution: I should propably replace it with the same function from this fork:
# https://github.com/babashka/tools.bbuild
# Example of an uberjar of a standard release:
# pod.jackdbd.jsoup-0.1.1-standalone.jar
# pod.jackdbd.jsoup-0.1.2-standalone.jar
# Example of an uberjar of a snapshot release:
# pod.jackdbd.jsoup-0.1.1-21-SNAPSHOT-standalone.jar
# pod.jackdbd.jsoup-0.1.2-345-SNAPSHOT-standalone.jar
- name: Set POD_VERSION (environment variable) and pod_version (job output)
id: set_pod_version
run: |
POD_VERSION=$(bb -e '(-> (slurp "deps.edn") edn/read-string :aliases :neil :project :version)' | tr -d '"')
PROJECT_VERSION=$(bb -e '(-> (slurp "deps.edn") edn/read-string :aliases :neil :project :version)' | tr -d '"')
if [ -z "${SNAPSHOT_SUFFIX}" ]; then
POD_VERSION=$PROJECT_VERSION
else
POD_VERSION="${PROJECT_VERSION}-${SNAPSHOT_SUFFIX}"
fi
echo "POD_VERSION=$POD_VERSION" >> $GITHUB_ENV
echo "pod_version=$POD_VERSION" >> $GITHUB_OUTPUT
echo "POD_VERSION is $POD_VERSION"
- name: 📦 Compile pod into an uberjar
run: clojure -T:build uber :snapshot ${{ env.SNAPSHOT }}
run: |
if [ -n "${SNAPSHOT_SUFFIX}" ]; then
clojure -T:build uber :snapshot-suffix ${{ env.SNAPSHOT_SUFFIX }}
else
clojure -T:build uber
fi
- name: ⬆️ Upload uberjar
uses: actions/upload-artifact@v4
Expand All @@ -104,6 +119,7 @@ jobs:

env:
POD_VERSION: ${{ needs.build-uberjar.outputs.pod_version }}
SNAPSHOT_SUFFIX: ${{ needs.build-uberjar.outputs.snapshot_suffix }}

steps:
- name: 🛎️ Checkout
Expand Down Expand Up @@ -332,6 +348,7 @@ jobs:

env:
POD_VERSION: ${{ needs.build-uberjar.outputs.pod_version }}
SNAPSHOT_SUFFIX: ${{ needs.build-uberjar.outputs.snapshot_suffix }}

permissions:
contents: write
Expand All @@ -346,23 +363,18 @@ jobs:
cli: 'latest'
bb: 'latest'

# - name: ⬇️ Download uberjar
# uses: actions/download-artifact@v4
# with:
# name: uberjar

# - name: Copy the uberjar to the target directory
# run: |
# mkdir target
# cp ${{ env.POD_ID }}-${{ env.POD_VERSION }}-standalone.jar target/${{ env.POD_ID }}-${{ env.POD_VERSION }}-standalone.jar

- name: 🌐 Publish to Clojars
env:
CLOJARS_USERNAME: jackdbd
CLOJARS_PASSWORD: ${{ secrets.CLOJARS_PASSWORD }}
run: |
clojure -T:build uber :snapshot ${{ env.SNAPSHOT }}
clojure -T:build deploy :snapshot ${{ env.SNAPSHOT }}
if [ -n "${SNAPSHOT_SUFFIX}" ]; then
clojure -T:build uber :snapshot-suffix ${{ env.SNAPSHOT_SUFFIX }}
clojure -T:build deploy :snapshot-suffix ${{ env.SNAPSHOT_SUFFIX }}
else
clojure -T:build uber
clojure -T:build deploy
fi
- name: ⬇️ Download x86_64 Linux binary
uses: actions/download-artifact@v4
Expand Down
48 changes: 11 additions & 37 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,53 +5,27 @@

Babashka pod for parsing HTML with [jsoup](https://jsoup.org/).

## Setup
## How to use it?

The developer environment for this project is declared using [devenv](https://github.com/cachix/devenv).

This project is managed with [neil](https://github.com/babashka/neil) and [Babashka tasks](https://book.babashka.org/#tasks).

## Compile the pod

### JAR

```sh
clj -T:build jar
```

### Uber-JAR
See [examples/jsoup.bb](./examples/jsoup.bb).

```sh
clj -T:build uber
```
## Development

### Executable binary
The developer environment for this project is declared using [devenv](https://github.com/cachix/devenv).

If you are on Linux, you can compile a statically-linked binary with the following command, which uses GraalVM native-image with [musl](https://musl.libc.org/) support.
This project is managed with [neil](https://github.com/babashka/neil) and [Babashka tasks](https://book.babashka.org/#tasks). You can use `bb tasks` to view all available tasks.

```sh
clj -T:build uber && ./script/compile.sh

# or, in alternative, just run the following command:
bb build:native
```
### Linux binary

If you are on Linux, you can compile a statically-linked binary using `bb build:binary`.
Double check that the binary is statically linked.

```sh
ldd target/pod-jackdbd-jsoup
objdump --dynamic-syms target/pod-jackdbd
```

## Tests

Run all tests

```sh
clj -X:test
```

## Upgrade version
### Upgrade version

Use `neil` to update the version in `deps.edn`. Here are a few examples:

Expand All @@ -61,7 +35,7 @@ neil version patch
neil version minor
```

These `neil` commands:
A few things to keep in mind about `neil version`:

- Create a Git commit and tag (this can be bypassed with `--no-tag`)
- Require the working directory to be clean (this can be bypassed with `--force`)
- it creates a Git commit and tag (this can be bypassed with `--no-tag`)
- it requires the working directory to be clean (this can be bypassed with `--force`)
23 changes: 13 additions & 10 deletions bb.edn
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,23 @@

build:binary
{:doc "Compile the pod into a statically-linked binary with GraalVM native-image (Linux only)"
:depends [build:uberjar]
:depends [build:uber]
:task (shell "script/compile.sh")}

build:jar
{:doc "Compile the the pod into a jar"
:depends [clean]
:task (let [snapshot (System/getenv "SNAPSHOT")]
(clojure "-T:build jar :snapshot" snapshot))}
:task (if-let [snapshot-suffix (System/getenv "SNAPSHOT_SUFFIX")]
(clojure "-T:build jar :snapshot-suffix" (keyword snapshot-suffix))
(clojure "-T:build jar"))}

build:uberjar
build:uber
{:doc "Compile the the pod into an uberjar"
:depends [clean]
:task
(let [snapshot (System/getenv "SNAPSHOT")]
(clojure "-T:build uber :snapshot" snapshot))}
(if-let [snapshot-suffix (System/getenv "SNAPSHOT_SUFFIX")]
(clojure "-T:build uber :snapshot-suffix" (keyword snapshot-suffix))
(clojure "-T:build uber"))}

clean
{:doc "Clean all compilation artifacts (e.g. jars, binaries)"
Expand All @@ -32,10 +34,11 @@

deploy:clojars
{:doc "Deploy the pod to Clojars"
:depends [build:uberjar]
:depends [build:uber]
:task
(let [snapshot (System/getenv "SNAPSHOT")]
(clojure "-T:build deploy :snapshot" snapshot))}
(if-let [snapshot-suffix (System/getenv "SNAPSHOT_SUFFIX")]
(clojure "-T:build deploy :snapshot-suffix" (keyword snapshot-suffix))
(clojure "-T:build deploy"))}

deps:audit
{:doc "Audit all dependencies declared in deps.edn"
Expand All @@ -52,7 +55,7 @@

list:uberjar
{:doc "List the contents of the uberjar"
:depends [build:uberjar]
:depends [build:uber]
:task (let [project (-> (edn/read-string (slurp "deps.edn")) :aliases :neil :project)
pod-name "pod.jackdbd.jsoup"
pod-version (:version project)
Expand Down
40 changes: 28 additions & 12 deletions build.clj
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,24 @@
"pod.jackdbd.jsoup's build script.
clojure -T:build jar
clojure -T:build jar :snapshot true
clojure -T:build uber
clojure -T:build uber :snapshot true
clojure -T:build uber :snapshot-prefix :123-SNAPSHOT
clojure -T:build deploy
clojure -T:build deploy :snapshot true
clojure -T:build deploy :snapshot-prefix :123-SNAPSHOT
For more information, run:
clojure -A:deps -T:build help/doc"
clojure -A:deps -T:build help/doc"
(:require [clojure.tools.build.api :as b]
[clojure.edn :as edn]
[clojure.pprint :refer [pprint]]
[deps-deploy.deps-deploy :as dd]))

;; The clojure.tools.build.api library works only in Clojure, not Babashka.
;; Consider replacing it with this fork https://github.com/babashka/tools.bbuild

(def project (-> (edn/read-string (slurp "deps.edn")) :aliases :neil :project))
(def lib (:name project))
(def release-version (:version project))
;; https://stackoverflow.com/a/5901460/3036129
(def snapshot-version (format "%s-%s-%s" release-version (b/git-count-revs nil) "SNAPSHOT"))

;; https://clojure.github.io/tools.build/clojure.tools.build.api.html#var-write-pom
(defn- pom-template [{:keys [version]}]
Expand All @@ -39,8 +39,12 @@
[:developerConnection "scm:git:ssh:git@github.com:jackdbd/pod-jackdbd-jsoup.git"]
[:tag (str "v" version)]]])

;; What exactly is a Maven Snapshot and why do we need it?
;; https://stackoverflow.com/a/5901460/3036129
(defn- shared-config [opts]
(let [vers (if (:snapshot opts) snapshot-version release-version)]
(let [vers (if (:snapshot-suffix opts)
(format "%s-%s" (:version project) (name (:snapshot-suffix opts)))
(:version project))]
(assoc opts
:basis (b/create-basis {:project "deps.edn"})
:class-dir "target/classes"
Expand All @@ -53,12 +57,13 @@
:uber-file (format "target/%s-%s-standalone.jar" (name lib) vers)
:version vers)))

(defn clean [_]
(defn clean "Remove all compilation artifacts." [_]
(b/delete {:path "target"}))

(defn jar "Build the JAR." [opts]
(let [config (shared-config opts)
{:keys [basis class-dir jar-file lib main pom-data src-dirs target version]} config]

(clean nil)

;; https://clojure.github.io/tools.build/clojure.tools.build.api.html#var-write-pom
Expand All @@ -83,6 +88,7 @@
(defn uber "Build the uber-JAR." [opts]
(let [config (shared-config opts)
{:keys [basis class-dir main pom-data src-dirs target uber-file version]} config]

(clean nil)

(println "\nWriting" (b/pom-path (select-keys config [:lib :class-dir])) "...")
Expand All @@ -107,19 +113,29 @@
:uber-file uber-file})))

(defn deploy "Deploy the uberjar to Clojars." [opts]
(println "\nOptions")
(pprint opts)

(let [config (shared-config opts)
{:keys [uber-file]} config
artifact (b/resolve-path uber-file)
pom-file (b/pom-path (select-keys config [:lib :class-dir]))]

(println "\nConfig")
(pprint config)

;; https://github.com/slipset/deps-deploy/blob/master/doc/intro.md
(dd/deploy {:artifact artifact
:installer :remote
:pom-file pom-file}))
opts)

(comment
(prn (pom-template {:version release-version}))
(prn (pom-template {:version (:version project)}))

(def snapshot-version (format "%s-%s" (:version project) (name (:snapshot-suffix "123-SNAPSHOT"))))
(prn (pom-template {:version snapshot-version}))

(jar {})
(uber {})
(deploy {}))
(deploy {:snapshot-prefix :123-SNAPSHOT}))
8 changes: 7 additions & 1 deletion devenv.nix
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
{pkgs, ...}: {
enterShell = ''
versions
# When SNAPSHOT_SUFFIX is set, `bb deploy:clojars` will create/overwrite a
# snapshot release. When SNAPSHOT_SUFFIX is not set, or set to an empty
# string, `bb deploy:clojars` will create a regular release, or fail if the
# release already exists.
export SNAPSHOT_SUFFIX="$(git rev-list --count HEAD)-SNAPSHOT"
# export SNAPSHOT_SUFFIX=""
'';

enterTest = ''
Expand Down Expand Up @@ -34,7 +41,6 @@
clojars_secrets.deploy_token;

GH_TOKEN = builtins.readFile "/run/secrets/github-tokens/semantic_release_bot";
SNAPSHOT = "true"; # this must be either "true" or "false", not true or false
};

languages = {
Expand Down
13 changes: 12 additions & 1 deletion script/compile.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,18 @@ set -euo pipefail

POD_ID=pod.jackdbd.jsoup
POD_NAME=pod-jackdbd-jsoup
POD_VERSION=$(bb -e '(-> (slurp "deps.edn") edn/read-string :aliases :neil :project :version)' | tr -d '"')
PROJECT_VERSION=$(bb -e '(-> (slurp "deps.edn") edn/read-string :aliases :neil :project :version)' | tr -d '"')

# If we built an uberjar for a snapshot release, its filename will include a
# snapshot suffix.
if [ -z "${SNAPSHOT_SUFFIX}" ]; then
POD_VERSION=$PROJECT_VERSION
else
POD_VERSION="${PROJECT_VERSION}-${SNAPSHOT_SUFFIX}"
fi
echo "PROJECT_VERSION is $PROJECT_VERSION"
echo "SNAPSHOT_SUFFIX is $SNAPSHOT_SUFFIX"
echo "POD_VERSION is $POD_VERSION"

# https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/store-information-in-variables#default-environment-variables
if [ "${CI+x}" ]; then
Expand Down

0 comments on commit 7e9cf32

Please sign in to comment.