Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Publish snapshots by default and add an override for hash releases #86

Open
wants to merge 7 commits into
base: main
Choose a base branch
from

Conversation

vasilmkd
Copy link
Contributor

@vasilmkd vasilmkd commented Dec 13, 2021

@armanbilge and I worked on this after discussing SNAPSHOT releases with other maintainers on Discord. We think this is generally desired by people.

By combining both the hash and the -SNAPSHOT suffix, we believe we can achieve a sensible middle ground where snapshots are mutable but not actually mutated (unless the user goes out of their way to make sure the hash matches a previous version), so this helps with the stability, maven central is not polluted (this doesn't at all affect tagged releases and they can still be done manually) and maintainers have a steady stream of stable snapshots to test stuff and look for regressions.

@vasilmkd
Copy link
Contributor Author

The question remains, can this work out of the box with the CI release mode of sbt-spiewak, because that accesses PGP_SECRET and what not, and this is not strictly required for SNAPSHOT releases.

@armanbilge
Copy link
Contributor

That's a very good point. I forgot Some People™ don't use CI publishing for the real releases, and therefore probably won't have the PGP_SECRET set. You are right, it will fail on this workflow step:

      - name: Import signing key
        run: echo $PGP_SECRET | base64 -d | gpg --import

https://github.com/typelevel/fs2/blob/144eccc216e5195a7f3c988080dee28a2a6b9db2/.github/workflows/ci.yml#L145

I wonder if we could make that step conditional, but I don't know on what. In fact, I suspect that solving this problem is nearly equivalent to solving the current problem where you tag a release with snapshots enabled it will try to publish the release twice. Essentially, one of those CI runs is for the snapshot, and if it could somehow know that it could avoid both these issues.

@vasilmkd
Copy link
Contributor Author

Conditional on the new override? If it's false (the default, so SNAPSHOTs are released), don't execute that command and vice versa.

Essentially, one of those CI runs is for the snapshot, and if it could somehow know that it could avoid both these issues.
Is this not a problem as things stand even without this PR?

@armanbilge
Copy link
Contributor

Yes, this is a general problem, which is a CI run doesn't know whether it's for an ordinary push or for a tag. Actually here's one way to solve it.

on:
  pull_request:
    branches: ['**']
  push:
    branches: ['**']
    tags: [v*]

These are the triggers for the workflow. So we could actually just duplicate the workflow, have one run on branch push, and the other one run on tag, and then it becomes possible to modify it for each case. It's really annoying to have duplicate workflows, but at least it's auto-generated.

@armanbilge
Copy link
Contributor

Conditional on the new override? If it's false (the default, so SNAPSHOTs are released), don't execute that command and vice versa.

If we generate a separate workflow for on branch push and on tag push, the branch push workflow can remove the PGP step if that setting is false.

@armanbilge
Copy link
Contributor

Aha, here's something much easier than that.

GITHUB_REF_TYPE: The type of ref that triggered the workflow run. Valid values are branch or tag.

https://docs.github.com/en/actions/learn-github-actions/environment-variables

@vasilmkd
Copy link
Contributor Author

On tag, run the tag release, on branch run a snapshot?

@vasilmkd
Copy link
Contributor Author

This still doesn't cover the hash releases as snapshots. Or am I missing something?

@armanbilge
Copy link
Contributor

armanbilge commented Dec 13, 2021

Assuming that the user wants -SNAPSHOT releases for their branch pushes, but NO ci release for their tag pushes, we just need to add a conditional:

  publish:
    name: Publish Artifacts
    needs: [build]                               # vvvvvvvvvvvvv
    if: github.event_name != 'pull_request' && env.GITHUB_REF_TYPE == 'branch' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/main' || github.ref == 'refs/heads/series/2.5.x')

That way it skips the publish step for tag pushes. We'd do the same thing for the PGP step:

      - name: Import signing key
        if: env.GITHUB_REF_TYPE == 'tag'
        run: echo $PGP_SECRET | base64 -d | gpg --import

@vasilmkd
Copy link
Contributor Author

I guess that works. Btw, env.GITHUB_REF_TYPE is the same as github.ref_type (same for all other env variables, e.g. github.event_name == env.GITHUB_EVENT_NAME).

@vasilmkd
Copy link
Contributor Author

Assuming that the user wants -SNAPSHOT releases for their branch pushes, but NO ci release for their tag pushes, we just need to add a conditional

I just realized, if they want tag or hash releases, they need to set up the PGP_SECRET, there is no way around it. So I think this should work.

@vasilmkd
Copy link
Contributor Author

Ah but not really?

      - name: Import signing key
        if: env.GITHUB_REF_TYPE == 'tag'
        run: echo $PGP_SECRET | base64 -d | gpg --import

This wouldn't run for hash releases.

@armanbilge
Copy link
Contributor

Right, so we only add that conditional to the generated YAML if the user has indicated they want -SNAPSHOT releases. If they want stable hash releases, we don't add that.

@vasilmkd
Copy link
Contributor Author

Which means that sbt-github-actions needs to know about the setting...

@armanbilge
Copy link
Contributor

Don't think so, it's needed here:

githubWorkflowPublishPreamble +=
WorkflowStep.Run(
List("echo $PGP_SECRET | base64 -d | gpg --import"),
name = Some("Import signing key")

@armanbilge
Copy link
Contributor

So just for my own clarification, we have three release modes:

  1. -SNAPSHOT "snapshot" releases
  2. stable "hash" releases
  3. tag "v" releases

With these, there are 6 configurations for CI?

branch push tag push example user
do nothing do nothing
snapshot do nothing Cats Effect
hash do nothing
do nothing v
snapshot v fs2
hash v

@vasilmkd
Copy link
Contributor Author

vasilmkd commented Dec 13, 2021

Assuming that the user wants -SNAPSHOT releases for their branch pushes, but NO ci release for their tag pushes, we just need to add a conditional:

  publish:
    name: Publish Artifacts
    needs: [build]                               # vvvvvvvvvvvvv
    if: github.event_name != 'pull_request' && env.GITHUB_REF_TYPE == 'branch' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/main' || github.ref == 'refs/heads/series/2.5.x')

That way it skips the publish step for tag pushes. We'd do the same thing for the PGP step:

      - name: Import signing key
        if: env.GITHUB_REF_TYPE == 'tag'
        run: echo $PGP_SECRET | base64 -d | gpg --import

This seems a bit complicated. Would a separate workflow for snapshots and a separate workflow for releases be simpler?

Especially this part, which I believe right now comes from sbt-github-actions?

needs: [build]                               # vvvvvvvvvvvvv
    if: github.event_name != 'pull_request' && env.GITHUB_REF_TYPE == 'branch' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/main' || github.ref == 'refs/heads/series/2.5.x')

@armanbilge
Copy link
Contributor

IDK, we might have to shave this yak first:

Ooph you are right, this might be an sbt-gh-actions thing 😓

@vasilmkd
Copy link
Contributor Author

I mean, as a stopgap, the release step can be behind a condition, and that one is here.

@armanbilge
Copy link
Contributor

It'll be a bit confusing in the UI to see an empty publish job succeed, but otherwise a good idea!

@vasilmkd
Copy link
Contributor Author

vasilmkd commented Dec 13, 2021

It'll be a bit confusing in the UI to see an empty publish job succeed, but otherwise a good idea!

This is how sbt-github-actions works out of the box.

https://github.com/djspiewak/sbt-github-actions/actions/runs/1531278166

@armanbilge
Copy link
Contributor

Oh, interesting, I didn't know that.

@vasilmkd
Copy link
Contributor Author

How does releasing snapshots without releasing tagged releases work currently? What's the discriminator?

@armanbilge
Copy link
Contributor

Actually, I don't think that capability exists as of now. You buy into CI release first, and then optionally into hash releases.

@vasilmkd vasilmkd marked this pull request as draft December 13, 2021 15:16
@vasilmkd
Copy link
Contributor Author

@armanbilge Can you maybe take this for a spin? I will release a SNAPSHOT. 😉

@armanbilge
Copy link
Contributor

    val gpgWarnOnFailure = settingKey[Boolean](
      "If true, only issue a warning when signing fails. If false, error " +
        "and fail the build. Defaults to true in publishLocal, false in publish.")

We should set this to true when the version is a -SNAPSHOT.
https://github.com/jodersky/sbt-gpg/blob/efcba49fc9d8e07d84f05b5d48386f72bbb81e1a/src/main/scala/SbtGpg.scala#L14

@vasilmkd
Copy link
Contributor Author

Ok cool. Good find.

@vasilmkd
Copy link
Contributor Author

@armanbilge Can you try the following snapshot please? 0.23-11-4c9ab83-SNAPSHOT. Thanks.

@vasilmkd vasilmkd marked this pull request as ready for review December 13, 2021 19:09
@vasilmkd
Copy link
Contributor Author

Do you mind also testing a tagged release?

@armanbilge
Copy link
Contributor

The snapshot worked! https://s01.oss.sonatype.org/content/repositories/snapshots/com/armanbilge/schrodinger_3/0.3-2-3fc5aaf-SNAPSHOT/

Time for 0.3.0-M2 😆

@armanbilge
Copy link
Contributor

0.3.0-M2 is on it's way to maven 🚀 nice work!!!

@vasilmkd
Copy link
Contributor Author

I can publish a snapshot to get things rolling?

@armanbilge
Copy link
Contributor

What do you have in mind? 😁

@vasilmkd
Copy link
Contributor Author

I found another issue, with publishHash and then sonatypeBundleRelease.

@vasilmkd
Copy link
Contributor Author

  private def sonatypeBundleReleaseIfRelevant: Command =
    Command.command("sonatypeBundleReleaseIfRelevant") { state =>
      val isSnap = state.getSetting(isSnapshot).getOrElse(false)
      if (!isSnap)
        Command.process("sonatypeBundleRelease", state)
      else
        state
    }

@vasilmkd
Copy link
Contributor Author

isSnapshot is now almost always true.

@armanbilge
Copy link
Contributor

Sorry, I couldn't understand what the problem is?

@vasilmkd
Copy link
Contributor Author

vasilmkd commented Dec 13, 2021

From sbt-sonatype:

    sonatypeBundleDirectory := {
      (ThisBuild / baseDirectory).value / "target" / "sonatype-staging" / s"${(ThisBuild / version).value}"
    },

and the error is the following:

java.io.IOException: Supplied file /Users/vasil/Code/sbt-spiewak/target/sonatype-staging/0.23-11-4c9ab83-SNAPSHOT is a not an existing directory!
        at org.sonatype.spice.zapper.fs.AbstractDirectory.<init>(AbstractDirectory.java:32)
        at org.sonatype.spice.zapper.fs.DirectoryIOSource.<init>(DirectoryIOSource.java:68)
        at org.sonatype.spice.zapper.fs.DirectoryIOSource.<init>(DirectoryIOSource.java:59)
        at org.sonatype.spice.zapper.fs.DirectoryIOSource.<init>(DirectoryIOSource.java:50)
        at xerial.sbt.sonatype.SonatypeClient.$anonfun$uploadBundle$2(SonatypeClient.scala:284)
        at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.java:23)
        at scala.util.Try$.apply(Try.scala:213)
        at wvlet.airframe.control.Retry$RetryContext.runInternal(Retry.scala:268)
        at wvlet.airframe.control.Retry$RetryContext.run(Retry.scala:253)
        at xerial.sbt.sonatype.SonatypeClient.uploadBundle(SonatypeClient.scala:269)
        at xerial.sbt.sonatype.SonatypeService.uploadBundle(SonatypeService.scala:73)
        at xerial.sbt.Sonatype$.$anonfun$sonatypeBundleRelease$2(Sonatype.scala:181)
        at xerial.sbt.Sonatype$.withSonatypeService(Sonatype.scala:437)

version ends with a -SNAPSHOT, and the hash release doesn't.

@armanbilge
Copy link
Contributor

Right, it seems like publishHash should drop -SNAPSHOT from the version number and proceed from there? IDK how easy that is...

@vasilmkd
Copy link
Contributor Author

publishHash does drop it already. The problem is, this is not then communicated to sonatypeBundleRelease.

@armanbilge
Copy link
Contributor

Ooh 😮

@vasilmkd
Copy link
Contributor Author

The problem is that publish and releases "should be" separate steps.

@vasilmkd
Copy link
Contributor Author

Here's a hash release:

addSbtPlugin("io.vasilev" % "sbt-spiewak-sonatype" % "0.23-12-4067672")

No snapshot resolver necessary.

@vasilmkd
Copy link
Contributor Author

@armanbilge Can you try releasing a hash with this version too? The steps are sbt publishHasIfRelevant sonatypeBundleReleaseIfRelevant.

@armanbilge
Copy link
Contributor

I've actually never released anything locally 😆 I'm not sure I know how.

@vasilmkd
Copy link
Contributor Author

You need to have gpg set up. Don't bother if you haven't yet. I released the hash using the plugin, so it works.

@armanbilge
Copy link
Contributor

What I can do easily, is toggle the setting so CI can release a stable hash instead. Would that be helpful?

@vasilmkd
Copy link
Contributor Author

Actually yes, that's a good scenario to try. Thanks.

@vasilmkd
Copy link
Contributor Author

What we should discuss again though is, should we flip everything, keep the old sbt-spiewak behavior exactly as it is, and instead add a publishSnapshot/releaseSnapshot that only releases a snapshot. We can still tweak the GHA yaml to cover that case.

@armanbilge
Copy link
Contributor

I think that's a Daniel vs the world question 😅 IDK if anybody likes the current default.

@armanbilge
Copy link
Contributor

What I can do easily, is toggle the setting so CI can release a stable hash instead. Would that be helpful?

Forgot to followup, this worked for me 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants