diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9308b7f2..0cd9f4a4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -5,9 +5,6 @@ on: branches: - master pull_request: - schedule: - # 12:00AM on the first of every month - - cron: "0 0 1 * *" jobs: setup: diff --git a/README.md b/README.md index 4e2eaa21..c828a22d 100644 --- a/README.md +++ b/README.md @@ -29,24 +29,48 @@ lein doc ## Releases -```clojure -# snapshot release -lein deploy +The project version in `project.clj` should always be a `-SNAPSHOT` on the main branch. +The release process (defined in `:release-tasks` in `project.clj`) handles bumping, +deploying, and advancing to the next snapshot automatically. + +### Before releasing + +Run `lein doc` and commit any generated changes. The release will fail at the +`vcs assert-committed` step if there are uncommitted doc changes. -# for releases, set project.clj version to x.y.z-SNAPSHOT -# this command then releases as x.y.z and bumps to x.y.(z+1)-SNAPSHOT -# aliased as ./script/release.sh +### Patch release + +```bash lein release :patch +``` + +For minor or major bumps, use `lein release :minor` or `lein release :major`. + +### Snapshot release -# if release fails partway through, use these commands to recover +```bash +lein deploy +``` + +### Recovery + +If the release fails **before** `deploy clojars`: + +```bash git tag --delete x.y.z -# you might have a redundant commit "Version x.y.z", undo with: git reset --hard SHA_BEFORE_FAILED_RELEASE ``` +If the release fails **after** `deploy clojars` (e.g., at the `vcs push` step), +the artifact is already published. Complete the release manually: + +```bash +git push --tags --set-upstream origin release-x.y.z +``` + ## License -Copyright © 2016-2024 Cisco Systems +Copyright © 2016-2026 Cisco Systems Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version. diff --git a/dev/ctim/change_schema_version.clj b/dev/ctim/change_schema_version.clj new file mode 100644 index 00000000..4a6c6d7f --- /dev/null +++ b/dev/ctim/change_schema_version.clj @@ -0,0 +1,5 @@ +(ns ctim.change-schema-version) + +(defn -main + [version] + (spit "./resources/ctim/version.txt" version)) diff --git a/project.clj b/project.clj index 90a1734a..039808a6 100644 --- a/project.clj +++ b/project.clj @@ -20,7 +20,7 @@ [kovacnica/clojure.network.ip "0.1.5"]] :uberjar-name "ctim.jar" - :resource-paths ["doc"] + :resource-paths ["doc" "resources"] :plugins [[lein-cljsbuild "1.1.7"] [com.google.guava/guava "20.0"] ;resolve internal conflict in `lein-doo` @@ -39,20 +39,26 @@ ;; please commit it and try again ["vcs" "assert-committed"] ["change" "version" "leiningen.release/bump-version" "release"] + ["sync-schema-version"] ;; will fail if project.clj doesn't already have -SNAPSHOT version ["vcs" "commit"] ["vcs" "tag" "--no-sign"] ["deploy" "clojars"] ["change" "version" "leiningen.release/bump-version"] + ["sync-schema-version"] ["vcs" "commit"] ;; fails if no upstream branch is defined ;; if it fails at this point you can complete the release using: ;; git push --tags --set-upstream origin release-x.y.z ["vcs" "push"]] - :aliases {"doc" ^{:doc "Generate documentation"} ["run" "-m" "ctim.document"] - "docs" ^{:doc "Generate documentation"} ["doc"] - "gen" ^{:doc "Generate an example"} ["run" "-m" "ctim.generate"]} + :aliases {"doc" ^{:doc "Sync schema version and generate documentation"} ["do" ["sync-schema-version"] ["run" "-m" "ctim.document"]] + "docs" ^{:doc "Sync schema version and generate documentation"} ["doc"] + "gen" ^{:doc "Generate an example"} ["run" "-m" "ctim.generate"] + "sync-schema-version" ^{:doc "Updates the CTIM schema version to match the project version."} ["run" + "-m" + "ctim.change-schema-version" + :project/version]} :cljsbuild {:builds {:node {:source-paths ["src" "test"] :compiler {:output-to "target/tests.js" @@ -76,4 +82,5 @@ [com.google.errorprone/error_prone_annotations "2.1.3"] ;;https://clojure.atlassian.net/browse/CLJS-3047 [com.google.code.findbugs/jsr305 "3.0.2"] - [org.clojure/clojurescript "1.12.42"]]}}) + [org.clojure/clojurescript "1.12.42"]]} + :dev {:source-paths ["dev"]}}) diff --git a/resources/ctim/version.txt b/resources/ctim/version.txt new file mode 100644 index 00000000..2b43cb36 --- /dev/null +++ b/resources/ctim/version.txt @@ -0,0 +1 @@ +1.3.30-SNAPSHOT \ No newline at end of file diff --git a/script/release.sh b/script/release.sh deleted file mode 100755 index a1c085b5..00000000 --- a/script/release.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -set -xe -lein release :patch diff --git a/src/ctim/schemas/common.cljc b/src/ctim/schemas/common.cljc index 875c4eba..3ce5669d 100644 --- a/src/ctim/schemas/common.cljc +++ b/src/ctim/schemas/common.cljc @@ -2,6 +2,7 @@ (:refer-clojure :exclude [ref uri?]) (:require [clj-momo.lib.clj-time.coerce :refer [to-long]] [clojure.set :refer [map-invert]] + [clojure.string :as str] #?(:clj [clojure.spec.alpha :as cs] :cljs [cljs.spec.alpha :as cs]) [clojure.zip :as z] @@ -17,15 +18,16 @@ def-enum-type def-eq]]) [flanders.navigation :as fn] - [flanders.predicates :as fp] - [clojure.string :as str])) + [flanders.predicates :as fp]) + (#?(:clj :require :cljs :require-macros) [ctim.version :refer [ctim-version]])) -(def ctim-schema-version "1.3.30") + +(def ctim-schema-version (ctim-version)) (def-eq CTIMSchemaVersion ctim-schema-version) (cs/def ::ctim-schema-version - #(re-matches #"\w+.\w+\.\w+" %)) + #(re-matches #"\w+.\w+\.\w+(-SNAPSHOT)?" %)) (def SchemaVersion (f/str diff --git a/src/ctim/version.clj b/src/ctim/version.clj new file mode 100644 index 00000000..be7ac12d --- /dev/null +++ b/src/ctim/version.clj @@ -0,0 +1,8 @@ +(ns ctim.version + (:require [clojure.java.io :as io])) + +(defmacro ctim-version + "This is a macro to support cljs compile-time inlining of the version string + from the JVM resource." + [] + (slurp (io/resource "ctim/version.txt"))) diff --git a/test/ctim/schemas/common_test.cljc b/test/ctim/schemas/common_test.cljc index da6be43f..b308da5f 100644 --- a/test/ctim/schemas/common_test.cljc +++ b/test/ctim/schemas/common_test.cljc @@ -1,8 +1,10 @@ (ns ctim.schemas.common-test (:refer-clojure :exclude [ref uri?]) - (:require [ctim.schemas.common :as sut] - [flanders.schema :as fs] - [clojure.test :refer [deftest is]])) + (:require + [clojure.java.io :as io] + [clojure.test :refer [deftest is testing]] + [ctim.schemas.common :as sut] + [flanders.schema :as fs])) (defn- ->swagger [dll] (:json-schema (meta (fs/->schema dll)))) @@ -10,3 +12,18 @@ (is (= {:example {:value "1.2.3.4", :type "ip"} :description "A simple, atomic value which has a consistent identity, and is stable enough to be attributed an intent or nature. This is the classic 'indicator' which might appear in a data feed of bad IPs, or bad Domains. These do not exist as objects within the CTIA storage model, so you never create an observable."} (->swagger sut/Observable)))) + +(defn lein-project-version + [] + (let [properties (with-open [pom-properties-reader (io/reader (io/resource "META-INF/maven/threatgrid/ctim/pom.properties"))] + (doto (java.util.Properties.) + (.load pom-properties-reader)))] + (if-let [ver (get properties "version")] + ver + (throw (ex-info "Unable to resolve ctim version" {}))))) + +(deftest version-test + (testing "The lein project version and ctim schema version are in sync." + (is (re-matches #"[\d]+\.[\d]+\.[\d]+.*?" sut/ctim-schema-version) + "Version follows the expected semantic versioning pattern.") + (is (= (lein-project-version) sut/ctim-schema-version))))