Skip to content

Commit ec38631

Browse files
martonvagopre-commit-ci[bot]lwjohnst86
authored
feat: ✨ add files with copier variables (#127)
# Description This PR adds `copier.yaml` and template files that depend on it. Some related config is also tidied up. Closes #33 ## Checklist - [x] Added or updated tests - [x] Updated documentation - [x] Ran `just run-all` --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Luke W. Johnston <[email protected]>
1 parent bc6bf79 commit ec38631

21 files changed

+423
-8
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
_ignore
33
bin/
44
dev/
5+
_temp/
56

67
# Temporary files
78
*.tmp

.vscode/settings.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
"python.languageServer": "Pylance",
3131
"files.insertFinalNewline": true,
3232
"files.associations": {
33+
"justfile.jinja": "plaintext",
3334
"*.yml.jinja": "jinja-yaml",
3435
"*.cff.jinja": "jinja-yaml",
3536
"*.toml.jinja": "jinja-toml",

copier.yaml

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
_subdirectory: template
2+
3+
# Post-copy commands:
4+
_tasks:
5+
# Add dev dependencies
6+
- command: "git init -b main; uv add --dev pre-commit ruff typos pytest bandit commitizen genbadge jupyter pytest-cov quartodoc types-tabulate mypy vulture"
7+
when: "{{ _copier_operation == 'copy' }}"
8+
9+
# Message to show after generating or regenerating the project successfully
10+
_message_after_copy: |
11+
12+
Your project "{{ package_name }}" has been created successfully!
13+
14+
Next steps:
15+
16+
1. Change directory to the project root:
17+
18+
$ cd {{ _copier_conf.dst_path }}
19+
20+
2. Install the pre-commit hooks:
21+
22+
$ just install-precommit
23+
24+
3. Install [`spaid`](https://github.com/seedcase-project/spaid) and run these commands to upload and configure your project on GitHub:
25+
26+
$ spaid_gh_create_repo_from_local -h
27+
$ spaid_gh_set_repo_settings -h
28+
$ spaid_gh_ruleset_basic_protect_main -h
29+
30+
4. Configure GitHub following this
31+
[guide](https://guidebook.seedcase-project.org/operations/security#using-github-apps-to-generate-tokens):
32+
33+
- Install the [auto-release-token](https://github.com/apps/auto-release-token)
34+
and [add-to-board-token](https://github.com/apps/add-to-board-token) GitHub Apps
35+
- Create an `UPDATE_VERSION_TOKEN` and `ADD_TO_BOARD_TOKEN` secret for the GitHub Apps
36+
- Create an `UPDATE_VERSION_APP_ID` and `ADD_TO_BOARD_APP_ID` variable of the GitHub Apps' IDs
37+
38+
5. List and complete all TODO items in the repository:
39+
40+
$ just list-todos
41+
42+
# Questions:
43+
package_github_repo:
44+
type: str
45+
help: "What is or will be the GitHub repository spec for the project?"
46+
placeholder: "user/repo"
47+
validator: |
48+
{% if package_github_repo and not (package_github_repo | regex_search('^[\w.-]+\/[\w.-]+$')) %}
49+
Must be in the format `user/repo` and contain only alphanumeric characters and `_`, `-`, or `.`.
50+
{% endif %}
51+
52+
github_user:
53+
type: str
54+
default: "{{ package_github_repo.split('/')[0] if package_github_repo else '' }}"
55+
when: false
56+
57+
package_name:
58+
type: str
59+
help: "What is the name of the package?"
60+
default: "{{ _copier_conf.dst_path | basename }}"
61+
validator: |
62+
{% if package_name and not (package_name | regex_search('^[\w.-]+$')) %}
63+
Must contain only alphanumeric characters and `_`, `-`, or `.`.
64+
{% endif %}
65+
66+
package_name_snake_case:
67+
type: str
68+
default: "{{package_name | replace('-', '_') | replace('.', '_')}}"
69+
when: false
70+
71+
is_seedcase_project:
72+
type: bool
73+
help: "Is this package part of the Seedcase Project?"
74+
default: "{{ github_user == 'seedcase-project' }}"
75+
76+
homepage:
77+
type: str
78+
help: "What is the homepage of your project?"
79+
default: "{{ 'https://%s.seedcase-project.org' % package_name if is_seedcase_project else '' }}"
80+
81+
author_given_name:
82+
type: str
83+
help: "What is your first/given name?"
84+
85+
author_family_name:
86+
type: str
87+
help: "What is your last/family name?"
88+
89+
author_email:
90+
type: str
91+
help: "What is your email address?"
92+
93+
review_team:
94+
type: str
95+
help: What GitHub team is responsible for reviewing pull requests?
96+
default: "{{ '@%s/developers' % github_user if github_user else '' }}"
97+
98+
github_board_number:
99+
type: str
100+
help: "What is the GitHub project board number to add issues and PRs to?"
101+
validator: |
102+
{% if github_board_number and not github_board_number.isdigit() %}
103+
The board number must be an integer.
104+
{% endif %}
105+
106+
copyright_year:
107+
type: str
108+
default: "{{ copyright_year | default('%Y' | strftime) }}"
109+
when: false

docs/guide.qmd

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,8 @@ Project, run:
136136
just update-quarto-theme
137137
```
138138

139+
Then set `seedcase-theme` as your project `type` in `_quarto.yml`.
140+
139141
This adds the `seedcase-theme` Quarto theme to the website, which
140142
provides a consistent look and feel across all Seedcase Project
141143
websites, including for Python package websites.

justfile

Lines changed: 58 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22
just --list --unsorted
33

44
@_checks: check-spelling check-commits
5+
# Test Seedcase and non-Seedcase projects
6+
@_tests: (test "true") (test "false")
57
@_builds: build-contributors build-website build-readme
68

79
# Run all build-related recipes in the justfile
8-
run-all: update-quarto-theme update-template _checks test _builds
10+
run-all: update-quarto-theme update-template _checks _tests _builds
911

1012
# Install the pre-commit hooks
1113
install-precommit:
@@ -26,7 +28,7 @@ update-template:
2628
mkdir -p template/tools
2729
cp tools/get-contributors.sh template/tools/
2830
cp .github/pull_request_template.md template/.github/
29-
cp .github/workflows/build-website.yml .github/workflows/dependency-review.yml template/.github/workflows/
31+
cp .github/workflows/dependency-review.yml template/.github/workflows/
3032

3133
# Check the commit messages on the current branch that are not on the main branch
3234
check-commits:
@@ -45,9 +47,59 @@ check-spelling:
4547
uvx typos
4648

4749
# Test and check that a Python package can be created from the template
48-
# TODO: add test for copier
49-
test:
50-
echo "copier test"
50+
test is_seedcase_project:
51+
#!/bin/zsh
52+
test_name="test-python-package"
53+
test_dir="$(pwd)/_temp/{{ is_seedcase_project }}/$test_name"
54+
template_dir="$(pwd)"
55+
commit=$(git rev-parse HEAD)
56+
rm -rf $test_dir
57+
# vcs-ref means the current commit/head, not a tag.
58+
uvx copier copy $template_dir $test_dir \
59+
--vcs-ref=$commit \
60+
--defaults \
61+
--trust \
62+
--data package_github_repo="first-last/repo" \
63+
--data is_seedcase_project={{ is_seedcase_project }} \
64+
--data author_given_name="First" \
65+
--data author_family_name="Last" \
66+
--data author_email="[email protected]" \
67+
--data review_team="@first-last/developers" \
68+
--data github_board_number=22
69+
# Run checks in the generated test Python package
70+
cd $test_dir
71+
git add .
72+
git commit -m "test: initial copy"
73+
just check-python check-spelling
74+
# TODO: Find some way to test the `update` command
75+
# Check that recopy works
76+
echo "Testing recopy command -----------"
77+
rm .cz.toml
78+
git add .
79+
git commit -m "test: preparing to recopy from the template"
80+
uvx copier recopy \
81+
--vcs-ref=$commit \
82+
--defaults \
83+
--overwrite \
84+
--trust
85+
# Check that copying onto an existing Python package works
86+
echo "Using the template in an existing package command -----------"
87+
rm .cz.toml .copier-answers.yml LICENSE.md
88+
git add .
89+
git commit -m "test: preparing to copy onto an existing package"
90+
uvx copier copy \
91+
$template_dir $test_dir \
92+
--vcs-ref=$commit \
93+
--defaults \
94+
--trust \
95+
--overwrite \
96+
--data package_github_repo="first-last/repo" \
97+
--data is_seedcase_project={{ is_seedcase_project }} \
98+
--data author_given_name="First" \
99+
--data author_family_name="Last" \
100+
--data author_email="[email protected]" \
101+
--data review_team="@first-last/developers" \
102+
--data github_board_number=22
51103

52104
# Clean up any leftover and temporary build files
53105
cleanup:
@@ -64,4 +116,4 @@ build-readme:
64116

65117
# Generate a Quarto include file with the contributors
66118
build-contributors:
67-
sh ./tools/get-contributors.sh seedcase-project/template-workshop
119+
sh ./tools/get-contributors.sh seedcase-project/template-python-project

template/.github/CODEOWNERS.jinja

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# All members on Developers team get added to review PRs
2+
* {{ review_team }}

template/.github/dependabot.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
version: 2
2+
updates:
3+
- package-ecosystem: uv
4+
directory: /
5+
schedule:
6+
interval: monthly
7+
versioning-strategy: increase-if-necessary
8+
commit-message:
9+
prefix: build
10+
include: scope
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
name: Add to project board
2+
3+
on:
4+
issues:
5+
types:
6+
- opened
7+
- reopened
8+
- transferred
9+
pull_request:
10+
types:
11+
- reopened
12+
- opened
13+
14+
# Limit token permissions for security
15+
permissions: read-all
16+
17+
jobs:
18+
add-to-project:
19+
uses: seedcase-project/.github/.github/workflows/reusable-add-to-project.yml@main
20+
permissions:
21+
pull-requests: write
22+
with:
23+
board-number: {{ github_board_number }}
24+
app-id: {{ '${{ vars.ADD_TO_BOARD_APP_ID }}' }}
25+
secrets:
26+
add-to-board-token: {{ '${{ secrets.ADD_TO_BOARD }}' }}
27+
gh-token: {{ '${{ secrets.GITHUB_TOKEN }}' }}

template/CITATION.cff.jinja

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# TODO: Add title of Python package.
2+
title: ""
3+
# TODO: Add abstract of Python package.
4+
abstract: ""
5+
authors:
6+
- family-names: {{ author_family_name }}
7+
given-names: {{ author_given_name }}
8+
# TODO: Add ORCID and affiliation for the author.
9+
orcid: ""
10+
affiliation: ""
11+
# TODO: Add more authors as needed.
12+
# - family-names: ""
13+
# given-names: ""
14+
# orcid: ""
15+
# affiliation: ""
16+
cff-version: 1.2.0
17+
# doi:
18+
keywords:
19+
# TODO: Add keywords relevant to the project.
20+
- ""
21+
license: MIT
22+
message: "If you use this Python package, please cite it using these metadata."
23+
repository-code: "https://github.com/{{ package_github_repo }}"
24+
url: "{{ homepage }}"

template/LICENSE.md.jinja

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# MIT License
2+
3+
Copyright (c) {{ copyright_year }} {{ package_name }} authors
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

0 commit comments

Comments
 (0)