Template for a Python package with a secure project host and package repository configuration.
The goals of this project are to:
Clone this repository locally:
$ git clone ssh://[email protected]/sethmlarson/secure-python-package-template
Cloning into 'secure-python-package-template'...
...
Receiving objects: 100% (79/79), 29.37 KiB | 1002.00 KiB/s, done.
Resolving deltas: 100% (20/20), done.
Rename the folder to the name of the package and remove existing git repository:
$ mv secure-python-package-template package-name
$ cd package-name
$ rm -rf .git
Create a new git repository and ensure the branch name is main
:
$ git init
Initialized empty Git repository in .../package-name/.git/
$ git status
On branch main
No commits yet
...
If the branch isn't named main
you can rename the branch:
$ git branch -m master main
Create an empty repository on GitHub. To ensure the repository is empty you shouldn't add a README file, .gitignore file, or a license yet. For the examples below the GitHub repository will be named sethmlarson/package-name
but you should substitute that with the GitHub repository name you chose.
We need to tell our git repository about our new GitHub repository:
$ git remote add origin ssh://[email protected]/sethmlarson/package-name
Change all the names and URLs be for your own package. Places to update include:
README.md
pyproject.toml
(project.name
and project.urls.Home
)src/{{secure_package_template}}
tests/test_{{secure_package_template}}.py
You should also change the license to the one you want to use for the package. Update the value in here:
LICENSE
README.md
Now we can create our initial commit and ensure it is signed by default:
$ git add .
$ git commit -m "Initial commit"
# Verify that this commit is signed. If not you
# should configure git to auto-sign commits.
$ git verify-commit HEAD
gpg: Signature made Fri 15 Jul 2022 10:55:10 AM CDT
gpg: using RSA key 9B2E1343B0B201B8883C79E3A99A0A21AD478212
gpg: Good signature from "Seth Michael Larson <[email protected]>" [ultimate]
Now we push our commit and branch:
$ git push origin main
Enumerating objects: 25, done.
Counting objects: 100% (25/25), done.
Delta compression using up to 12 threads
Compressing objects: 100% (21/21), done.
Writing objects: 100% (25/25), 17.92 KiB | 1.28 MiB/s, done.
Total 25 (delta 0), reused 0 (delta 0), pack-reused 0
To ssh://github.com/sethmlarson/package-name
* [new branch] main -> main
Success! You should now see the commit and all files on your GitHub repository.
PyPI is increasing the minimum requirements for account security and credential management to make consuming packages on PyPI more secure. This includes eventually requiring 2FA for all users and requiring API tokens to publish packages. Instead of waiting for these best practices to become required we can opt-in to them now.
API tokens will eventually be required for all packages to publish to PyPI.
PYPI_TOKEN
in the GitHub Environments section below)If you don't have 2FA enabled on PyPI already there's a section in the PyPI Help page about how to enable 2FA for your account. To make 2FA required for the new project:
.github/workflows/codeql-analysis.yml
main
Analyze (python)
Test (3.8)
Test (3.9)
Test (3.10)
*
to protect all tagspublish
PYPI_TOKEN
.whl
file select "view hashes" and copy the SHA256 and save the value somewhere (de58d65d34fe9548b14b82976b033b50e55840324053b5501073cb98155fc8af
)$ git clone ssh://[email protected]/sethmlarson/secure-python-package-template
)$ git checkout v0.1.0
)$ git log -1 --pretty=%ct
and store this value (1656789393
)SOURCE_DATE_EPOCH
($ export SOURCE_DATE_EPOCH=1656789393
)$ python -m pip install -r requirements/publish.txt
)$ python -m build
sha256sum dist/*.whl
.whl
file.CC0-1.0