-
Notifications
You must be signed in to change notification settings - Fork 16
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 Python 3 compatible packages and migrate to CircleCI 2.0 #41
Conversation
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.
Hard but necessary job! Thanks for handling it 😃 👍
deploy-if-version-bump.sh
Outdated
fi | ||
fi | ||
|
||
if [ $PY_VERSION = "3" ]; then |
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.
So if the Python version is 3
then there is no functional changes check. Is that really the goal?
setup.py
Outdated
@@ -7,7 +7,7 @@ | |||
|
|||
setup( | |||
name='OpenFisca-Country-Template', | |||
version='3.0.2', | |||
version='3.0.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.
Changelog and setup versions do not match.
I prefer the minor bump over the patch bump 🙂
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.
Done
.circleci/config.yml
Outdated
country-template: | ||
jobs: | ||
- checkout | ||
- dependencies: |
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.
What about suffixing with
_python2
like it is done with_python3
?
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.
Done
.circleci/config.yml
Outdated
context: Py2 | ||
requires: | ||
- tests | ||
- tests_python3 |
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 reads like “if I'm in Py2
context, run tests_python3
” 🤔 Is this normal?
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.
Got rid of contexts
.circleci/config.yml
Outdated
- deploy_python3: | ||
context: Py3 | ||
requires: | ||
- tests |
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 reads like “if I'm in Py3
context, run tests
(which is Python2)” 🤔 Is this normal?
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.
Got rid of contexts
.circleci/config.yml
Outdated
name: Deploy (if version bump) | ||
command: | | ||
. /tmp/venv/country-template/bin/activate | ||
. deploy-if-version-bump.sh |
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.
Unless CircleCI does something special, the .
is a non-readable equivalent of source
. I recommend we use source
over .
for readability. I also believe that . deploy-if-version-bump.sh
should not be sourced, but directly executed, and that it currently works only as a side-effect of sourcing.
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.
Done
.circleci/config.yml
Outdated
steps: | ||
- restore_cache: | ||
keys: | ||
- v1-checkout-{{ .Environment.CIRCLE_SHA1 }} |
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.
Such a key prevents the cache from having almost any use: only a rerun with cache would benefit from it.
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 it was only used to persist the files from one job to another. But yes, checksuming setup.py seems better.
.circleci/config.yml
Outdated
- image: python:3.6 | ||
|
||
deploy: &deploy | ||
working_directory: ~/country-template |
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 don't think you need to state this explicitly.
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.
Indeed we don't
.circleci/config.yml
Outdated
# pip install --editable git+https://github.com/openfisca/openfisca-core.git@BRANCH_NAME#egg=OpenFisca-Core | ||
|
||
- save_cache: | ||
# PY_VERSION is set in the context |
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.
“the context” is ambiguous. I personally don't understand where this is coming from.
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.
Got rid of that
I must say that I am a bit surprised and frustrated that my PR on CircleCI 2.0 migration (#40) has been lingering for over a week, and this one does essentially the same thing. I had already invested in this long, error-prone process, and now we have two very different implementations. @fpagnoux I'll let you have a look at both implementations and assess if it would be easier to add Python3 support on top of #40 or integrate #40's syntax refinements in this PR. How can we avoid such collaboration mishaps in the future? |
I updated the configuration to look more #40's one, which I find simpler. To handle both Python 2 and Python 3, I went for duplication over complexity.
@MattiSG let me know if that still seem too complicated for a package that aims to be cloned and re-used by many openfisca contributors. |
.circleci/deploy-python-3.sh
Outdated
|
||
set -e | ||
|
||
VERSION_CHANGE_TRIGGERS="setup.py MANIFEST.in openfisca_core openfisca_web_api_preview" |
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.
@MattiSG I'm not sure about repeating this in 3 different files, as the whole continuous publishing relies on this variable to have the same values in the 3 files.
However, I didn't manage to share it. I tried to declare it in a separate shell file and to source it from each of the 3 scripts, but the source
would not find the file (I think because relative paths in a script are always relative to where you launch the script, not where the script is).
If you know how to make it better, please proceed 🙂
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'll just extract that in a new script 😉
If you're curious, this is how I usually solve the problem.
.circleci/deploy-python-2.sh
Outdated
|
||
VERSION_CHANGE_TRIGGERS="setup.py MANIFEST.in openfisca_core openfisca_web_api_preview" | ||
|
||
if git diff-index --quiet HEAD^ -- $VERSION_CHANGE_TRIGGERS ":(exclude)*.md" |
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're only checking for changes in the last commit, not in the whole branch. Is that expected?
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.
There is a subtlety here.
We are in the context of deployment. So there is not more feature branch involved: we are on master
, and want to know if the new version of master brings any functional change compared to the last version of master. Hence the comparison with HEAD^
.
This is different when we are testing a feature branch, and running check-version-bump.sh
. In that case, we indeed want to compare our branch to the current version of master.
So we can't really share the whole detect-functional-changes.sh
as is. I'll try to find a solution though.
.circleci/deploy-python-3.sh
Outdated
|
||
set -e | ||
|
||
VERSION_CHANGE_TRIGGERS="setup.py MANIFEST.in openfisca_core openfisca_web_api_preview" |
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'll just extract that in a new script 😉
If you're curious, this is how I usually solve the problem.
@@ -16,7 +16,7 @@ | |||
url='https://github.com/openfisca/openfisca-country-template', | |||
include_package_data = True, # Will read MANIFEST.in | |||
install_requires=[ | |||
'OpenFisca-Core >= 23, < 24.0', | |||
'OpenFisca-Core >= 23.1, < 24.0', |
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.
Any reason for that change here or is it just a knight? 😛
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.
The changelog claims that we are making this package compatible with python 3.
We thus need to make sure we request a core version that is compatible with python 3.
.circleci/config.yml
Outdated
name: Check version number has been properly updated | ||
command: | | ||
git fetch | ||
./.circleci/check-version-bump.sh |
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.
No need for the
./
when you're already giving a directory path.
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 you fixed it
.circleci/config.yml
Outdated
docker: | ||
- image: python:2.7.14 | ||
environment: | ||
PYPI_USERNAME: openfisca-bot |
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.
Since this is a template, there should be a comment here about customising this value.
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.
Done
.circleci/config.yml
Outdated
- build_python2 | ||
- build_python3 | ||
- deploy_python2: | ||
requires: # Only deploy if tests passed both with Python 2 and Python 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.
This is quite readable in the config. This comment would add more value by explaining why we don't want to deploy unless both versions pass.
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, I thought it was unclear from a previous comment. Do you think we should not require the build_python2
for deploy_python3
? I guess that we are on master, so technically the tests have already passed...
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.
Removed the dependency, as it's not really necessary
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 thought it would be because we don't really want to publish a new version for only one version: I wouldn't want to deal with version 23.1.2
existing in Python3 but not in Python2 and the other way around for 23.1.3
😅
.circleci/deploy-python-2.sh
Outdated
if ! git rev-parse `python setup.py --version` 2>/dev/null ; then | ||
|
||
if ./detect-functional-changes.sh | ||
then | ||
git tag `python setup.py --version` | ||
git push --tags # update the repository 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.
I don't see the difference between Python2 and Python3 deployment beyond this initial tagging.
If indeed there is none, then I think the tagging should be done in CI (or in a script), and that the deployment should be a single script as it was. Right now, there is an apparent dependency of deployment of Python3 to deployment of Python2, which is both absurd and not guaranteed by CI; there is also unnecessary code duplication in the deployment scripts.
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.
Done
.circleci/deploy-python-2.sh
Outdated
git tag `python setup.py --version` | ||
git push --tags # update the repository version | ||
python setup.py bdist_wheel # build this package in the dist directory | ||
twine upload dist/* --username $PYPI_USERNAME --password $PYPI_PASSWORD # publish | ||
ssh -o StrictHostKeyChecking=no deploy-api@fr.openfisca.org # Deploy the OpenFisca-France public API |
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 don't understand why this is in the country template 🤔
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.
Excessive copy pasting
|
||
VERSION_CHANGE_TRIGGERS="setup.py MANIFEST.in openfisca_country_template" | ||
|
||
if git diff-index --quiet origin/master -- $VERSION_CHANGE_TRIGGERS ":(exclude)*.md" |
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.
@fpagnoux Beware, this is not the same check as it was before I factored it: please double-check based on #41 (comment) that this is the proper check we want to apply 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.
See reply on the said comment
4f95107
to
bb48902
Compare
Tests ran:
Now let's please get done with 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.
Almost there… 😉 My only real problem is with the Python2 + Python3 dependency on deployment. We need to be 100% clear on the conditions we put on making a package available to the world.
|
||
- run: | ||
name: Check for functional changes | ||
command: if .circleci/detect-functional-changes.sh ; then circleci step halt ; fi |
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.
Why don't we just .circleci/detect-functional-changes.sh
? Shouldn't deployment fail?
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.
Alright I understood. No, it should not fail, it should be green but not do anything. Gotcha.
- build_python3 | ||
- deploy_python2: | ||
requires: | ||
- build_python2 |
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 don't think we want to publish a Python2 package that does not pass Python3 builds. How would we manage a 23.1.2
tag that got published in Python2 but failed in Python3? We would then have to publish a 23.1.3
tag that would be available in both environments… So all version numbers could co-exist differently in each language 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.
OK, I misinterpreted a previous comment.
|
||
VERSION_CHANGE_TRIGGERS="setup.py MANIFEST.in openfisca_country_template" | ||
|
||
if [[ "$CIRCLE_BRANCH" == "master" ]] |
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.
No need for quotes there 😉
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
@@ -0,0 +1,4 @@ | |||
#! /usr/bin/env bash |
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.
When you're not using bash-specific instructions,
sh
is safer:bash
is an implementation with extensions whilesh
is an interface.
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'd add that usually sh
is just a pointer to bash
, but not always.
I reviewed all links and agree with all the tests. Thank you so much for this list of links, it has proven extremely useful. It is also very reassuring to see how all possible cases have been covered 👏 |
then LAST_MASTER_VERSION="HEAD^" | ||
else LAST_MASTER_VERSION="origin/master" | ||
fi | ||
last_tagged_commit=`git describe --tags --abbrev=0 --first-parent` # --first-parent ensures we don't follow tags not published in master through an unlikely intermediary merge commit |
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.
Not sure I fully understand the motive of the change.
Can you give a concrete example of a situation where the previous implem would not do its job?
One risk I can see here is if for some reason a tag is published in the middle of the feature branch. Then the script would not compare the feature branch to the last published version, but to that tag.
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 change has the technical benefit of working in both cases without needing specific logic based on the branch name.
In terms of logic, it makes the assumption that all tagged commits are published. The previous implementation made the assumption that all commits on master
are published. I am more confident that no accidental tagging will happen than no commits on master
can accidentally happen.
In the same way, if we want to unpublish a version (or mark a version as unpublished), we now simply have to remove a tag. Removing a commit on master
is harder 😉
If you want added rigidity (which would go beyond what was already the case), I'm happy to add a check for the tag to be x.y.z
, preventing preversions from being taken into account 🙂
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, fair enough.
I was thinking that under our workflow, accidental commits on master are pretty rare, if not inexistent, but we can't assume that it will be the same for all re-users.
Let's merge this as-is, and see if we need more refinement later.
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.
under our workflow, accidental commits on master are pretty rare
Totally agree! It just happens that I believe the semantics of “this version was published” are more closely aligned with “this version is tagged” than “this version was merged into master
”. Thanks to all the automation we've made, this is luckily all aligned, but I felt this implementation was both clearer and shorter 😉
Changed the workflow so that we deploy only if the two builds have passed. |
I'm changing the required CI checks to allow for merging. |
Done. |
Do not rely on master merge commits to necessarily have been tagged and published: if there is an issue there, we would enter a cycle of failing deployments
If none are detected, there will still be no output
Pew, that was painful 😅 |
Wonderful thanks ! |
Relates to openfisca/openfisca-core#630
Deployment works for Python 2 and Python 3