Skip to content
Closed
Show file tree
Hide file tree
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
73 changes: 7 additions & 66 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,71 +12,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed

### Changed
- point readme towards govcookiecutter-lite, added section on original govcookiecutter

### Removed

## [2.1.0] - 2nd June 2025

### Added

- Example test and module
- Example pipeline
- Version to config
- Dev dependencies to config
- New requirements: `bandit` and `jinja2-time`
- `bandit` to user pre-commit hooks
- Including common Excel file times in the default .gitignore
- `bandit` to dev pre-commit hooks
- R install guidance to template README
- Setup question for locked down environments, uses local installed packages for commit hooks

### Fixed

- Broken links

### Changed

- Updated instructions on running the tests
- Updated imports
- Exclude certain files from pre-commit hooks
- Updated README to use `python -m`
- Minor contributing guidance changes
- Updated Python versions to 3.9-3.12
- Updated Python versions in workflows to 3.9-3.12
- Updated dev pre-commit hook versions via `pre-commit autoupdate`
- Template code of conduct updated
- Template contributing guidance updated
- Updated README
- Updated documentation website for `govcookiecutter` and created repo structures

### Removed

- Example data folder
- Removed the Email Address prompts from the installation.

## [2.0.0] - 6th March 2023

### Added

- Workflow to check external links on pull request

### Fixed

- Broken links

### Changed

- Updated folder structure
- Relative links have been replaced with complete paths
- Workflow actions now use later versions
- Updated CRAN link being installed from in startup.R
- Updates to the Contributing Guidance

### Removed

- Workflow support for Python 3.6


[unreleased]: https://github.com/best-practice-and-impact/govcookiecutter
[2.1.0]: https://github.com/best-practice-and-impact/govcookiecutter/tree/2.1.0
[2.0.0]: https://github.com/best-practice-and-impact/govcookiecutter/tree/2.0.0
- Project version from setup, default is 0.0.1
- locked down setup question, not needed as commit hooks have been removed
- removed all R files, not included in lite version
- removed overview setup question, a placeholder has been inserted into readme and project toml
- removed repo name question, instead derived from project name question
- hosting platform setup question, PR templates not included in lite version
9 changes: 1 addition & 8 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ pytest
Code coverage of Python scripts is measured using the [`coverage` Python
package][coverage]; its configuration can be found in `pyproject.toml`. Note coverage
only extends to Python scripts in the `hooks`, and
`{{ cookiecutter.repo_name }}/{{ cookiecutter.repo_name.lower().replace(' ', '_').replace('-', '_') }}` folders.
`{{ cookiecutter.project_name.lower().replace(' ', '_').replace('-', '_') }}/{{ cookiecutter.project_name.lower().replace(' ', '_').replace('-', '_') }}` folders.

To run code coverage, and view it as an HTML report, enter the following command in
your terminal:
Expand Down Expand Up @@ -114,13 +114,6 @@ make docs
This should create an HTML version of your documentation accessible from
`docs/_build/index.html`.

## Organisational frameworks

Organisational frameworks are stored in the
`.govcookiecutter/organisational_frameworks` folder. [If you would like to add your own
organisation's framework, follow the instructions][docs-govcookiecutter-frameworks] in
the `README.md` file in that folder.

[code-of-conduct]: https://github.com/best-practice-and-impact/govcookiecutter/blob/main/CODE_OF_CONDUCT.md
[coverage]: https://coverage.readthedocs.io/
[detect-secrets-repo]: https://github.com/Yelp/detect-secrets/tree/master
Expand Down
23 changes: 13 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
# `govcookiecutter`

## What is govcookiecutter?
## What is govcookiecutter-lite?

A cookiecutter template for analytical, Python-, or Python and R-based projects within
A lightweight cookiecutter template for analytical Python-based projects within
His Majesty's Government, and wider public sector.

## How is the template used?

This template helps to set up standardised project structures, and [includes security
features using pre-commit hooks][docs-pre-commit]. This cookiecutter template also acts
This template helps to set up standardised project structures. This cookiecutter template also acts
as an installable template (python projects only).

It also provides an Agile, centralised, and lightweight analytical quality assurance
(AQA) process. Pull or merge request templates are used to nudge users to complete this
process. [This helps meet HM Government best practice on producing quality analysis, as
(AQA) process. [This helps meet HM Government best practice on producing quality analysis, as
defined in the Aqua Book][aqua-book].

govcookiecutter-lite was developed from the original [govcookiecutter][govcookiecutter] but has
minimised the project creation to include only the minimum files and structure to quickly setup
python packages.

[For reasons why we developed `govcookiecutter`, read the blog post][blog-post], and
[watch the live demonstration from March 2021 on version 0.5.3][youtube].

Expand All @@ -26,8 +28,8 @@ The cookiecutter template generated for each project will follow this folder str
```shell
.
└── govcookiecutter/
├── {{ cookiecutter.repo_name }}/
│ └── {{ cookiecutter.repo_name.lower().replace(' ', '_').replace('-', '_') }}/
├── {{ cookiecutter.project_name.lower().replace(' ', '_').replace('-', '_') }}/
│ └── {{ cookiecutter.project_name.lower().replace(' ', '_').replace('-', '_') }}/
│ ├── example_modules/
│ │ ├── __init__.py
│ │ └── example_module.py
Expand Down Expand Up @@ -85,13 +87,13 @@ Next, open your
terminal, navigate to the directory where you want your new repository to exist. Then run the following command for the latest stable release:

```shell
python -m cookiecutter https://github.com/best-practice-and-impact/govcookiecutter.git
python -m cookiecutter https://github.com/best-practice-and-impact/govcookiecutter-lite.git
```

or for a specific branch, tag, or commit SHA `{SPECIFIC}`, run:

```shell
python -m cookiecutter https://github.com/best-practice-and-impact/govcookiecutter.git --checkout {SPECIFIC}
python -m cookiecutter https://github.com/best-practice-and-impact/govcookiecutter-lite.git --checkout {SPECIFIC}
```

Follow the prompts; if you are asked to re-download `govcookiecutter`, input `yes`.
Expand Down Expand Up @@ -168,6 +170,7 @@ project][drivendata]. Specifically, it uses a modified version of the `help` com
[cruft]: https://github.com/cruft/cruft
[docs-pre-commit]: ./CONTRIBUTING.md#getting-started
[drivendata]: http://drivendata.github.io/cookiecutter-data-science/
[govcookiecutter]: https://github.com/best-practice-and-impact/govcookiecutter.git
[homebrew]: https://brew.sh/
[issue-windows-os]: https://github.com/best-practice-and-impact/govcookiecutter/issues/20
[pluralsight]: https://www.pluralsight.com/tech-blog/managing-python-environments/
Expand Down
9 changes: 1 addition & 8 deletions cookiecutter.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
{
"organisation_name": "Your public sector organisation name, for example Government Digital Service",
"repository_hosting_platform": ["GitHub", "GitLab"],
"organisation_handle": "Your GitHub/GitLab organisation name, for example ukgovdatascience",
"organisational_framework": ["GDS", "N/A"],
"project_name": "Your new project name",
"repo_name": "{{ cookiecutter.project_name.lower().replace(' ', '_').replace('-', '_') }}",
"overview": "Brief overview of your project.",
"project_version": "0.0.1",
"locked_down_environment": ["No", "Yes"],
"using_R": ["No", "Yes"]
"project_name": "your_new_project_name"
}
1 change: 0 additions & 1 deletion docs/contributing_guide/docs_contributor_README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,5 @@ This is the contributor guide for the `govcookiecutter` project.
../CODE_OF_CONDUCT.md
../CONTRIBUTING.md
./modify_govcookiecutter.md
../{{ cookiecutter.repo_name }}/.govcookiecutter/organisational_frameworks/docs_repo_frameworks_README.md

```
35 changes: 12 additions & 23 deletions docs/contributing_guide/modify_govcookiecutter.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ When you open your terminal and run:
cookiecutter https://github.com/best-practice-and-impact/govcookiecutter.git
```

you'll see a list of prompts to answer; one of them is `repo_name`.
you'll see a list of prompts to answer; one of them is `project_name`.

Your answer for `repo_name` is used to overwrite every instance of
`{{ cookiecutter.repo_name }}`. The first instance is the `govcookiecutter` folder
`{{ cookiecutter.repo_name }}`, which becomes your outputted project!
Your answer for `project_name` is used to overwrite every instance of
`{{ cookiecutter.project_name.lower().replace(' ', '_').replace('-', '_') }}`. The first instance is the `govcookiecutter` folder
`{{ cookiecutter.project_name.lower().replace(' ', '_').replace('-', '_') }}`, which becomes your outputted project!

This means every folder and file contained within the `{{ cookiecutter.repo_name }}`
This means every folder and file contained within the `{{ cookiecutter.project_name.lower().replace(' ', '_').replace('-', '_') }}`
folder becomes part of your output project, including their content. Anything else
outside of this folder in `govcookiecutter` will not exist in the outputted project.

Expand All @@ -33,7 +33,7 @@ The prompts, and their default responses are defined in `cookiecutter.json`. Her
keys starting with `_` are not shown to the user, but provide template extensions.

One such extension is `jinja2_time.TimeExtension`, which is used to add the correct
year in the `{{ cookiecutter.repo_name }}/LICENSE` file.
year in the `{{ cookiecutter.project_name.lower().replace(' ', '_').replace('-', '_') }}/LICENSE` file.

All other keys are used to inject the user responses throughout the template. This
happens wherever you see `{{ cookiecutter.{KEY} }}`, where `{KEY}` is the key in
Expand All @@ -44,9 +44,7 @@ to the user. If the user does not enter a response, these default values are use
Values that are lists are shown as numerical options to the user, with the first list
element as the default value.

Note that these default values can also contain Jinja templating! For example, the
default response for `repo_name` is actually based on `project_name`, but with all
characters in lowercase, and any spaces replaced with hyphens.
Note that these default values can also contain Jinja templating!

## Validating user entries

Expand Down Expand Up @@ -75,7 +73,7 @@ defined in `hooks/post_gen_project.py`. These hooks only run after a project has
generated and, if they fail, will rollback the entire project.

Conditional files and folders are defined as `features` in the
`{{ cookiecutter.repo_name }}/manifest.json` file, which looks like:
`{{ cookiecutter.project_name.lower().replace(' ', '_').replace('-', '_') }}/manifest.json` file, which looks like:

```
{
Expand Down Expand Up @@ -118,14 +116,6 @@ For example, for the following Markdown:

The contributing guidelines for this project.

{% if cookiecutter.using_R == "Yes" -%}
### `DESCRIPTION`

R-specific information related to the project including the name, authors and packages
necessary for the project.

{% endif -%}

### `LICENSE`

The licence for this project...
Expand All @@ -146,19 +136,19 @@ These are performed in the `hooks/post_gen_project.py`file.
## Tests, coverage, and continuous integration

All pre- and post-generation hooks should be fully tested, alongside any generic
functions that we want to supply to users within the `{{ cookiecutter.repo_name }}`
functions that we want to supply to users within the `{{ cookiecutter.project_name.lower().replace(' ', '_').replace('-', '_') }}`
package. These tests should be written in `tests` or
`{{ cookiecutter.repo_name }}/tests` as appropriate.
`{{ cookiecutter.project_name.lower().replace(' ', '_').replace('-', '_') }}/tests` as appropriate.

Coverage also only covers the `hooks` and `{{ cookiecutter.repo_name }}/{{ cookiecutter.repo_name.lower().replace(' ', '_').replace('-', '_') }}` folders.
Coverage also only covers the `hooks` and `{{ cookiecutter.project_name.lower().replace(' ', '_').replace('-', '_') }}/{{ cookiecutter.project_name.lower().replace(' ', '_').replace('-', '_') }}` folders.

### Testing Jinja templating

Most of the tests are straightforward, and comprehensive. However, to test the Jinja
injection of user responses, the `test_govcookiecutter_injected_variables.py` script
adopts a test-driven development approach to completeness.

This test parses all the content of the `{{ cookiecutter.repo_name }}` folder, and
This test parses all the content of the `{{ cookiecutter.project_name.lower().replace(' ', '_').replace('-', '_') }}` folder, and
counts the number of times the replacement variable and its variations appear.

The constant dictionary variables at the top of the test script define the different
Expand Down Expand Up @@ -207,7 +197,6 @@ then use semantic versioning to number our releases][semver]. This helps our use
select a different version of `govcookiecutter` to use based on their individual needs.

[cookiecutter]: https://cookiecutter.readthedocs.io
[docs-organisational-frameworks]: https://github.com/best-practice-and-impact/govcookiecutter/blob/main/docs/%7B%7B%20cookiecutter.repo_name%20%7D%7D/.govcookiecutter/organisational_frameworks/docs_repo_frameworks_README.md
[github-issues]: https://github.com/best-practice-and-impact/govcookiecutter/issues
[html5-email-format]: https://html.spec.whatwg.org/multipage/input.html#valid-e-mail-address
[jinja]: https://jinja.palletsprojects.com
Expand Down
4 changes: 2 additions & 2 deletions docs/docs_README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ This folder contains documentation for `govcookiecutter`. These are written in M
Further details to consider when modifying these files are supplied in the [contributing guidance][contributing-guidance].
```

To include documentation from the `{{ cookiecutter.repo_name }}`
folder without duplicating it, refer to it in a file within the `docs/{{ cookiecutter.repo_name }}` folder.
To include documentation from the `{{ cookiecutter.project_name.lower().replace(' ', '_').replace('-', '_') }}`
folder without duplicating it, refer to it in a file within the `docs/{{ cookiecutter.project_name.lower().replace(' ', '_').replace('-', '_') }}` folder.

To build the documentation, run:

Expand Down
6 changes: 3 additions & 3 deletions docs/govcookiecutter_structure/docs_structure_README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Further detail on folder contents is available:
./example.md
./hooks.md
./tests.md
../{{ cookiecutter.repo_name }}/docs_repo_README.md
../{{ cookiecutter.project_name.lower().replace(' ', '_').replace('-', '_') }}/docs_repo_README.md
```

## Top-level files
Expand Down Expand Up @@ -101,7 +101,7 @@ Python imports are arranged according to the [specification defined by `black`][

#### `pytest`

To run the tests within the `tests`, and `{{ cookiecutter.repo_name }}/tests` folders
To run the tests within the `tests`, and `{{ cookiecutter.project_name.lower().replace(' ', '_').replace('-', '_') }}/tests` folders
using the `pytest` Python package, enter the following command:

```shell
Expand All @@ -125,7 +125,7 @@ make coverage_html
```

A code coverage report in HTML will be produced on the code in the `hooks` and
`{{ cookiecutter.repo_name }}/{{ cookiecutter.repo_name.lower().replace(' ', '_').replace('-', '_') }}` folders.
`{{ cookiecutter.project_name.lower().replace(' ', '_').replace('-', '_') }}/{{ cookiecutter.project_name.lower().replace(' ', '_').replace('-', '_') }}` folders.
This HTML report can be accessed at `htmlcov/index.html`.

### `README.md`
Expand Down
2 changes: 1 addition & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@
self
./contributing_guide/docs_contributor_README.md
./govcookiecutter_structure/docs_structure_README.md
./{{ cookiecutter.repo_name }}/docs_repo_README.md
./{{ cookiecutter.project_name.lower().replace(' ', '_').replace('-', '_') }}/docs_repo_README.md
./reference/docs_ref_README.md
```
1 change: 0 additions & 1 deletion docs/reference/docs_ref_README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ hooks fail, the generated project will be rolled-back, and deleted.
:toctree: api/

set_aqa_framework
set_request_template

```

Expand Down

This file was deleted.

2 changes: 1 addition & 1 deletion docs/{{ cookiecutter.repo_name }}/docs.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
```{include} ../../{{ cookiecutter.repo_name }}/docs/repo_docs_README.md
```{include} ../../{{ cookiecutter.project_name.lower().replace(' ', '_').replace('-', '_') }}/docs/repo_docs_README.md
```
4 changes: 2 additions & 2 deletions docs/{{ cookiecutter.repo_name }}/docs_repo_README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# `{{ cookiecutter.repo_name }}` folder structure
# `{{ cookiecutter.project_name.lower().replace(' ', '_').replace('-', '_') }}` folder structure

This is information about the structure of the created repository contained
in the `{{ cookiecutter.repo_name }}` folder within the `govcookiecutter` repository.
in the `{{ cookiecutter.project_name.lower().replace(' ', '_').replace('-', '_') }}` folder within the `govcookiecutter` repository.
Some of these files may not be present in the actual created repository, as this is
customised based on the user's answers to the prompts on set-ups.

Expand Down
13 changes: 0 additions & 13 deletions docs/{{ cookiecutter.repo_name }}/dot_govcookiecutter.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,3 @@

Used in cookiecutter configuation for removing files in the created repository that are not required
for users not using R.

## organisational_frameworks/

Contains folders for organisation-specific frameworks. These allow for customisation of the created repository.
The folders require:

- A template Analytical Quality Assurance (AQA) plan
- A template data log
- A template assumptions and caveats log
- A `pull_request_template.md`
- A `README.md`.

`govcookiecutter` currently contains a Government Digital Service framework.
2 changes: 1 addition & 1 deletion docs/{{ cookiecutter.repo_name }}/source_code.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# `{{ cookiecutter.repo_name.lower().replace(' ', '_').replace('-', '_') }}` folder overview
# `{{ cookiecutter.project_name.lower().replace(' ', '_').replace('-', '_') }}` folder overview

This is where source code for the created project is stored. We recommend following a standard Python project structure,
with functions grouped into modules inside a descriptively named folder. The created repository contains an `example_module.py`
Expand Down
2 changes: 1 addition & 1 deletion docs/{{ cookiecutter.repo_name }}/tests.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
```{include} ../../{{ cookiecutter.repo_name }}/tests/repo_tests_README.md
```{include} ../../{{ cookiecutter.project_name.lower().replace(' ', '_').replace('-', '_') }}/tests/repo_tests_README.md
```
6 changes: 2 additions & 4 deletions hooks/__init__.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
from hooks.post_gen_project import (
delete_files_and_folders,
parse_features_json,
set_aqa_framework,
set_request_template,
)
from hooks.pre_gen_project import check_repo_name_structure

__all__ = (
"delete_files_and_folders",
"check_repo_name_structure",
"parse_features_json",
"set_aqa_framework",
"set_request_template",
)
Loading
Loading