generated from ajparsons/python-poetry-auto-template
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 1019c03
Showing
24 changed files
with
655 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
# Tools to publish package to pypi automatically | ||
# on update of poetry version. | ||
# Will also update tags on automatic release. | ||
|
||
name: "Publish package" | ||
|
||
# don't allow multiple 'identical' processes to run. A second push should cancel the job from the first one. | ||
concurrency: | ||
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }}-${{ github.event.inputs.pypi }}-${{ github.event.inputs.testpypi }} | ||
cancel-in-progress: true | ||
|
||
on: | ||
workflow_dispatch: | ||
inputs: | ||
pypi: | ||
description: Force to pypi | ||
type: boolean | ||
default: false | ||
testpypi: | ||
description: Force to testpypi | ||
type: boolean | ||
default: false | ||
push: | ||
branches: [main] | ||
|
||
jobs: | ||
|
||
# run the tests first, if this fails nothing continues | ||
test: | ||
uses: ./.github/workflows/test.yml | ||
|
||
# run auto either if nothing explicit forced in workflow or it is a push event | ||
publish-auto: | ||
if: ${{ (github.event.inputs.testpypi == 'false' && github.event.inputs.pypi == 'false') || github.event_name == 'push' }} | ||
needs: test | ||
runs-on: ubuntu-latest | ||
steps: | ||
|
||
- uses: actions/checkout@v2 | ||
|
||
- name: Fetch repo name | ||
id: repo_name | ||
run: echo "::set-output name=value::$(echo '${{ github.repository }}' | awk -F '/' '{print $2}')" | ||
|
||
- id: get_status | ||
name: get_status | ||
uses: ajparsons/compare-pypi-poetry-version@v1 | ||
with: | ||
package_name: ${{ steps.repo_name.outputs.value }} | ||
|
||
- name: Update git tags | ||
if: ${{ steps.get_status.outputs.remote_exists == 'true' && steps.get_status.outputs.version_difference == 'true'}} | ||
shell: bash | ||
run: | | ||
git config --global user.email "[email protected]" | ||
git config --global user.name "GitHub Action" | ||
git tag -f -a -m "Latest release" "latest" | ||
for val in $TAGS; do | ||
git tag -f -a -m "Release for $val" "$val" | ||
done | ||
git push -f --tags | ||
env: | ||
TAGS: ${{ steps.get_status.outputs.version_tags }} | ||
|
||
- name: Build and publish to pypi | ||
if: ${{ steps.get_status.outputs.remote_exists == 'true' && steps.get_status.outputs.version_difference == 'true'}} | ||
uses: JRubics/[email protected] | ||
with: | ||
pypi_token: ${{ secrets.PYPI_TOKEN }} | ||
|
||
# run manual if one of the boolean buttons for workflow was used | ||
# this can force the initial creation of the package | ||
publish-manual: | ||
if: ${{ github.event.inputs.testpypi == 'true' || github.event.inputs.pypi == 'true' }} | ||
needs: test | ||
runs-on: ubuntu-latest | ||
steps: | ||
|
||
- uses: actions/checkout@v2 | ||
|
||
- name: Build and publish to pypi | ||
if: ${{ github.event.inputs.pypi == 'true' }} | ||
uses: JRubics/[email protected] | ||
with: | ||
pypi_token: ${{ secrets.PYPI_TOKEN }} | ||
|
||
- name: Build and publish to testpypi | ||
if: ${{ github.event.inputs.testpypi == 'true' }} | ||
uses: JRubics/[email protected] | ||
with: | ||
pypi_token: ${{ secrets.TEST_PYPI_TOKEN }} | ||
repository_name: "testpypi" | ||
repository_url: "https://test.pypi.org/legacy/" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
# From https://raw.githubusercontent.com/simonw/python-lib-template-repository/main/.github/workflows/setup.yml | ||
name: Execute template to populate repository | ||
|
||
on: | ||
push: | ||
workflow_dispatch: | ||
|
||
permissions: | ||
actions: write | ||
contents: write | ||
|
||
jobs: | ||
setup-repo: | ||
if: ${{ !endsWith(github.repository, '-auto-template') }} | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v2 | ||
with: | ||
fetch-depth: 0 | ||
ref: ${{ github.head_ref }} | ||
|
||
- name: Install cookiecutter | ||
run: pip3 install cookiecutter | ||
|
||
- uses: actions/github-script@v4 | ||
id: fetch-repo-and-user-details | ||
with: | ||
script: | | ||
const query = `query($owner:String!, $name:String!) { | ||
repository(owner:$owner, name:$name) { | ||
name | ||
description | ||
owner { | ||
login | ||
... on User { | ||
name | ||
} | ||
... on Organization { | ||
name | ||
} | ||
} | ||
} | ||
}`; | ||
const variables = { | ||
owner: context.repo.owner, | ||
name: context.repo.repo | ||
} | ||
const result = await github.graphql(query, variables) | ||
console.log(result) | ||
return result | ||
- name: Rebuild contents using cookiecutter | ||
env: | ||
INFO: ${{ steps.fetch-repo-and-user-details.outputs.result }} | ||
run: | | ||
export REPO_NAME=$(echo $INFO | jq -r '.repository.name') | ||
# Run cookiecutter | ||
pushd /tmp | ||
cookiecutter $GITHUB_WORKSPACE --no-input \ | ||
lib_name=$REPO_NAME \ | ||
description="$(echo $INFO | jq -r .repository.description)" \ | ||
github_username="$(echo $INFO | jq -r .repository.owner.login)" \ | ||
author_name="$(echo $INFO | jq -r .repository.owner.name)" \ | ||
author_email="${{ github.event.pusher.email }}" \ | ||
github_id=$GITHUB_REPOSITORY | ||
popd | ||
# Move generated content to root directory of repo | ||
rm -r tests | ||
rm -r hooks | ||
mv /tmp/$REPO_NAME/* . | ||
# And hidden settings files: | ||
mv /tmp/$REPO_NAME/.gitignore . | ||
mv /tmp/$REPO_NAME/.devcontainer . | ||
mv /tmp/$REPO_NAME/.vscode . | ||
# Delete the template related workflow and the cookiecutter files | ||
rm .github/workflows/template_setup.yml | ||
rm .github/workflows/template_test.yml | ||
rm -r "{{cookiecutter.hyphenated}}" | ||
rm -r cookiecutter.json | ||
rm pytest.ini | ||
rm requirements.dev.txt | ||
- name: Force push new repo contents | ||
uses: stefanzweifel/git-auto-commit-action@v4 | ||
with: | ||
commit_message: "Initial library structure" | ||
push_options: --force |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
name: Run meta pytest suite on repo | ||
|
||
on: | ||
pull_request: | ||
push: | ||
|
||
jobs: | ||
run-test: | ||
if: ${{ endsWith(github.repository, '-auto-template') }} | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v2 | ||
with: | ||
fetch-depth: 0 | ||
ref: ${{ github.head_ref }} | ||
|
||
- name: Install Poetry | ||
uses: snok/install-poetry@v1 | ||
|
||
- name: Install cookiecutter | ||
run: pip install -r requirements.dev.txt | ||
|
||
- name: run pytest | ||
run: python -m pytest |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
name: Run tests | ||
|
||
on: | ||
push: | ||
branches-ignore: [ main ] | ||
pull_request: | ||
branches-ignore: [ main ] | ||
workflow_call: | ||
workflow_dispatch: | ||
|
||
jobs: | ||
test: | ||
if: ${{ !endsWith(github.repository, '-auto-template') }} | ||
strategy: | ||
fail-fast: false | ||
matrix: | ||
python-version: ["3.8", "3.9", "3.10"] | ||
poetry-version: ["1.8"] | ||
|
||
runs-on: ubuntu-latest | ||
|
||
steps: | ||
- uses: actions/checkout@v2 | ||
|
||
- name: Set up Python ${{ matrix.python-version }} | ||
uses: actions/setup-python@v2 | ||
with: | ||
python-version: ${{ matrix.python-version }} | ||
|
||
- name: Install poetry ${{ matrix.poetry-version }} | ||
run: | | ||
python -m ensurepip | ||
python -m pip install --upgrade pip | ||
python -m pip install poetry==${{ matrix.poetry-version }} | ||
- name: Install dependencies | ||
shell: bash | ||
run: | | ||
python -m poetry config virtualenvs.create false | ||
python -m poetry install | ||
- name: Test with pytest | ||
shell: bash | ||
run: | | ||
python -m pytest -v tests | ||
- name: Test with pyright | ||
uses: jakebailey/pyright-action@v1 | ||
|
||
- name: Test with ruff | ||
shell: bash | ||
run: | | ||
python -m ruff . | ||
python -m ruff format --check . |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
*.pyc | ||
__pycache__ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
# Python project template | ||
|
||
This template repository can be used to create a new repository with the skeleton of a poetry-based Python library. | ||
|
||
This is based on the general approach of [simonw/python-lib](https://github.com/simonw/python-lib), but with a different default structure. | ||
|
||
# Creating a new template | ||
|
||
A new repository based on this template can be created in Github or through cookiecutter. | ||
|
||
## Templating in GitHub | ||
|
||
The templating process can be run entirely in GitHub to create a new repository. | ||
|
||
Start here: https://github.com/ajparsons/python-poetry-auto-template/generate | ||
|
||
Add a one-line description of your repository, then click "Create repository from template". | ||
|
||
# Templating with cookiecutter | ||
|
||
This repo can also be used to set up a template offline using [cookiecutter](https://cookiecutter.readthedocs.io/en/stable/). To start the processs: | ||
|
||
``` | ||
python -m cookiecutter https://github.com/ajparsons/python-poetry-auto-template/ | ||
``` | ||
|
||
# Features | ||
|
||
The default package uses: | ||
|
||
* [poetry](https://python-poetry.org/) for package management, | ||
* [pytest](https://docs.pytest.org/en/7.1.x/) for testing, | ||
* [black](https://black.readthedocs.io/en/stable/) for linting, | ||
* [pyright](https://github.com/microsoft/pyright) for typechecking. | ||
* [GitHub Actions](https://github.com/features/actions) for CI and publishing. | ||
|
||
New repositories include config files and Dockerfile for developing in VS Code or Codespaces, so the development process can happen end to end in Github. (Or not! Will still worked cloned locally). | ||
|
||
The test suite contains meta tests for alignment between the `__version__` of the package and the poetry version, and that the current version is documented in the change log. | ||
|
||
The template version includes a default GitHub Action for testing on Python 3.8-3.10, and publishing to pypi. | ||
|
||
By default, the test action requires pytest, black and pyright to return no errors. | ||
|
||
The default licence is the MIT Licence. Change if needed. | ||
|
||
# Publishing the package | ||
|
||
* Set a GitHub Actions secret for PYPI_TOKEN. | ||
* For the initial publish. In the Actions tab for a repo, trigger a manual workfork flow with the 'force to pypi' box ticked. | ||
* Subsequently, if the poetry version is bumped and all tests pass - the GitHub Action will automatically publish on push to the main branch. | ||
|
||
# Development and forking | ||
|
||
If you want to modify or extend this approach - the self-bootstrapping behaviour will only happen when a repo does *not* end in '-auto-template'. If you clone this repo, into a different user or org space, it will not self-bootstrap because the name is the same. | ||
|
||
If you wanted to extend this into a basic django template - you might fork or clone the repo and call it 'django-auto-template'. This will not self-bootstrap, but new projects created from that template would. | ||
|
||
## Meta tests | ||
|
||
This project defines several meta tests in `tests/` that will: | ||
|
||
* Attempt to provision a template with basic variables. | ||
* Run the projects internal tests for self-integrity. | ||
|
||
This requires the packages listed in `requirements.dev.txt` to be installed. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{ | ||
"lib_name": "", | ||
"description": "", | ||
"hyphenated": "{{ '-'.join(cookiecutter['lib_name'].lower().split()).replace('_', '-') }}", | ||
"underscored": "{{ cookiecutter.hyphenated.replace('-', '_') }}", | ||
"github_username": "", | ||
"author_name": "", | ||
"author_email": "", | ||
"year":"{% now 'utc', '%Y' %}", | ||
"yyyy_mm_dd":"{% now 'utc', '%Y-%m-%d' %}", | ||
"github_id": "{{cookiecutter.github_username}}/{{cookiecutter.lib_name}}" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import shutil | ||
import os | ||
from pathlib import Path | ||
|
||
# transpose github workflows into cookiecutter after generate | ||
# there's a problem where a github actions self template can't | ||
# modify an action, so we instead have all actions at the top - so | ||
# they are only removed, and not 'modified' by the templating process. | ||
# this hook makes sure when used as a cookiecutter - the actions are loaded correctly. | ||
|
||
template_dir = r"{{ cookiecutter._template }}" | ||
if any(x in template_dir for x in ["https:", "gh:"]): | ||
repo_name = template_dir.split("/")[-1] | ||
template_dir = Path.home() / ".cookiecutters" / repo_name | ||
else: | ||
template_dir = Path(template_dir) | ||
|
||
workflow_dir_source = template_dir / ".github" / "workflows" | ||
workflow_dir_dest = Path(os.getcwd()) / ".github" / "workflows" | ||
|
||
workflow_dir_dest.mkdir(parents=True, exist_ok=True) | ||
for item in workflow_dir_source.glob("*.yml"): | ||
if item.name.startswith("template_") is False: | ||
shutil.copyfile(item, workflow_dir_dest / item.name) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# pytest.ini | ||
[pytest] | ||
testpaths = | ||
tests |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
pytest==7.1.3 | ||
cookiecutter==2.1.0 | ||
requests==2.28.1 |
Oops, something went wrong.