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

Add major-minor-release workflow #45

Draft
wants to merge 8 commits into
base: unstable/v1
Choose a base branch
from
Draft
Changes from 3 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
51 changes: 51 additions & 0 deletions .github/workflows/publish-major-minor.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
name: "Publish Major-Minor-Tags"
on:
push:
Copy link
Member

Choose a reason for hiding this comment

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

Honestly, I'm lately preferring the create event because it has closer semantics to what we're attempting to trigger. But using it requires a post-condition.

WDYT?

Copy link
Author

Choose a reason for hiding this comment

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

I mostly use push due to sheer habit, there were a lot fewer triggers (at least in the docs) when I started adopting gh-actions as soon as they came out of beta.
The docs are kinda unclear on how to use it, would simply changing push for create work? Or what is the proper pattern, only to trigger on tags that start with v

I guess semantically the closes would be to use release.

on:
  release:
    types: [published]

I use this trigger for my actions and it works fine, but I'm not sure how this will play out with dev, pre and post tags, since those will most likely not published.
The other release type to use would be created, which wouldn't force one to release on the markedplace, but it could still happen by accident (I think to remember that the checkbox is checked by default after fist publishing).

Copy link
Member

Choose a reason for hiding this comment

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

The usage of create is
It's

on:
  create:

jobs:
  job-name:
    if: github.event.ref_type == 'tag'  # to filter out branch creation

(because it doesn't have "native" filters)

I usually create the tags using local Git and push them from CLI. And only after that I publish releases. So I'm not sure if release would be suitable. OTOH this workflow could auto-publish a release on tag creation. You already have a way of saying if the "pre-release" checkbox should be set.

Also, I'm fine with publishing pre-releases to Marketplace. I've done it before.
See https://github.com/pypa/gh-action-pypi-publish/releases/tag/v1.0.0a0 — it has a pre-release checkbox. And it's marketplace page https://github.com/marketplace/actions/pypi-publish?version=v1.0.0a0 also has a pre-release marker, just like PyPI.

Copy link
Author

Choose a reason for hiding this comment

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

I think auto-publishing is a bit too much automation since the release messages often need some handcrafted work. e.g. markdown formatting, which can't be extracted from the tag.

As for the published event, I don't know how github determines what the current release is, my guess is that it sorts them by published date. If that assumption is correct a post release could mess up what version is displayed on the marketplace. E.g. you have a v2.0.0 release and after that release v1.4.1.post0 to trigger the workflow, v1.4.1.post0 might be shown a current version. So IMHO [created, edited] would be closer to the desired behavior.
Also using release would make it more reasonable to add a link to the release to the created tags (see #45 (comment)).

As for the semantics of create vs. push, I think this boils down to different reference systems remote vs. locally (sorry physics student here 😆 ).
I personally prefer the more concise syntax of push, where

on:
  push:
    tags:
      - "v*"

gives you the same functionality as

on:
  create:

jobs:
  job-name:
    if: github.event.ref_type == 'tag' && startsWith( github.ref, 'v')

Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure about the markdown part. First of all, it's possible to have tag annotations with markdown baked-in but I wouldn't care about it too much: when you mark a release as published to the Marketplace, the new version appears there but the release description does not show up there. Instead, it just contains README content.
So it's okay to just auto-publish and then, if needed, I'd just correct it.
FWIW we shouldn't care about ordering the tags: it'll be like this regardless of whether a robot or a human makes the release... And we're not going to avoid putting .post tags on the marketplace while moving the major tag there in Git.

tags:
- "v*"

jobs:
push-tags:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python 3.8
uses: actions/setup-python@v2
with:
python-version: 3.8
Comment on lines +12 to +15
Copy link
Member

Choose a reason for hiding this comment

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

I guess it's time to bump this

Suggested change
- name: Set up Python 3.8
uses: actions/setup-python@v2
with:
python-version: 3.8
- name: Set up Python 3.9
uses: actions/setup-python@v2
with:
python-version: 3.9

- name: Install packaging
run: python -m pip install -U packaging --user
- name: Get versions
id: get_versions
shell: python
run: |
from packaging.version import parse

tag_ref = "${{ github.ref }}"
tag_name = tag_ref.split("/")[-1]
version = parse(tag_name)
print(f"tag_name: {tag_name}")
print(f"version: {version}")
if not version.is_prerelease:
print("Creating new major and minor tags!")
print(f"::set-output name=original_tag_name::{tag_name}")
print(f"::set-output name=major_version::v{version.major}")
print(f"::set-output name=minor_version::v{version.major}.{version.minor}")
else:
print("No tags created (dev or pre version)!")
s-weigand marked this conversation as resolved.
Show resolved Hide resolved

s-weigand marked this conversation as resolved.
Show resolved Hide resolved
- name: Push Tags Version
s-weigand marked this conversation as resolved.
Show resolved Hide resolved
if: steps.get_versions.outputs.original_tag_name != ''
s-weigand marked this conversation as resolved.
Show resolved Hide resolved
env:
original_tag_name: ${{ steps.get_versions.outputs.original_tag_name }}
major_version: ${{ steps.get_versions.outputs.major_version }}
minor_version: ${{ steps.get_versions.outputs.minor_version }}
run: |
git config user.email 'github-actions[bot]@users.noreply.github.com'
git config user.name 'github-actions[bot]'
git tag --annotate '${{ env.major_version }}' \
--message='original tag: ${{ env.original_tag_name }}'
Copy link
Member

Choose a reason for hiding this comment

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

have you considered appending the message from the original tag too?

Suggested change
--message='original tag: ${{ env.original_tag_name }}'
--message='original tag: ${{ env.original_tag_name }}' \
--message="$(git tag -l --format='%(contents)' '${{ env.original_tag_name }}')"

Copy link
Author

Choose a reason for hiding this comment

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

This would only work as intended if the tag had an additional message to it or?
E.g. v1.4.0 works fine

$ git tag -l --format='%(contents)' 'v1.4.0'
Merge PR #39

This change exposes an extra GitHub Action input called `verbose`. It
allows to see `twine upload` detailed output if needed for debugging.

while v1.4.1 doesn't

$ git tag -l --format='%(contents)' 'v1.4.1'
v1.4.1
-----BEGIN PGP SIGNATURE-----
.
.
.
-----END PGP SIGNATURE-----

IMHO adding a link to the release would be more informative.

Copy link
Member

Choose a reason for hiding this comment

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

In the second case, v1.4.1 is also an additional message because all signed tags are also annotated. While I understand the sentiment of having a link, I'm not sure if it could be achieved easily. Another thing that would be useful is the commit hash where the tag points at (security-wise).

Copy link
Author

Choose a reason for hiding this comment

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

With some conditions, creating a link would be pretty straight forward:

  • release name always needs to be the same as tag name
  • workflow triggers on
    on:
      release:
       types: [created, edited]

If those conditions are met, the link would be
https://github.com/pypa/gh-action-pypi-publish/releases/tag/${{ env.original_tag_name }}

As for adding the SHA1 of the commit, this only provides additional information in a CLI context, since the github website already points to the underlying commit (see test tag v2.0.0).

Copy link
Member

Choose a reason for hiding this comment

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

As for adding the SHA1 of the commit, this only provides additional information in a CLI context, since the github website already points to the underlying commit (see test tag v2.0.0).

Besides being a pointer, it's also proof that it was created by the workflow and not manually, overriding it to some malicious commit.

git tag --annotate '${{ env.minor_version }}' \
--message='original tag: ${{ env.original_tag_name }}'
git push origin '${{ env.major_version }}' --force-with-lease
git push origin '${{ env.minor_version }}' --force-with-lease
s-weigand marked this conversation as resolved.
Show resolved Hide resolved
s-weigand marked this conversation as resolved.
Show resolved Hide resolved