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
3 changes: 0 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@ on:
branches:
- master
pull_request:
schedule:
# 12:00AM on the first of every month
- cron: "0 0 1 * *"

jobs:
setup:
Expand Down
42 changes: 33 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
5 changes: 5 additions & 0 deletions dev/ctim/change_schema_version.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
(ns ctim.change-schema-version)

(defn -main
[version]
(spit "./resources/ctim/version.txt" version))
17 changes: 12 additions & 5 deletions project.clj
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand All @@ -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"]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we always want to update the docs when we bump versions, and vice-versa.

Please redefine the "doc" alias to do the equivalent of running ctim.change-schema-version/-main followed by ctim.document/-main.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

["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"
Expand All @@ -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"]}})
1 change: 1 addition & 0 deletions resources/ctim/version.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1.3.30-SNAPSHOT
3 changes: 0 additions & 3 deletions script/release.sh

This file was deleted.

10 changes: 6 additions & 4 deletions src/ctim/schemas/common.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can remove requires of clojure.java.io and clojure.string.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what the state of things was at the time of this comment, but as it stands:

  • clojure.string is still imported because it's used.
  • clojure.java.io is removed.

#?(:clj [clojure.spec.alpha :as cs]
:cljs [cljs.spec.alpha :as cs])
[clojure.zip :as z]
Expand All @@ -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
Expand Down
8 changes: 8 additions & 0 deletions src/ctim/version.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
(ns ctim.version
(:require [clojure.java.io :as io]))

(defmacro ctim-version
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This may be me misunderstanding how cljs works, but I'm unclear why this needs to be a macro

Copy link
Copy Markdown
Contributor

@frenchy64 frenchy64 Mar 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The initial problem here was that you'd need to manually update (def ctim-schema-version "1.3.30") every release with the new version. If you forgot, the version was desynced from project.clj

We considered two main solutions.

  1. Have leiningen write the new version directly to this def on version change.
  2. Create a separate file with the version that we refer to.

This implements 2. The reason it needs to be a macro is that cljs doesn't implement io/resource or slurp, so we need get the version string via JVM Clojure. Macros are expanded in JVM Clojure.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's been a minute since I wrote this, but I think what's happening is that clojurescript needs to read the resource that holds the version at compile time, and having it as a macro allows the code to be evaluated at compile time instead of runtime.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I recall correctly, @frenchy64 and I had a lot of back-and-forth about how to keep the CTIM library and schema versions in sync, only some of which seems to be captured in the PR comments. Several ideas were considered, and the one we ended up with involves this version file and the need for the clj/cljs code to read from it to get the schema version.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I hadn't seen @frenchy64's comment. He explains it better.

"This is a macro to support cljs compile-time inlining of the version string
from the JVM resource."
[]
(slurp (io/resource "ctim/version.txt")))
23 changes: 20 additions & 3 deletions test/ctim/schemas/common_test.cljc
Original file line number Diff line number Diff line change
@@ -1,12 +1,29 @@
(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))))

(deftest swagger-test
(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))))
Loading