Skip to content

Commit

Permalink
Merge pull request #1 from boozt-platform/add-hooks-and-adjust-docs
Browse files Browse the repository at this point in the history
Feat: add hooks and update information about the project
  • Loading branch information
doniz authored Mar 1, 2024
2 parents 2894d45 + a3f42f7 commit 9a33de6
Show file tree
Hide file tree
Showing 11 changed files with 297 additions and 30 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# ignore goreleaser files
/dist/
6 changes: 6 additions & 0 deletions .goreleaser.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,9 @@ builds:
# merged to the main branch. If this is a Go project, you can remove this section
# and use the default configuration to release the packages within the new version.
- skip: true

checksum:
name_template: "checksums.txt"

snapshot:
name_template: "{{ .Tag }}-next"
10 changes: 10 additions & 0 deletions .lefthook.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# SPDX-FileCopyrightText: Copyright Boozt Fashion, AB
# SPDX-License-Identifier: MIT

extends:
# lint commit messages based by the conventional commits
- hooks/commitlint/.lefthook.yaml
# lint Dockerfiles
- hooks/hadolint/.lefthook.yaml
# lint shell scripts
- hooks/shellcheck/.lefthook.yaml
38 changes: 38 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# SPDX-FileCopyrightText: Copyright Boozt Fashion, AB
# SPDX-License-Identifier: MIT

SHELL := /usr/bin/env bash
.DEFAULT_GOAL := build
NAME ?= ""
DOCKERFILE ?= "false"

.PHONY: build
build: container_build container_scanning

.PHONY: container_build
container_build:
@docker build \
-t ${NAME} \
--file "${PWD}/hooks/${NAME}/Dockerfile" \
.

.PHONY: container_run
run: container_run
container_run:
@docker run --rm -it \
-v ${PWD}:/app \
${NAME} \
bash

.PHONY: container_scanning
scan: container_scanning
container_scanning:
@docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
-v ${HOME}/.trivy:/root/.cache/ \
aquasec/trivy:0.38.3 \
image --no-progress --exit-code 1 --severity CRITICAL ${NAME}

.PHONY: add_hook
add_hook:
@NAME=$(NAME) DOCKERFILE=$(DOCKERFILE) $(PWD)/add-hook.sh
56 changes: 26 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,45 +1,42 @@
<!-- Header Starts -->
[<img src="https://raw.githubusercontent.com/boozt-platform/branding/main/assets/img/platform-logo.png" width="350"/>][homepage]

[![GitHub Tag (latest SemVer)](https://img.shields.io/github/v/tag/boozt-platform/quickstart-template.svg?label=latest&sort=semver)][releases]
[![GitHub Tag (latest SemVer)](https://img.shields.io/github/v/tag/boozt-platform/lefthook.svg?label=latest&sort=semver)][releases]
[![license](https://img.shields.io/badge/license-mit-brightgreen.svg)][license]

<!-- Title & Description -->
# quickstart-template
# lefthook

Quickstart template for GitHub repositories. You may use this template to create new repositories with a predefined structure.
<!-- Header Ends -->
Various organizational hooks based on the [lefthook](https://github.com/evilmartians/lefthook) for development and continuous integration. Hooks enforce consistent practices across all commits and deployments.

<!-- TOC Starts -->
## Table of Contents

- [How to Use It](#how-to-use-it)
- [Available Hooks](#available-hooks)
- [About Boozt](#about-boozt)
- [Reporting Issues](#reporting-issues)
- [Contributing](#contributing)
- [License](#license)
<!-- TOC Ends -->

<!-- Body Starts -->
## How to Use It

This project is a template repository with various guidelines, the required CI release versioning pipeline, licenses, and more. You may use this project as a reference to start a new repository. Once you've created a new repository from this template, update the `README.md` file content according to your needs.
```yaml
remotes:
- git_url: [email protected]/boozt-platform/lefthook
ref: v1.0.0
configs:
# lint commit messages based by the conventional commits
- hooks/commitlint/.lefthook.yaml
# lint Dockerfiles
- hooks/hadolint/.lefthook.yaml
# lint shell scripts
- hooks/shellcheck/.lefthook.yaml
```
## Available Hooks
- [commitlint](./hooks/commitlint/) (**commit-msg**) - Lint commit messages based by the conventional commits
- [hadolint](./hooks/hadolint/) (**pre-commit**) - A smarter Dockerfile linter
- [shellcheck](./hooks/shellcheck/) (**pre-commit**) - a static analysis tool for shell scripts
It is necessary to maintain consistency and structure in this `README.md` file. Please follow the action items below and the comment blocks of this file (`<!-- comment block -->`):

- [x] Create repository from this quickstart template.
- [ ] Update Title & Description
- [ ] Add extra header badges if needed. Please keep the License, SemVer badges, and Logo image the same as they were distributed within this file.
- [ ] Update body content according to your project.
- [ ] Update the Table of Contents (TOC) based on your updated body content.
- [ ] Please keep the footer the same as it was distributed within this file.
- [ ] Remove all comment blocks from this `README.md` file i.e. `<!-- Body Starts--> <!-- Any other comment block -->`.
- [ ] Remove this [How to Use It](#how-to-use-it) section.
- [ ] Update [docs/CODEOWNERS](docs/CODEOWNERS) file.
- [ ] Update [.goreleaser.yaml](.goreleaser.yaml) to your needs, this file and CI pipeline [.github/workflows/release.yml](.github/workflows/release.yml) are used to release new versions automatically once the PRs are merged to the main branch.
<!-- Body Ends -->

<!-- Footer Starts -->
## About Boozt
Boozt is a leading and fast-growing Nordic technology company selling fashion and lifestyle online mainly through its multi-brand webstore [Boozt.com][boozt] and [Booztlet.com][booztlet].
Expand Down Expand Up @@ -68,14 +65,13 @@ Contributions are highly valued and very welcome! For the process of reviewing c
This project is licensed under the MIT. Please see [LICENSE][license] for full details.
[homepage]: https://github.com/boozt-platform/quickstart-template
[releases]: https://github.com/boozt-platform/quickstart-template/releases
[issues]: https://github.com/boozt-platform/quickstart-template/issues
[pull-request]: https://github.com/boozt-platform/quickstart-template/pulls
[homepage]: https://github.com/boozt-platform/lefthook
[releases]: https://github.com/boozt-platform/lefthook/releases
[issues]: https://github.com/boozt-platform/lefthook/issues
[pull-request]: https://github.com/boozt-platform/lefthook/pulls
[contributing]: ./docs/CONTRIBUTING.md
[license]: ./LICENSE
[boozt]: https://www.boozt.com/
[booztlet]: https://www.booztlet.com/
[blog]: https://medium.com/boozt-tech
[careers]: https://careers.booztgroup.com/
<!-- Footer Ends -->
97 changes: 97 additions & 0 deletions add-hook.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
#!/usr/bin/env bash

# SPDX-FileCopyrightText: Copyright Boozt Fashion, AB
# SPDX-License-Identifier: MIT

export NAME="${NAME:-""}"
export DOCKERFILE="${DOCKERFILE:-false}"

SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
HOOKS_DIR="hooks"
HOOKS_PATH="${SCRIPT_DIR}/${HOOKS_DIR}"

# error message function printing in red color
# usage: error "message"
error() {
local message=${1:-""}
echo -e "\033[0;31m${message}\033[0m"
}

# create hooks dir if not exists
if [ ! -d "${HOOKS_PATH}" ]; then
mkdir -p "${HOOKS_PATH}"
fi

# check if the NAME environment variable is not empty
if [ -z "$NAME" ]; then
error "The NAME environment variable is empty"
exit 1
fi

# check if the given module name not yet exists to be able to create a new module
if [ -d "${HOOKS_PATH}/${NAME}" ]; then
error "The module ${NAME} already exists"
exit 1
fi

# create a new module directory
mkdir -p "${HOOKS_PATH}/${NAME}"

# create .lefthook.yaml file with the SPDX license in it
cat > "${HOOKS_PATH}/${NAME}/.lefthook.yaml" <<EOF
# SPDX-FileCopyrightText: Copyright Boozt Fashion, AB
# SPDX-License-Identifier: MIT
EOF

# create Dockerfile if the DOCKERFILE environment variable is set and
# add the SPDX license to the Dockerfile
if [ "$DOCKERFILE" = "true" ]; then
cat > "${HOOKS_PATH}/${NAME}/Dockerfile" <<EOF
# SPDX-FileCopyrightText: Copyright Boozt Fashion, AB
# SPDX-License-Identifier: MIT
EOF

# output yaml configuration for .goreleaser.yaml file
# so it can be manually added in order to build the
# docker images for the new module.
cat <<EOF
dockers:
# Docker images for the ${NAME} module
- image_templates:
- "{{ .Env.REGISTRY }}/{{.ProjectName}}-${NAME}:{{ .Version }}-amd64"
- "{{ .Env.REGISTRY }}/{{.ProjectName}}-${NAME}:latest-amd64"
use: buildx
dockerfile: ${HOOKS_DIR}/${NAME}/Dockerfile
build_flag_templates:
- "--platform=linux/amd64"
- image_templates:
- "{{ .Env.REGISTRY }}/{{.ProjectName}}-${NAME}:{{ .Version }}-arm64"
- "{{ .Env.REGISTRY }}/{{.ProjectName}}-${NAME}:latest-arm64"
use: buildx
dockerfile: ${HOOKS_DIR}/${NAME}/Dockerfile
build_flag_templates:
- "--platform=linux/arm64"
- image_templates:
- "{{ .Env.REGISTRY }}/{{.ProjectName}}-${NAME}:{{ .Version }}-386"
- "{{ .Env.REGISTRY }}/{{.ProjectName}}-${NAME}:latest-386"
use: buildx
dockerfile: ${HOOKS_DIR}/${NAME}/Dockerfile
build_flag_templates:
- "--platform=linux/386"
docker_manifests:
# Docker manifest for the ${NAME} module
- name_template: "{{ .Env.REGISTRY }}/{{.ProjectName}}-${NAME}:{{ .Version }}"
image_templates:
- "{{ .Env.REGISTRY }}/{{.ProjectName}}-${NAME}:{{ .Version }-amd64"
- "{{ .Env.REGISTRY }}/{{.ProjectName}}-${NAME}:{{ .Version }-arm64"
- "{{ .Env.REGISTRY }}/{{.ProjectName}}-${NAME}:{{ .Version }-386"
- name_template: "{{ .Env.REGISTRY }}/{{.ProjectName}}-${NAME}:latest"
image_templates:
- "{{ .Env.REGISTRY }}/{{.ProjectName}}-${NAME}:latest-amd64"
- "{{ .Env.REGISTRY }}/{{.ProjectName}}-${NAME}:latest-arm64"
- "{{ .Env.REGISTRY }}/{{.ProjectName}}-${NAME}:latest-386"
EOF
fi

exit 0
24 changes: 24 additions & 0 deletions docs/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Thank you for considering contributing to our project! Your contributions are hi
1. [Updating Tests](#updating-tests)
1. [Updating Code](#updating-code)
1. [Creating a Pull Request](#creating-a-pull-request)
1. [Creating a new hook](#creating-a-new-hook)
1. [License Information](#license-information)
1. [Merging and Releasing](#merging-and-releasing)

Expand Down Expand Up @@ -74,6 +75,29 @@ Once you've made your changes and are ready to contribute them back to the proje

Be sure to follow the pull request template, if one is provided.

## Creating a new hook

To create a new hook, follow these steps:

1. Run `make add_hook [options]` (i.e. `make add_hook NAME=jslint`). Below are the available options you can pass:

Name|Description|Required|Default|
---|---|---|---|
NAME|The name of the hook|Yes||
DOCKERFILE|Boolean option to create an empty Dockerfile file in the hook folder with the license included|No|False|

2. Add necessary files to your new hook.
3. Adjust the `.lefthook.yaml` file to execute your new hook. You can use either a script or Docker. It's recommended to use Docker unless it's a simple bash script or specific to a development niche (such as frontend - JavaScript, CSS, or backend - Go, Python).
4. Update the README.md documentation to include your new hook in the list of available hooks and provide a brief description.
5. If you requested to create a Dockerfile, the script will output the `yaml` options to add to the `.goreleaser.yaml` file. These options facilitate the creation of a Docker image for various OS architectures.
6. To run tests against your Docker image, you can use the following commands:

- `make NAME=<hook-name>` or `make build NAME=<hook-name>`: This command builds the image and runs the security check. For example: `make NAME=jslint`.
- Alternatively, you can execute these commands individually:
- `make container_build NAME=<hook-name>`: Builds the Docker image.
- `make container_scan NAME=<hook-name>`: Performs a security scan on the Docker image.
- `make container_run NAME=<hook-name>`: Runs the Docker image.

## License Information

To ensure proper attribution and compliance with licensing terms, we require that all source code files include a [short-form SPDX ID][spdx-license-info] license comment block. This block should be added at the top of each source code file.
Expand Down
10 changes: 10 additions & 0 deletions hooks/commitlint/.lefthook.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# SPDX-FileCopyrightText: Copyright Boozt Fashion, AB
# SPDX-License-Identifier: MIT

commit-msg:
parallel: true
commands:
# Lint commit messages based by the conventional commits
# https://www.conventionalcommits.org/en/v1.0.0/
commitlint:
run: bash -c "hooks/commitlint/commitlint.sh {0}"
64 changes: 64 additions & 0 deletions hooks/commitlint/commitlint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#!/usr/bin/env bash

# SPDX-FileCopyrightText: Copyright Boozt Fashion, AB
# SPDX-License-Identifier: MIT

# Run commitlint.sh script to lint commit messages
# based on the conventional commits specification.
# https://www.conventionalcommits.org/en/v1.0.0/
#
# Create a new .commitlint configuration environment file
# in the root project to override the default configuration.

set -euo pipefail

# error message function printing in red color
# usage: error "message"
error() {
local message=${1:-""}
echo -e "\033[0;31m${message}\033[0m"
}

commitTitle=$(head -n1 "${1}")
configurationFile=".commitlint"

# source configuration environment file if exists
if [ -f "$configurationFile" ]; then
# shellcheck source=/dev/null
source "$configurationFile"
fi

# default values for environment variables
export MAX_COMMIT_MESSAGE_LENGTH=${MAX_COMMIT_MESSAGE_LENGTH:-80}
# valid commit prefix types for semantic versioning
export VALID_COMMIT_PREFIXES=${VALID_COMMIT_PREFIXES:-"build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test"}

# check commit message length
if [ ${#commitTitle} -gt "${MAX_COMMIT_MESSAGE_LENGTH}" ]; then
error "Your commit message is too long: ${#commitTitle} characters"
exit 1
fi

# check if the commit message contains Merge Branch to skip the commit message check
if echo "$commitTitle" | grep -qE 'Merge branch'; then
echo "Skipping commit message check for merge commits"
exit 0
fi

# check if the commit message is valid for semantic versioning
if ! echo "$commitTitle" | grep -qE '^('"${VALID_COMMIT_PREFIXES}"')(\([a-z0-9\s\-\_\,]+\))?!?:\s\w'; then
error "Your commit message is not valid for semantic versioning: \"$commitTitle\""

echo
echo "Format: <type>(<scope>): <subject>"
echo "Scope: optional"
echo "Example: feat(auth): add login feature"
echo
echo "Exclamation mark (!) is optional and can be used to indicate breaking changes."
echo "Use it before colon (:). i.e. feat(auth)!: add login feature"
echo
echo "Valid types: ${VALID_COMMIT_PREFIXES//|/,}"
echo

exit 1
fi
10 changes: 10 additions & 0 deletions hooks/hadolint/.lefthook.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# SPDX-FileCopyrightText: Copyright Boozt Fashion, AB
# SPDX-License-Identifier: MIT

pre-commit:
parallel: true
commands:
hadolint:
glob: "Dockerfile*"
run: |
docker run --rm -it -v $(pwd):/app -w /app ghcr.io/hadolint/hadolint hadolint {staged_files}
10 changes: 10 additions & 0 deletions hooks/shellcheck/.lefthook.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# SPDX-FileCopyrightText: Copyright Boozt Fashion, AB
# SPDX-License-Identifier: MIT

pre-commit:
parallel: true
commands:
shellcheck:
glob: "*.sh"
run: |
docker run --rm -v $(pwd):/mnt koalaman/shellcheck:stable {staged_files}

0 comments on commit 9a33de6

Please sign in to comment.