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

tweaks for CI and CD #9

Merged
merged 2 commits into from
Apr 2, 2017
Merged
Changes from all 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
6 changes: 3 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
.*
!.gitignore
*.pyc
__pycache__/
build/
!.travis.yml
dist/
*.egg-info/
44 changes: 44 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
language: python

python: "3.4"

# build sdist
script: make build

# install twine for uploading to PyPI
before_deploy: pip install twine

deploy:

# create github release
- provider: releases

# GitHub access token
api_key:
secure: "Hv2ICkPkC7hiRw8GS9adkEcfoYGeVPbGHRNPQdGxLTeP1Mz9x/2ylUprrb2Ohq+pHGRa1W55nSJAZWHto4L/seWS17vN1JB1o71KYeD8h4Ywm/iJzYJFu4v8cmuT9qMPC89GtSGUkEZml+Vd6lb6d/eBr7HWoAMF7LCobzVvpJftgSBqkN1Z0aaunGNRtPVaqf0D4iQMSU1e0X9HFyIsxjS68sNqVcU/eSqbkHQ32COliOdEZXDqNmoJjIq4NYVH7DCS4kSpfxSd3BkJPn1UH4891MntflMllH7khmSA0lqSuunp+olfzhzchYb0/e0LavqYyFU/cRemyt8RBuE0GD3J3TMudVav/5HLKt6/exZwqfv7bHyorDXkkKGJqYNPUCOD2K4RS4ExpUU5c5en5inJZdgKYVI9gZS15oXmKV3H/8JkJPgx0xRP1Rx8niQKezKdFb0dZxArbMBUuAnolgyoq2EgnsNYhboRWXoJP36FCWFn8U8UNUfmgOkkMcP59mZ6svznxWPIyCMhfGgShY03GTvPp94P6c6OZJpjyjmWyPsvGZJrvnRlJ8VxBaUBcfuQl9rtBorwJ3VI1VWguyBaSINM6OWPtEJ0J2oVM/8Dvjuw2qPNkCdUhflc7wV/AUYB9/6rfpjY+GwTEKtZBBw4epbZX/B0L+vdRONZJ0Q="

# enable wildcards in filenames
file_glob: true

# upload sdist
file: dist/*

# avoid stashing sdist
skip_cleanup: true

# create releases on tags only
on:
tags: true

# deploy to PyPI
- provider: script

# upload sdist to PyPI
script: twine upload -u $PYPI_USERNAME -p $PYPI_PASSWORD dist/*

# avoid stashing sdist
skip_cleanup: true

# deploy on tags only
on:
tags: true
52 changes: 16 additions & 36 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,42 +1,22 @@
BUILD_DIR = build
DESCRIPTION = CS50 Library for Python
MAINTAINER = CS50 <[email protected]>
NAME = python-cs50
OLD_NAME = lib50-python
VERSION = 1.3.0

.PHONY: bash
bash:
docker run -i --rm -t -v "$(PWD)":/root cs50/cli

.PHONY: build
build: clean
mkdir -p "$(BUILD_DIR)"/usr/lib/python2.7/dist-packages/cs50
cp src/* "$(BUILD_DIR)"/usr/lib/python2.7/dist-packages/cs50
mkdir -p "$(BUILD_DIR)"/usr/lib/python3/dist-packages/cs50
cp src/* "$(BUILD_DIR)"/usr/lib/python3/dist-packages/cs50
python setup.py sdist

.PHONY: clean
clean:
rm -rf "$(BUILD_DIR)"
rm -rf *.egg-info dist

.PHONY: install
install: build
pip install dist/*.tar.gz

.PHONY: push
push:
git push origin "v$$(python setup.py --version)"

.PHONY: release
release: tag push

.PHONY: deb
deb: build
fpm \
-C "$(BUILD_DIR)" \
-m "$(MAINTAINER)" \
-n "$(NAME)" \
-p "$(BUILD_DIR)" \
-s dir \
-t deb \
-v "$(VERSION)" \
--after-install after-install.sh \
--conflicts "$(NAME) (<< $(VERSION)), $(OLD_NAME)" \
--deb-no-default-config-files \
--depends python \
--depends python3 \
--description "$(DESCRIPTION)" \
--replaces "$(NAME) (<= $(VERSION)), $(OLD_NAME)" \
--provides "$(NAME)" \
--provides "$(OLD_NAME)" \
usr
.PHONY: tag
tag:
git tag "v$$(python setup.py --version)"
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# CS50 Library for Python

[![Build Status](https://travis-ci.org/cs50/python-cs50.svg?branch=master)](https://travis-ci.org/cs50/python-cs50)

Supports Python 2 and Python 3.

## Development
7 changes: 0 additions & 7 deletions after-install.sh

This file was deleted.

File renamed without changes.
File renamed without changes.
File renamed without changes.
19 changes: 19 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from setuptools import setup

setup(
author="CS50",
author_email="[email protected]",
classifiers=[
"Intended Audience :: Developers",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Topic :: Software Development :: Libraries :: Python Modules"
],
description="CS50 library for Python",
install_requires=["SQLAlchemy"],
keywords="cs50",
name="cs50",
packages=["cs50"],
url="https://github.com/cs50/python-cs50",
version="1.3.0"
Copy link
Member

Choose a reason for hiding this comment

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

Any way to factor out version?

Copy link
Member Author

Choose a reason for hiding this comment

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

I thought we don't need anymore, since we're distributing via PyPI only, aren't we?

Copy link
Member Author

Choose a reason for hiding this comment

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

@dmalan ended up reading the version specified in setup.py this way, without need to factor it out. Generally, I don't think we need to factor it out so long as we don't build multiple distributions (e.g., deb, rpm, sdist, etc).

Factoring it out (e.g., to a file) and parsing that from setup.py (or any number of other scripts/config files) is fairly easy, but just feels unnecessary to me, tbh, specially that we decided to distribute Python packages via PyPI only? Thoughts?

Copy link
Member

Choose a reason for hiding this comment

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

Interesting. Is calling the var __version__ conventional? This would seem to mean that setup.py needs to be installed along with, e.g., cs50.py itself. Is that indeed the norm with PyPi packages, does setup.py end up getting installed somewhere?

Separately, what's to be the relationship between the version number in setup.py and our GitHub repo's branches? Should we automatically (forcibly) create a GitHub tag and release called v#.#.# anytime there's a push, extracting the release's version number from setup.py too?

Copy link
Member Author

Choose a reason for hiding this comment

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

Is calling the var __version__ conventional?

Yes, see https://www.python.org/dev/peps/pep-0396/#specification

  1. When a module (or package) includes a version number, the version SHOULD be available in the __version__ attribute.

This would seem to mean that setup.py needs to be installed along with, e.g., cs50.py itself. Is that indeed the norm with PyPi packages, does setup.py end up getting installed somewhere?

The setup.py script end up being part of the source distribution (sdist) that we build and deploy to PyPI, since pip uses it to build this package for and install it on the target system. I don't think it typically gets installed (it's not in our case either), but what does get installed is some metadata about the package, based on what we provided in setup.py, and that's what's used to extract the version number at runtime in this case.


Separately, what's to be the relationship between the version number in setup.py and our GitHub repo's branches? Should we automatically (forcibly) create a GitHub tag and release called v#.#.# anytime there's a push, extracting the release's version number from setup.py too?

If you're referring to the problem per cs50/submit50#44, recall PyPI doesn't allow the same filename (including version) to be uploaded more than once. So we can't re-upload the same version of a package, to overwrite it, for example. (And frankly, this doesn't seem ideal, since two users might have the same package version installed, but effectively, they're different packages.)

But it might be the case that we, for example, have multiple PRs pending, and we want some or all of them to be part of the next release. If we just go ahead and merge these PRs into master, one after the other, only the first one will be deployed to PyPI, and all the others will fail, because they use the same version number. So we can't do that, using the current setup, without merging these PRs into one, and then merging that big PR into master, which seems unnecessary.

For that reason, we should automatically deploy, but manually trigger deployment somehow. A couple of solutions to this might be:

  1. Deploy on tags instead of commits to master. This should allow us to merge as many PRs as we want before the next release is published. And once we're comfortable releasing, we just tag and push that tag, which should trigger a build and deploy to PyPI.

  2. Deploy on commits to a production branch (or the equivalent). This also should allow us to merge as many PRs as we want into master, without any problems. And once a release is ready, we merge master into production, which should trigger a build and deploy to PyPI.

)