Project Structure¶
Project Structure foundation or template¶
Project: |
||||
GitLab: |
||||
GitHub: |
||||
Docker: |
||||
Author: |
This repository provides a minimal, yet opinionated baseline for software projects. It includes:
A Makefile [1] for local development, build, test, and maintenance
A Docker image for development, which runs tests
A target that formats all source, including for style
A kitchen sink linter configuration that runs all source checks
Version Control System (VCS) hooks [3] to enforce conventional commits [4], successful build and test on commit and push, and Towncrier [5] end-user oriented release notes on push
Targets that automate releases
Targets that automate dependency upgrades
Documentation built by Sphinx [6] with useful Sphinx extensions [7]
Targets used for both local development and on CI/CD platforms
A GitLab CI/CD [8] pipeline integrating those CI/CD recipes and targets
A GitHub Actions [9] workflow integrating those CI/CD recipes and targets
Organize source by feature [10], for example
\./src/foo/(template|view|model)\..*
, rather than by source type, for example\./src/(templates|views|models)/foo\..*
.
Add a VCS remote for this repository to a real project. When the template adds structure specific to certain types of projects, for example command-line tools, web services, UI apps, the it adds branches for each variant. When the template makes changes to structure common to different variants it can merge those changes into those variants. Real projects can also merge those changes.
Template usage¶
This is a rough guide for how to use this template in your project. This isn’t widely tested. Such tests are meta and wasteful to create and support. Report any issues you have or better yet submit a PR with corrections.
Pick the branch to use:
Pick the branch for your project type:
(py|js|ruby|…)
:Basic package metadata for a given language.
docker
:Docker images for development and end-users or deployments.
ci
:The preceding plus GitLab CI/CD pipelines that run tests and linters as CI and publish releases from
develop
andmain
as CD.
It’s important to use one of the preceding branches to merge into your project and not the
develop
ormain
branches from the template. Template developers use those branches to test the release process. They contain bumped versions, release notes, and other release artifacts that real projects shouldn’t merge into their code or history.Merge into your project:
If starting a fresh project:
$ git clone --origin "template" --branch "${TEMPLATE_BRANCH:?}" \ "https://gitlab.com/rpatterson/project-structure.git" "./foo-project" $ cd "./foo-project" $ git config remote.template.tagOpt --no-tags $ git remote add "origin" "git@gitlab.com:foo-username/foo-project.git" $ git switch -C "main" --track "origin/main"
If merging into an existing project:
$ git remote add "template" \ "https://gitlab.com/rpatterson/project-structure.git" $ git config remote.template.tagOpt --no-tags $ git merge --allow-unrelated-histories "template/${TEMPLATE_BRANCH:?}"
Rename files and directories derived from the project name:
$ git ls-files | grep -iE 'project.?structure'
Rename project name and template creator identity strings:
$ git grep -iE 'project.?structure|ross|Patterson'
Make changes described in
# TEMPLATE:
comments:These bits need the developer’s attention and reasoning. Read the comments and follow them with care:
$ git grep "TEMPLATE"
Update the project logo images:
$ git ls-files 'logo*.png' '**/logo*.png' 'logo*.svg' '**/logo*.svg' \ 'docs/_static/favicon.ico'
Create the project Matrix room [19], and set up the GitHub bot by using the
Add widgets, bridges & bots
link at the bottom of the room info right pane.
Lastly, remove this Template usage section and update the rest of this
./README.rst
for your project. When the template adds fixes and features, merge them
into your project and repeat steps 3–5.
This template publishes pre-releases on push to the develop
branch and final
releases on push to the main
branch. Project owners can decide the types of changes
that require a pre-release before final release and the types of changes that go
straight to final release. For example they can decide that:
Merge public contributions into
develop
. See the contributing documentation [11] for an example public contributions policy and workflow.Optionally commit fixes for bugs in final releases to a branch off
main
. After passing all tests and checks, merge back intomain
to publish final releases directly.Optionally also merge version upgrades for security updates directly to
main
.
Installation¶
Install locally or use the Docker container image:
Local Installation¶
Use a package manager for the project language to install locally:
.. code:: console
$ true “TEMPLATE: Always specific to the project type”
Docker Container Image¶
The recommended way to use the container image is by using Docker Compose [12]. See the example ./docker-compose.yml file [13]. Write your configuration and run the container:
$ docker compose up
You can also use the image directly. Pull the Docker image [14]. Use it to create and run a container:
$ docker pull "registry.gitlab.com/rpatterson/project-structure"
$ docker run --rm -it "registry.gitlab.com/rpatterson/project-structure" ...
Use image variant tags to control when the image updates. Releases publish tags for the
branch and for major and minor versions. For example, to keep up to date with a specific
branch, use a tag such as
registry.gitlab.com/rpatterson/project-structure:main
. Releases from develop
publish pre-releases. Releases from main
publish final releases. Releases from
main
also publish tags without a branch, for example
registry.gitlab.com/rpatterson/project-structure
. Releases from main
also
publish tags for the major and minor version, for example
registry.gitlab.com/rpatterson/project-structure:v0.8
.
Releases publish multi-platform images for the following platforms:
linux/amd64
linux/arm64
linux/arm/v7
Contributing¶
GitLab hosts this project [15] and mirrors it to GitHub [16]. Use GitLab for reporting issues [17] or submitting pull or merge requests [18]. Join the project Matrix room [19] for discussion. See the contributing documentation [11] for more details on how to get started with development.
Motivation¶
Plenty other project templates exists. Why make another? I’ve been a full-stack web developer from 1998 on. I’ve had plenty of time to develop plenty of opinions of my own. From a template I want a full tool set (for example test coverage, linting, formatting, CI). Conversely, I want minimal dependencies, structure, and opinion beyond a full tool set (for example some build or task system, structure for unused frameworks or libraries). I couldn’t find a template that manages that balance and I created this one.
I also find it hard to discern from other templates why they made what choices the did. As such, I also use this template to try out different options and learn for myself. You can learn about my findings and the reasons the choices I’ve made in the commit history.
Most importantly I’ve never found a satisfactory approach to keeping project structure up to date over time. As such, the primary motivation is providing a template upstream remote, merging structure updates into real projects over their lifetime.