Skip to content

Commit 7f19931

Browse files
authored
Refactor: Improve make help output (nhs-england-tools#118)
## Description - Improve `make help` output. - Fix issue with `Dockerfile` processing when replacing image from latest placeholder - Ensure `make` command line arguments are distinctive for the `docker` and `terraform` modules ## Context ### Current output (v2) <img width="1024" alt="image" src="https://github.com/nhs-england-tools/repository-template/assets/499338/e8e6800f-9510-45ae-bb70-4d044adb4752"> ### Previous output (v1) <img width="1024" alt="image" src="https://github.com/nhs-england-tools/repository-template/assets/499338/f577aa1f-a261-4a51-ae20-25f5093f5f85"> ### Legacy output <img width="2050" alt="image" src="https://github.com/nhs-england-tools/repository-template/assets/499338/60a2b2fd-1f19-4e9f-883a-5b5903f85d3d"> ### Testing ``` # clone the repo and switch to the `Improve_make_help_output` branch, then run: $ make help ``` ## Type of changes - [x] Refactoring (non-breaking change) - [ ] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would change existing functionality) - [x] Bug fix (non-breaking change which fixes an issue) ## Checklist - [x] I am familiar with the [contributing guidelines](../docs/CONTRIBUTING.md) - [x] I have followed the code style of the project - [x] I have added tests to cover my changes - [x] I have updated the documentation accordingly - [ ] This PR is a result of pair or mob programming --- ## Sensitive Information Declaration To ensure the utmost confidentiality and protect your and others privacy, we kindly ask you to NOT including [PII (Personal Identifiable Information) / PID (Personal Identifiable Data)](https://digital.nhs.uk/data-and-information/keeping-data-safe-and-benefitting-the-public) or any other sensitive data in this PR (Pull Request) and the codebase changes. We will remove any PR that do contain any sensitive information. We really appreciate your cooperation in this matter. - [x] I confirm that neither PII/PID nor sensitive data are included in this PR and the codebase changes.
1 parent ba990e1 commit 7f19931

File tree

12 files changed

+192
-95
lines changed

12 files changed

+192
-95
lines changed

Makefile

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,23 @@ include scripts/init.mk
77

88
# Example CI/CD targets are: dependencies, build, publish, deploy, clean, etc.
99

10-
dependencies: # Install dependencies needed to build and test the project
10+
dependencies: # Install dependencies needed to build and test the project @Pipeline
1111
# TODO: Implement installation of your project dependencies
1212

13-
build: # Build the project artefact
13+
build: # Build the project artefact @Pipeline
1414
# TODO: Implement the artefact build step
1515

16-
publish: # Publish the project artefact
16+
publish: # Publish the project artefact @Pipeline
1717
# TODO: Implement the artefact publishing step
1818

19-
deploy: # Deploy the project artefact to the target environment
19+
deploy: # Deploy the project artefact to the target environment @Pipeline
2020
# TODO: Implement the artefact deployment step
2121

22-
clean:: # Clean-up project resources
22+
clean:: # Clean-up project resources (main) @Operations
2323
# TODO: Implement project resources clean-up step
2424

25-
config:: # Configure development environment
26-
# TODO: Use only `make` targets that are specific to this project, e.g. you may not need to install Node.js
25+
config:: # Configure development environment (main) @Configuration
26+
# TODO: Use only 'make' targets that are specific to this project, e.g. you may not need to install Node.js
2727
make \
2828
nodejs-install \
2929
python-install \

docs/adr/ADR-001_Use_git_hook_and_GitHub_action_to_check_the_editorconfig_compliance.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ As a result of the above decision
126126
- the name of the file will be `check-file-format.sh`
127127
- there will be a `pre-commit` runner installed by the [pre-commit](https://pre-commit.com/) framework using a make target
128128
- the GitHub Action will call the git hook `check-file-format.sh` script directly
129-
- and a couple of `Makefile` targets like `config`, `githooks-install` will be implemented to bootstrap the project
129+
- and a couple of `Makefile` targets like `config`, `githooks-config` will be implemented to bootstrap the project
130130

131131
The intention of this decision is to guide any other git hook and GitHub Action implementations.
132132

docs/developer-guides/Bash_and_Make.md

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,23 @@
77
- [Conventions](#conventions)
88
- [Debugging](#debugging)
99
- [Scripts](#scripts)
10-
- [TODO](#todo)
1110

1211
## Using Make
1312

14-
Sample make target definition:
13+
Sample make target signature definition:
1514

1615
```makefile
17-
some-target: # Short target description - mandatory: foo=[description]; optional: baz=[description, default is 'qux']
16+
some-target: # Target description - mandatory: foo=[description]; optional: baz=[description, default is 'qux'] @Category
1817
# Recipe implementation...
1918
```
2019

20+
- `some-target`: This is the name of the target you would specify when you want to run this particular target. Use the kebab-case naming convention and prefix with an underscore `_` to mark it as a "private" target. The first part of the name is used for grouping, e.g. `docker-*` or `terraform-*`.
21+
- `Target Description`: Provided directly after the target name as a single line, so be concise.
22+
- `mandatory` parameters: Parameters that must be provided when invoking the target. Each parameter has its own description. Please, follow the specified format as it is used by `make help`.
23+
- `optional` parameters: Parameters that are not required when invoking the target. They may have a default value. Each parameter has its own description.
24+
- `@Category` label: Used for grouping by the `make help` command.
25+
- `Recipe implementation`: This section defines the actual commands or steps the target will execute. **Do not exceed 5 lines of effective code**. For more complex operations, use a shell script. Refer to the `docker-build` implementation in the [docker.mk](../../scripts/docker/docker.mk) file. More complex operations are implemented in the [docker.sh](../../scripts/docker/docker.lib.sh) script for readability and simplicity.
26+
2127
Run make target from a terminal:
2228

2329
```shell
@@ -31,6 +37,10 @@ All make targets should be added to the `${VERBOSE}.SILENT:` section of the `mak
3137

3238
It is worth noting that by default, `make` creates a new system process to execute each line of a recipe. This is not the desired behaviour for us and the entire content of a make recipe (a target) should be run in a single shell invocation. This has been configured in this repository by setting the [`.ONESHELL:`](https://www.gnu.org/software/make/manual/html_node/One-Shell.html) special target in the `scripts/init.mk` file.
3339

40+
To see all available make targets, run `make help`.
41+
42+
![make help](./assets/make_help.png)
43+
3444
## Using Bash
3545

3646
When working in the command-line ensure the environment variables are reset to their initial state. This can be done by reloading shell using the `env -i $SHELL` command.
@@ -141,10 +151,3 @@ You can combine it with the `VERBOSE` flag to see the details of the execution f
141151
```shell
142152
VERBOSE=1 FORCE_USE_DOCKER=1 scripts/shellscript-linter.sh
143153
```
144-
145-
## TODO
146-
147-
- Use of CLI tools installed and available on `$PATH`
148-
- Commands run in Docker containers when a CLI tool is not installed
149-
- Explain the concept of modules in this repository
150-
- Make is used as an orchestrator and tool to integrate development processes with the CI/CD pipeline
660 KB
Loading

docs/user-guides/Run_Git_hooks_on_commit.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,6 @@ The [pre-commit](https://pre-commit.com/) framework is a powerful tool for manag
2828
You can run and test the process by executing the following commands from your terminal. These commands should be run from the top-level directory of the repository:
2929

3030
```shell
31-
make githooks-install
31+
make githooks-config
3232
make githooks-run
3333
```

scripts/docker/docker.lib.sh

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,12 @@ function docker-build() {
2424

2525
local dir=${dir:-$PWD}
2626

27-
_create-effective-dockerfile
2827
version-create-effective-file
28+
_create-effective-dockerfile
29+
# The current directory must be changed for the image build script to access
30+
# assets that need to be copied
31+
current_dir=$(pwd)
32+
cd "$dir"
2933
docker build \
3034
--progress=plain \
3135
--platform linux/amd64 \
@@ -42,6 +46,7 @@ function docker-build() {
4246
--rm \
4347
--file "${dir}/Dockerfile.effective" \
4448
.
49+
cd "$current_dir"
4550
# Tag the image with all the stated versions, see the documentation for more details
4651
for version in $(_get-all-effective-versions) latest; do
4752
docker tag "${DOCKER_IMAGE}:$(_get-effective-version)" "${DOCKER_IMAGE}:${version}"
@@ -217,14 +222,14 @@ function _replace-image-latest-by-specific-version() {
217222
local build_datetime=${BUILD_DATETIME:-$(date -u +'%Y-%m-%dT%H:%M:%S%z')}
218223

219224
if [ -f "$versions_file" ]; then
220-
# First, list the entries specific for Docker to take precedence, then the rest
221-
content=$(grep " docker/" "$versions_file"; grep -v " docker/" "$versions_file")
225+
# First, list the entries specific for Docker to take precedence, then the rest but exclude comments
226+
content=$(grep " docker/" "$versions_file"; grep -v " docker/" "$versions_file" | grep -v "^#")
222227
echo "$content" | while IFS= read -r line; do
223228
[ -z "$line" ] && continue
224229
line=$(echo "$line" | sed "s/^#\s*//; s/\s*#.*$//" | sed "s;docker/;;")
225230
name=$(echo "$line" | awk '{print $1}')
226231
version=$(echo "$line" | awk '{print $2}')
227-
sed -i "s;\(FROM .*\) ${name}:latest;\1 ${name}:${version};g" "$dockerfile"
232+
sed -i "s;\(FROM .*\)${name}:latest;\1${name}:${version};g" "$dockerfile"
228233
done
229234
fi
230235

scripts/docker/docker.mk

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,48 +4,54 @@
44
# Custom implementation - implementation of a make target should not exceed 5 lines of effective code.
55
# In most cases there should be no need to modify the existing make targets.
66

7-
docker-build: # Build Docker image - optional: dir=[path to the Dockerfile to use, default is '.']
8-
make _docker cmd="build"
7+
docker-build: # Build Docker image - optional: docker_dir|dir=[path to the Dockerfile to use, default is '.'] @Development
8+
make _docker cmd="build" \
9+
dir=$(or ${docker_dir}, ${dir})
10+
file=$(or ${docker_dir}, ${dir})/Dockerfile.effective
11+
scripts/docker/dockerfile-linter.sh
912

10-
docker-push: # Push Docker image - optional: dir=[path to the image directory where the Dockerfile is located, default is '.']
11-
make _docker cmd="push"
13+
docker-push: # Push Docker image - optional: docker_dir|dir=[path to the image directory where the Dockerfile is located, default is '.'] @Development
14+
make _docker cmd="push" \
15+
dir=$(or ${docker_dir}, ${dir})
1216

13-
clean:: # Remove Docker resources - optional: dir=[path to the image directory where the Dockerfile is located, default is '.']
14-
make _docker cmd="clean"
17+
clean:: # Remove Docker resources (docker) - optional: docker_dir|dir=[path to the image directory where the Dockerfile is located, default is '.'] @Operations
18+
make _docker cmd="clean" \
19+
dir=$(or ${docker_dir}, ${dir})
1520

16-
_docker: # Docker command wrapper - mandatory: cmd=[command to execute]
21+
_docker: # Docker command wrapper - mandatory: cmd=[command to execute]; optional: dir=[path to the image directory where the Dockerfile is located, relative to the project's top-level directory, default is '.']
1722
# 'DOCKER_IMAGE' and 'DOCKER_TITLE' are passed to the functions as environment variables
1823
DOCKER_IMAGE=$(or ${DOCKER_IMAGE}, $(or ${docker_image}, $(or ${IMAGE}, $(or ${image}, ghcr.io/org/repo))))
1924
DOCKER_TITLE=$(or "${DOCKER_TITLE}", $(or "${docker_title}", $(or "${TITLE}", $(or "${title}", "Service Docker image"))))
2025
source scripts/docker/docker.lib.sh
21-
docker-${cmd} # 'dir' is passed to the function as environment variables, if set
26+
dir=$(realpath ${dir})
27+
docker-${cmd} # 'dir' is accessible by the function as environment variable
2228

2329
# ==============================================================================
2430
# Quality checks - please, DO NOT edit this section!
2531

26-
docker-shellscript-lint: # Lint all Docker module shell scripts
32+
docker-shellscript-lint: # Lint all Docker module shell scripts @Quality
2733
for file in $$(find scripts/docker -type f -name "*.sh"); do
2834
file=$${file} scripts/shellscript-linter.sh
2935
done
3036

3137
# ==============================================================================
3238
# Module tests and examples - please, DO NOT edit this section!
3339

34-
docker-test-suite-run: # Run Docker test suite
40+
docker-test-suite-run: # Run Docker test suite @ExamplesAndTests
3541
scripts/docker/tests/docker.test.sh
3642

37-
docker-example-build: # Build Docker example
43+
docker-example-build: # Build Docker example @ExamplesAndTests
3844
source scripts/docker/docker.lib.sh
3945
cd scripts/docker/examples/python
4046
DOCKER_IMAGE=repository-template/docker-example-python
4147
DOCKER_TITLE="Repository Template Docker Python Example"
4248
docker-build
4349

44-
docker-example-lint: # Lint Docker example
50+
docker-example-lint: # Lint Docker example @ExamplesAndTests
4551
dockerfile=scripts/docker/examples/python/Dockerfile
4652
file=$${dockerfile} scripts/docker/dockerfile-linter.sh
4753

48-
docker-example-run: # Run Docker example
54+
docker-example-run: # Run Docker example @ExamplesAndTests
4955
source scripts/docker/docker.lib.sh
5056
cd scripts/docker/examples/python
5157
DOCKER_IMAGE=repository-template/docker-example-python
@@ -55,7 +61,7 @@ docker-example-run: # Run Docker example
5561
"
5662
docker-run
5763

58-
docker-example-clean: # Remove Docker example resources
64+
docker-example-clean: # Remove Docker example resources @ExamplesAndTests
5965
source scripts/docker/docker.lib.sh
6066
cd scripts/docker/examples/python
6167
DOCKER_IMAGE=repository-template/docker-example-python

scripts/docker/tests/docker.test.sh

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ function main() {
2727
test-docker-suite-setup
2828
tests=( \
2929
test-docker-build \
30-
test-docker-version \
30+
test-docker-image-from-signature \
31+
test-docker-version-file \
3132
test-docker-test \
3233
test-docker-run \
3334
test-docker-clean \
@@ -70,7 +71,17 @@ function test-docker-build() {
7071
docker image inspect "${DOCKER_IMAGE}:$(_get-effective-version)" > /dev/null 2>&1 && return 0 || return 1
7172
}
7273

73-
function test-docker-version() {
74+
function test-docker-image-from-signature() {
75+
76+
# Arrange
77+
cp Dockerfile Dockerfile.effective
78+
# Act
79+
_replace-image-latest-by-specific-version
80+
# Assert
81+
grep -q "FROM python:.*-alpine.*@sha256:.*" Dockerfile.effective && return 0 || return 1
82+
}
83+
84+
function test-docker-version-file() {
7485

7586
# Arrange
7687
export BUILD_DATETIME="2023-09-04T15:46:34+0000"

0 commit comments

Comments
 (0)