-
Notifications
You must be signed in to change notification settings - Fork 12
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
Fix: update release workflow to follow pypa and pypi guidelines #73
Conversation
README.md
Outdated
@@ -44,6 +44,22 @@ To use this template: | |||
as your source. You can read more about generating your project | |||
in the [copier documentation](https://copier.readthedocs.io/en/stable/generating/). | |||
|
|||
## How to run the test suite locally |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Friends, bare with me on the instructions. I'm still getting to know copier and am wrapping my head around the test suite works. it seems great as it caught some spacing issues in my workflow! I just don't fully understand it yet so if any of this isn't quite right please say the word!
i'd love review on this (but also see a merge conflict now that i just merged the other pr!! a few points of potential contention
id love your feedback here all @sneakers-the-rat @blink1073 @Midnighter i'd llike to get our template nailed down for spring workshops and then scipy if we get accepted! |
environment: | ||
name: pypi | ||
# Modify the url to be the name of your package | ||
url: https://pypi.org/p/yourPackage |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should be able to template this line, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you are right! I forgot about that. I still need to learn more about how this works with copier. i'll update the PR this week.
template/{% if use_git and dev_platform == 'GitHub' %}.github{% endif %}/workflows/release.yml
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggested a few minor things. With what you intend to do, it makes sense to turn the release pipeline into a templated file and use copier values to fill in the information. That's the bigger change.
jobs: | ||
prerequisites: | ||
uses: ./.github/workflows/test.yml | ||
|
||
release: | ||
needs: [prerequisites] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This part was responsible for running the test suite before publishing. And running the release job only when the test suite is successful. It sounds like you want that kind of behaviour (and I agree it's a good idea), just add these lines again to the jobs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i'm torn here. i LIKE this approach as it is robust. I like it best from a learning standpoint because it adds complexity to the CI job - we are calling a CI job within a CI job (reusable workflows), which is another concept for people to learn who may just be learning about tests and CI in general. I'm curious what @agriyakhetarpal and thinks about this.
weighing complexity for those new to packaging vs. a robust release process.
also pinging @ucodery @willingc on this one as it's part education, part packaging complexity but beyond packaging it's CI complexity. cognative load x 3.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think i've been convinced that this approach reduces cognative load as it allows a user to just rerun tests on release. i'll fix my change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like it best from a learning standpoint because it adds complexity to the CI job - we are calling a CI job within a CI job (reusable workflows), which is another concept for people to learn who may just be learning about tests and CI in general. I'm curious what @agriyakhetarpal and thinks about this.
weighing complexity for those new to packaging vs. a robust release process.
I would be okay with such a mechanism. However, running the tests (from a built wheel, that is) is something that I've seen more commonly used with compiled packages, and can be generally overkill with pure Python packages, especially when intended for a tutorial for beginners. I'll leave it up to you to remove or keep it. :D
name: >- | ||
Publish Python 🐍 distribution 📦 to PyPI | ||
# Modify the repo name below to be your project's repo name. | ||
if: github.repository_owner == 'pyopensci' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks to me like we need to enable templating for this workflow and insert the organization/repo owner here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This has been fixed locally! i didn't understand copier at first but now I get the jinja templating !!
template/{% if use_git and dev_platform == 'GitHub' %}.github{% endif %}/workflows/release.yml
Outdated
Show resolved
Hide resolved
template/{% if use_git and dev_platform == 'GitHub' %}.github{% endif %}/workflows/release.yml
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, @lwasser! This looks great; as promised, here's a review. I've tried to express my thought process with my suggestions, but please feel free to push back on them as you feel fit, especially for a template that's oriented towards a tutorial. Most of these comments are security-focused.
# This ensures that the publish action only runs in the main repository | ||
# rather than forks |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume that an if:
condition was probably removed from here, and the comment is a remnant?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oooh yes likely that was the case!! i put the publish step into it's own independent step for security!
template/{% if use_git and dev_platform == 'GitHub' %}.github{% endif %}/workflows/release.yml
Outdated
Show resolved
Hide resolved
|
||
- name: Build package | ||
run: hatch build | ||
# Security recommends we should pin deps. Should we pin the workflow version? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, please. I'll recommend that all GitHub Actions—whether by GitHub as an actor or external ones available on the marketplace—should be pinned to their commit hashes, at least for a workflow concerning a release. There is a case to be made about how it makes things a bit more challenging for new contributors/packagers, but I think supply-chain security shouldn't be at the end of a compromise.
There are tools such as gha-update
which can replace them with pins, that we can recommend elsewhere (not in this PR, though, of course). Once this is done, I think it's just a matter of letting Dependabot (if configured) take over, as it can handle both the upgrade and the inline version comment in its automated PRs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
great. So, looking at the action here
Ofek suggests that too - we'd use this - this hash is almost the most recent but the most recent is just a readme update.
-
name: Install Hatch
uses: pypa/hatch@a3c83abBut now we'd have to update that hash manually? How often should that update happen?
We should do that as part of this repo's maintenance, but also, we'll want to tell users to update this periodically, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
great. So, looking at the action here
Ofek suggests that too - we'd use this - this hash is almost the most recent but the most recent is just a readme update.
- name: Install Hatch
uses: pypa/hatch@a3c83ab
But now we'd have to update that hash manually? How often should that update happen?We should do that as part of this repo's maintenance, but also, we'll want to tell users to update this periodically, right?
Updating it weekly for our maintenance could be a good cadence; what do you think? It would depend on the amount of activity we have on this template.
If we were to ask our users to enable Dependabot in the GitHub settings and inherit the same settings, they should also get the same updates. However, I'm not sure whether it's too much to ask for beginners (😕).
As long as it is pinned for a start, we can proceed with a small guide on how to keep this workflow maintained, where we can describe this more (or link to an external guide if that's alright and vetted by us?).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@agriyakhetarpal this is awesome. We, I think, have Depdendabot set up in the org, I think, but I didn't configure it. This is a basic question but would it help update things like this version? IE could we use it in this repo?
My gut tells me we won't have the bandwidth to perform weekly updates here unless someone wants to take that one! But perhaps monthly or quarterly would work. I am not sure what is best, however and would love suggestions.
also if you were interested in helping us maintain here, that would be awesome (only if you have bandwidth!)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We, I think, have Depdendabot set up in the org, I think, but I didn't configure it. This is a basic question but would it help update things like this version? IE could we use it in this repo?
Oh, I notice that here are a few moving parts, here. As this file is not a workflow of its own but a template that will be generated and moved into .github/workflows/
, I am not sure if Dependabot will be able to operate on the template file as well, in addition to the workflow file. It does have a directory:
setting, which I think we should try out: https://docs.github.com/en/code-security/dependabot/working-with-dependabot/dependabot-options-reference#directories-or-directory--
That means that we have two possible scenarios:
- the GitHub Actions dependencies in this file get outdated and are not kept up to date: assuming we also ship a Dependabot configuration file with our template that will be copied (and we instruct users on how to use Dependabot), the generated workflow file will receive updates. This should be good for users, as they receive updates. However, we, as the ones shipping the template, would need to find a method to "mirror" the updates from our workflow file to the template file.
- the GitHub Actions dependencies in this file are also updated in addition to our own workflows (that would be great!)
The first one is surely not ideal, so we should explore if Dependabot will choose to be the star here or not 😉
My gut tells me we won't have the bandwidth to perform weekly updates here unless someone wants to take that one! But perhaps monthly or quarterly would work. I am not sure what is best, however and would love suggestions.
I agree with you. Monthly updates would be nicer – and users can always bump it to daily, or weekly, and so on, based on their bandwidth.
also if you were interested in helping us maintain here, that would be awesome (only if you have bandwidth!)
I'd love to! I've also helped out with the development and maintenance of especially other copier
templates, such as https://github.com/pybamm-team/pybamm-cookie – where my experience should be transferable enough for me to help out. I do have limited bandwidth, however and can't say I can work full-time on this, but I would be open to lend a hand with more reviews and occasional updates anytime :D
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok wonderful!! @agriyakhetarpal i'm going to create an issue for thiw topic specifically as it's beyon the scope of this pr and merging this would be nice!! BUT it's an important topic. So let's move your comment above to an issue.
Also i'd love to add you to our packaging council team here at pyOpenSci which will give ou more superpowers in our repos!! I"ll do that now. So happy to have you here and also happy that @Midnighter is able to help me undstand some of the technical points and updates that you have so carefully pointed out and fixed!! thank you both!
# Modify the repo name below to be your project's repo name. | ||
if: github.repository_owner == 'pyopensci' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
# Modify the repo name below to be your project's repo name. | |
if: github.repository_owner == 'pyopensci' | |
# Modify the repo name below to be your project's repo name. | |
if: github.repository == 'pyopensci/pyos-package-template' |
How would you feel about a more stringent check here, like this? The idea is to make users more careful (and it's possible that a fork of the repository within one's organisation can trigger this workflow otherwise).
template/{% if use_git and dev_platform == 'GitHub' %}.github{% endif %}/workflows/release.yml
Show resolved
Hide resolved
template/{% if use_git and dev_platform == 'GitHub' %}.github{% endif %}/workflows/release.yml
Outdated
Show resolved
Hide resolved
# Environment is encouraged for increased security | ||
environment: build |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a new one for me, so I'm curious. Could you please share how it works?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh! @agriyakhetarpal environments allow you to setup a trusted connection with pypi. This is the build environment, so we don't need to worry too much about security here in terms of PYPI. so anyone can run the build step in theory. but by having a publish environment, we can control who can trigger that step of the build. (if that is what you're asking) .
here is a bit more about this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I'm aware of trusted publishing and environments, thanks! My question was more around the need for this build
environment, as it seems to be redundant. Most release workflows can get by with just one pypi
(or publish
, or any other similar name) environment, omitting the need for an environment for the build step. Does including two environments, one for building and one for publishing, have security provisions? Moreover, I imagine that the users would also have questions around why they need (and we recommend) to set up two environments in their repository's settings, when it is only the publishing one that connects to PyPI's OIDC publishing functionalities.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh gosh my apologies. i suspected I was telling you something you already knew. 🙈
This is a great point. I don't know the answer to your question!! But i suspect this is ME introducing complexity.
i just checked the tutorials and there is a build step but not an additional environment. Shall we remove this environment as you are correct it's not required. we need the job but not an environment AFAIK .
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh gosh my apologies. i suspected I was telling you something you already knew. 🙈
No worries at all! 😄
This is a great point. I don't know the answer to your question!! But i suspect this is ME introducing complexity.
i just checked the tutorials and there is a build step but not an additional environment. Shall we remove this environment as you are correct it's not required. we need the job but not an environment AFAIK .
Thank you for dropping it!
template/{% if use_git and dev_platform == 'GitHub' %}.github{% endif %}/workflows/release.yml
Outdated
Show resolved
Hide resolved
template/{% if use_git and dev_platform == 'GitHub' %}.github{% endif %}/workflows/release.yml
Outdated
Show resolved
Hide resolved
template/{% if use_git and dev_platform == 'GitHub' %}.github{% endif %}/workflows/release.yml
Outdated
Show resolved
Hide resolved
template/{% if use_git and dev_platform == 'GitHub' %}.github{% endif %}/workflows/release.yml
Show resolved
Hide resolved
Ok i've made changes and seemingly have broken CI. I wondered if someone can help me understand how to test this locally. i tried:
|
@all-contributors please add @agriyakhetarpal for review |
I've put up a pull request to add @agriyakhetarpal! 🎉 |
Copier by default applies the template from the last tag rather than the local version. A design choice I'm not super happy with either. You will need to use the -r option with your branch name so it uses your last commit instead. |
…% endif %}/workflows/release.yml
…% endif %}/workflows/release.yml
This makes sense. Thank you, @Midnighter !!! |
well it turns out #77 fixes this pr too. I am not sure why CI was passing before 🤷🏻♀️ but the issue was pydoclint can't run without knowing where to run. |
template/{% if use_git and dev_platform == 'GitHub' %}.github{% endif %}/workflows/release.yml
Show resolved
Hide resolved
fix: update contributing
add: run pydoclint on tests too
Co-authored-by: Agriya Khetarpal <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @lwasser, thank you! I really appreciate the warmth in your responses while addressing my review comments
I'm happy to approve this PR in principle, it being a valuable step forward – even though there are a few pieces of unresolved conversations at the moment.
# Environment is encouraged for increased security | ||
environment: build |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh gosh my apologies. i suspected I was telling you something you already knew. 🙈
No worries at all! 😄
This is a great point. I don't know the answer to your question!! But i suspect this is ME introducing complexity.
i just checked the tutorials and there is a build step but not an additional environment. Shall we remove this environment as you are correct it's not required. we need the job but not an environment AFAIK .
Thank you for dropping it!
template/{% if use_git and dev_platform == 'GitHub' %}.github{% endif %}/workflows/release.yml
Outdated
Show resolved
Hide resolved
|
||
- name: Build package | ||
run: hatch build | ||
# Security recommends we should pin deps. Should we pin the workflow version? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We, I think, have Depdendabot set up in the org, I think, but I didn't configure it. This is a basic question but would it help update things like this version? IE could we use it in this repo?
Oh, I notice that here are a few moving parts, here. As this file is not a workflow of its own but a template that will be generated and moved into .github/workflows/
, I am not sure if Dependabot will be able to operate on the template file as well, in addition to the workflow file. It does have a directory:
setting, which I think we should try out: https://docs.github.com/en/code-security/dependabot/working-with-dependabot/dependabot-options-reference#directories-or-directory--
That means that we have two possible scenarios:
- the GitHub Actions dependencies in this file get outdated and are not kept up to date: assuming we also ship a Dependabot configuration file with our template that will be copied (and we instruct users on how to use Dependabot), the generated workflow file will receive updates. This should be good for users, as they receive updates. However, we, as the ones shipping the template, would need to find a method to "mirror" the updates from our workflow file to the template file.
- the GitHub Actions dependencies in this file are also updated in addition to our own workflows (that would be great!)
The first one is surely not ideal, so we should explore if Dependabot will choose to be the star here or not 😉
My gut tells me we won't have the bandwidth to perform weekly updates here unless someone wants to take that one! But perhaps monthly or quarterly would work. I am not sure what is best, however and would love suggestions.
I agree with you. Monthly updates would be nicer – and users can always bump it to daily, or weekly, and so on, based on their bandwidth.
also if you were interested in helping us maintain here, that would be awesome (only if you have bandwidth!)
I'd love to! I've also helped out with the development and maintenance of especially other copier
templates, such as https://github.com/pybamm-team/pybamm-cookie – where my experience should be transferable enough for me to help out. I do have limited bandwidth, however and can't say I can work full-time on this, but I would be open to lend a hand with more reviews and occasional updates anytime :D
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left some more minor comments, but don't want to stand in the way of what is generally a great improvement 🙂.
template/{% if use_git and dev_platform == 'GitHub' %}.github{% endif %}/workflows/release.yml
Outdated
Show resolved
Hide resolved
template/{% if use_git and dev_platform == 'GitHub' %}.github{% endif %}/workflows/release.yml
Outdated
Show resolved
Hide resolved
Co-authored-by: Agriya Khetarpal <[email protected]>
Co-authored-by: Agriya Khetarpal <[email protected]>
Co-authored-by: Moritz E. Beber <[email protected]>
Ok friends!! ✅ i've got two checks of approval here so I think we can merge! But let's let ci run after I merged the last inline changes suggested! I'll go ahead and merge this once CI finishes (or someone else can!). Then we can decide what's next. I think documentation is likely going to be an important focus in the future! |
this closes #48 We've been working with the pypa and pypi security folks on our blog post and this pr should address the suggested approaches to publishing using a release based workflow.
Because we are using a release, this assumes that tests are running on the main branch before a release is made. It also allows a dynamic maintainer team to make releases without the command line which is really nice.
NOTE: i haven't yet tested this specific file for issues. i'm not quite sure how - maybe via test pypi?