clj-commons/clj-http-lite

Prep for 1.0 release

lread opened this issue · 19 comments

lread commented
  1. move to 1.0.<release count> based off a ./version.edn (same idea as etaoin and rewrite-clj).
    We'll count releases from current maven coordinates, so our next release will likely be 1.0.5.
  2. ensure correct files are being updated with the release version
  3. also automatically check/update changelog

Optional:

  1. automate creation of GitHub release (I do this for my other projects, can see if I can do here too).
  2. add in bb task for cljdoc preview (can steal from my other projects)
  3. move from text to badges for contributors (can also steal this work from other projects)
lread commented

Actually not hard to count all clj-http-lite releases:
4 from hiredman
4 from martinklepsch
4 from org.clj-commons

12 past releases, so we'll likely start with 1.0.13

lread commented

I spent a little time looking at GitHub Actions and how workflows are triggered.

Our current strategy is to update versions in files locally, create a version tag and push the tag and commits up to GitHub.

Although we'd rather not trigger our deploy job, it does get triggered and we programmatically check if we should really deploy.

We can do better by telling GitHub Actions not to trigger the deploy job when there is no Release-* tag. I see 2 ways to do this.

  1. add in an if on the deploy job: if: ${{ startsWith(github.ref, 'refs/tags/Release-') }}.
  2. split out deploy job to its own workflow that is triggered on Release-* tags and have it depend on tests job.

I like option 2, it seems clearer to me.

I also toyed with avoiding tests being run twice on release by trying atomic commits (example git push --atomic origin main Release-1.0.8). But GitHub Actions still sees the separate events of a commit and a tag and will trigger jobs/workflows on those.

I don't have this problem on my other projects because I trigger a deploy on GitHub Actions via a user-initiated Release workflow. It does all the work of a release in the action, including bumping versions, updating files, etc. But this release workflow is triggered via the GitHub Actions GUI, which some find non-obvious.

lread commented

Perhaps not popular, but I think I'll start with my personal preference:

I don't have this problem on my other projects because I trigger a deploy on GitHub Actions via a user-initiated Release workflow. It does all the work of a release in the action, including bumping versions, updating files, etc. But this release workflow is triggered via the GitHub Actions GUI, which some find non-obvious.

I'll leave in the bb publish task that will give brief instructions and point to maintainers guide.

@lread

We can do better by telling GitHub Actions not to trigger the deploy job when there is no Release-* tag. I see 2 ways to do this.

I've actually been through this and ended up where we are now after messing with some of the things you suggested. I suggest we just leave things that work and not change for the sake of changing things, unless there bugs or clear wins. Pushing a tag to release is done in a similar way for other clj-commons projects.

lread commented

Thanks for the reply @borkdude, I see your concern and see it as entirely valid.

I too invested time in messing around with these options on a test project yesterday.

Option 1: Carry on with client-side update and tag push

Pro:

  • consistency with other clj-commons projects

Con:

  • release work is partly done on dev box and completed on ci
  • deploy job is invoked when there is no deploy, this is confusing (it can look like we deploy on every commit but we do not)
  • workflow invoked twice for release 1) tests -> deploy (no) 2) tests -> deploy (yes)

Option 2: Option 1 without invoking deploy job when there is no deploy

Pro:

  • release invoked same way as other clj-commons projects
  • deploy job shows as skipped when there is no deploy (this is less confusing when looking at GitHub actions runs)

Con:

  • release work is partly done on dev box and complete on ci
  • minor inconsistency with other clj-commons projects
  • workflow invoked twice for release 1) tests -> deploy (skip) 2) tests -> deploy (not skipped)

Option 3: Option 2 but separate deploy to release workflow

Pro:

  • release invoked same way as other clj-commons projects
  • deploy workflow is not invoked when there is no deploy (even clearer than option 2)
  • separating the release to a different workflow allows clojars secrets to be available only to that workflow.

Con:

  • a little more inconsistent with other clj-commons projects
  • tests invoked twice for release 1) tests 2) release (which invokes tests as dependency)

Option 4: Carry out release entirely on CI

Pro:

  • tests not invoked twice for release workflow
  • separating the release to a different workflow allows clojars secrets to be available only to that workflow.
  • subjective: easier to grok. Release work happens in one place: CI.
  • not dependent on the state of git repo on your dev box
    • no concern if you have uncommitted work or unpushed commits

Con:

  • inconsistent with other clj-commons projects

My Preference

I personally really like the simplicity of doing all the work of the release up on CI.
I have release flows that release this way for etaoin, rewrite-clj, and test-doc-blocks.

My preference is option 4 but I realize I'm working on teams that might not agree with this.
I feel I can get away with my preference when I am the primary maintainer, which is currently the case for etaoin, rewrite-clj, and test-doc-blocks.

I think one con of 4 that hasn't been mentioned is that the CI deploy is a bit tied together with Github Actions and makes it more difficult to build a redundant CI (like babashka has, it currently uses 3 CI systems).

Anyway, I don't want to die on this hill and if you insist very strongly, go with 4.

lread commented

Yes, good point. The git tag as a release trigger is universal and CI vendor agnostic. So 4
is not only redundancy-unfriendly but also has vendor lock-in (or more to figure out if switching to a different CI vendor).

Another pro of 4 is that it can be a bit more atomic; if the release to clojars does not work the flow will not commit any changes back to the repo.

lread commented

Anyway, I don't want to die on this hill and if you insist very strongly, go with 4.

I have preferred option 4, but I also want to be a good teammate/citizen, which might make me reconsider for this and other projects.

Do you have any strong objections to Options 2 or 3?

I don't have strong objections to any of the above (although I would probably not choose 4 for projects I find redundant CI important for, which probably doesn't hold for this project). In fact, I don't find working on changing this important enough with the risk of introducing new problems, since it already worked fine.

This:

Screenshot 2022-08-28 at 17 55 48

lread commented

Yeah, when I first read that it stunned me a bit, but I think that makes good sense for the Clojure core team where stability is paramount. And also the core team is so very careful in what they add.

But I'll change things in my projects for other reasons, like maintainability and grokability. For examples, on etaoin we defined the public API to reduce the maintenance burden, and here we got rid of babashka-specific conditional code which was no longer needed.
And I seem to introduce bb tasks everywhere.

I'll leave it up to you ;-).

I'm a little grumpy today, forgive me for being annoying.

lread commented

Apologies, I was oblivious to your grumpiness!
All I felt was an interesting discussion with a smart person I respect.

I think I've overcome my grumpiness and I still prefer the tag-push release over "log into some UI I don't know and press a button". But what's most important to me is that people like @slipset know how to deploy in case any of us are not around, like just happened with clj-commons/clj-yaml.

If I were to weigh in, as I guess I am doing :) I really prefer the solution of releasing by somehow creating and pushing a release tag. This way, maintainers like me don't have to care about how the release happens, just that it does happen.

Also, it is beneficial in so far that we then always remember to tag releases, which is great because tools like Github then produces release bundles of the repo.

In a way, you could even argue that this is a declarative, rather than an imperative approach. We just declare that this commit is version whatever, and someone else makes it so.

As it happens, I tend to log into GitHub, and create the release tag from there :)

lread commented

Thanks for chiming in @slipset, much appreciated!

When I hit friction, I sometimes move on for a bit to any of my many other OSS interests. When things become not-fun, I can refresh by do something that is more enjoyable. It's such a luxury to be able to do that!

My personal opinion is that the main downside to option 4 for this project is that it is not invoked from command line. It is otherwise doing the same work (and also creates that GitHub release 🙂).

I will come back sometime soon, likely rework my commit to conform to a tag triggered release approach (likely Option 3) and finally push the PR.

More on separating out a release workflow:

When there was that security issue with codecov.io, it made me wonder if I should be doing something different. I moved my clojars creds to a github actions "environment" and only permitted my existing separate release workflow access to that environment.

I also minimized the work that sees the clojars secrets to the work that needs it; the actual deploy to clojars. I'll keep this is mind too, but since less release work is happening up on ci, it may be less of an issue here.