Fork me on GitHub
#polylith
<
2022-11-26
>
licht1stein00:11:35

Trying to set up CI tests to only run test for what has changed. Somehow, it just shows me that everything is stable: Locally, it shows several projects that need to be tested. How do I set it up? Please help 🙈

seancorfield00:11:14

The stable-* tag needs to be visible in CI -- I expect it's only a local tag in your git tree?

seancorfield00:11:30

What we do in CI is poly test since:release and when a CI build succeeds, we tag it as a "release" (with a version -- per workspace.edn patterns)

seancorfield00:11:43

(and CI pushes that new tag back to git)

seancorfield00:11:33

Our build.clj file handles stable tagging like this (per-developer):

(defn stable-tag
  "Record a stable tag for the current user."
  []
  (let [{:keys [exit out]} (b/process {:command-args ["whoami"]
                                       :out :capture})
        stable-tag (str/trim (str "stable-" out))]
    (when-not (and (zero? exit) (seq out))
      (throw (ex-info "whoami failed to return username" {:out out})))
    (b/git-process {:git-args ["fetch" "--tags" "-f"]})
    (b/git-process {:git-args ["tag" "-f" stable-tag]})
    (b/git-process {:git-args ["push" "origin" (str "refs/tags/" stable-tag) "-f"]})))

seancorfield00:11:49

This is what happens in CI:

(defn tag-and-push
  "Given a tag prefix (billing or build, typically), add
  a timestamped git tag and push it to the repo.

  If this format changes (specifically with build as a
  prefix), remember to update workspace.edn as well!"
  [{:keys [prefix] :as params}]
  (let [tag (str prefix "-" (.format (java.time.LocalDateTime/now)
                                     (java.time.format.DateTimeFormatter/ofPattern
                                      "")))]
    (b/git-process {:git-args ["tag" tag]})
    (b/git-process {:git-args ["push" "origin" (str "refs/tags/" tag)]}))
  params)
(`:prefix "build"` is used for the migrated-to-Polylith stuff and a different prefix is used for the legacy projects which run in a separate CI job).

seancorfield00:11:26

And in workspace.edn:

:tag-patterns {;; we tag each QA deployment with build-
                :release "build-[0-9][0-9][0-9][0-9]-*"
                :stable  "stable-*"}

seancorfield00:11:57

So it sees the tags from tag-and-push above, but not the tags from the legacy CI job 🙂

licht1stein00:11:08

Bloody hell, that is so smart. I'm off to try to implement a similar system 🙂 Thank you so much!

seancorfield00:11:37

I need to blog this stuff...

seancorfield00:11:38

bitbucket-pipelines.xml has (effectively) this:

# ensure we have all the deps for our cache
          - ../build/clojure/bin/clojure -P -M:build:poly:dev:test
          - ../build/clojure/bin/clojure -T:build cold-start
          - ../build/clojure/bin/clojure -M:poly test since:release
cold-start sets up our database and populates an Elastic Search instance for CI to run.

seancorfield00:11:09

(we vendor the Clojure CLI into our repo under build/clojure in you're wondering about that)

seancorfield01:11:42

And finally we have:

- ../build/clojure/bin/clojure -T:build tag-build-and-upload-all
which does the tag-and-push above plus building all the uberjar artifacts and uploading them to S3, and then notifying our QA system a deployment is ready (triggering a script to draw down those JARs and restart the services)

seancorfield01:11:54

(that's also how we deploy to the production cluster)

licht1stein01:11:49

We're using Datomic Ions and Github Actions. But I think I got the idea, working on it now, thanks again!

licht1stein01:11:58

I will probably come back 🙂

seancorfield01:11:29

Happy to answer any Qs 🙂

licht1stein01:11:14

Thank you ❤️

licht1stein01:11:27

Ok, I seem to be missing something. My workflow now looks like the screenshot. I have used your tag-and-push function, so the last release was successfully tagged by the CI. I have fetched and pulled the master branch, and I can see the tag from the CI (screenshot 2). I have created a new branch from the master, and changed some tests. Locally poly detects the changes (screenshot 3), but somehow still shows an older tag stable-mb, which I created using the stable-tag function earlier (screenshot 3). In my test action I run clojure -M:poly test since:release, and I still get 0 tests. And I run poly info in an earlier test and it doesn't show any tags at all (screenshot 4). @U04V70XH6 please help 🙂

seancorfield01:11:40

That tag-and-push creates a build-... tag which is not the default way that Polylith recognizes a release.

seancorfield01:11:52

since:release is different to since:stable

seancorfield01:11:24

In our build.clj file, stable-tag produces the stable-<username> tags and that's what poly test looks for by default -- since:stable -- and the default in workspace.edn for release is v[0-9]* I think, so your release tag needs to match that.

licht1stein01:11:35

It seems tag-and-push creates a tag with a prefix, so I run it like this: clojure -T:build tag-and-push '{:prefix "release"}'

licht1stein01:11:27

Oh, the pattern is wrong now

seancorfield01:11:44

The default in workspace.edn is

:tag-patterns {:stable "stable-*"
                :release "v[0-9]*"}

seancorfield01:11:58

So a prefix of "v" would work 🙂

seancorfield01:11:27

Oh, not quite, you'd need to update :release to "v-[0-9]*"

seancorfield01:11:37

Anyways, I think you've figured it out now?

licht1stein01:11:04

Changed t*o* release "release-[0-9][0-9][0-9][0-9]-*". Waiting for the CI to run, dunno yet. But I think I understand it much better for sure, thank you!

seancorfield01:11:46

There are so many knobs to adjust in Polylith 🙂 and when you add deps.edn and build.clj to the mix, you have a very flexible system!

licht1stein01:11:37

That I feel, and I'm very happy to have both 🙂

seancorfield01:11:51

Our build.clj file is nearly 500 lines 🙂

seancorfield02:11:02

(with over two dozen "tasks" in it -- I just counted the defn forms)

licht1stein02:11:29

@U04V70XH6 I understand the system now, and it helped me figure out the problem. I used the following github action to checkout the code:

- name: Checkout
        uses: actions/checkout@v2
And by default it doesn't check out the tag history. To get the tag history you need to use with fetch-depth: 0
- name: Checkout
        uses: actions/checkout@v2
        with:
          fetch-depth: 0
This finally got it working. But I'm so glad I had to chance to talk to you and actually understand it properly. Thank you!

1