diff --git a/.devcontainer/.env b/.devcontainer/.env new file mode 100644 index 0000000..4b0ae72 --- /dev/null +++ b/.devcontainer/.env @@ -0,0 +1,12 @@ +DEVCONTAINER_WORKDIR=/usr/local/devcontainer +DEVCONTAINER_BUILD_SCRIPT=$DEVCONTAINER_WORKDIR/build/run.sh + +PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin + +HOMEBREW_PREFIX=/home/linuxbrew/.linuxbrew +PATH=$HOMEBREW_PREFIX/sbin:$HOMEBREW_PREFIX/bin:$PATH + +GOPATH=/usr/local/go +GOBIN=/usr/local/bin + +USE_EMOJI=false diff --git a/.devcontainer/Brewfile b/.devcontainer/Brewfile new file mode 100644 index 0000000..3d5fd04 --- /dev/null +++ b/.devcontainer/Brewfile @@ -0,0 +1,49 @@ +brew "actionlint" +brew "bash-completion@2" +brew "codespell" +brew "direnv" +brew "dotenv-linter" +brew "editorconfig-checker" +brew "fd" +brew "fdupes" +brew "gcc" +brew "gh" +brew "git" +brew "gitleaks" +brew "go" +brew "hadolint" +brew "htop" +brew "jq" +brew "lychee" +brew "markdownlint-cli" +brew "markdownlint-cli2" +brew "moreutils" +brew "optipng" +brew "pipx" +brew "pngcheck" +brew "pngcrush" +brew "pngnq" +brew "pngquant" +brew "proselint" +brew "python" +brew "semgrep" +brew "shellcheck" +brew "shfmt" +brew "sqlfluff" +brew "svgo" +brew "syft" +brew "taplo" +brew "the_silver_searcher" +brew "tree" +brew "trivy" +brew "yamllint" + +# TODO +# ----------------------------------------------------------------------------- + +# - [ ] fixred +# - [ ] brok +# - [ ] ripgrep +# - [ ] fzf +# - [ ] Install https://github.com/junegunn/fzf in devcontainer +# - [ ] Install hooks in dotfiles repo diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index aebeeed..901c567 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,13 +1,6 @@ # Use the latest Debian release FROM mcr.microsoft.com/vscode/devcontainers/base:bullseye as base -ENV BREW_BIN='/home/linuxbrew/.linuxbrew/bin' -ENV SYS_PATH='/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin' -ENV PATH="${BREW_BIN}:${SYS_PATH}" - -COPY . /opt/devcontainer -WORKDIR /opt/devcontainer -RUN ./run.d/00_apt.sh && \ - ./run.d/01_npm.sh && \ - ./run.d/02_homebrew.sh && \ - ./run.d/03_system.sh +COPY . $DEVCONTAINER_WORKDIR +WORKDIR $DEVCONTAINER_WORKDIR +RUN ./bootstrap.sh && make build diff --git a/.devcontainer/Makefile b/.devcontainer/Makefile new file mode 100644 index 0000000..a026756 --- /dev/null +++ b/.devcontainer/Makefile @@ -0,0 +1,20 @@ +# ============================================================================= +# Container build +# ============================================================================= + +.EXPORT_ALL_VARIABLES: + +LC_ALL = C # Ensure simplest POSIX locale + +# Primary targets +# ============================================================================= + +.PHONY: build # Build the container +# ----------------------------------------------------------------------------- + +build: + echo "TODO: Implement this target" + exit 1 + +.PHONY: build-test # Test the build in the current container +# ----------------------------------------------------------------------------- diff --git a/.devcontainer/bootstrap.sh b/.devcontainer/bootstrap.sh new file mode 100755 index 0000000..d5b7a95 --- /dev/null +++ b/.devcontainer/bootstrap.sh @@ -0,0 +1,4 @@ +#!/bin/sh -ex + +sudo apt-get -qq update +sudo apt-get -qq install -y --no-install-recommends build-essential diff --git a/.devcontainer/build/run.d/00_init.sh b/.devcontainer/build/run.d/00_init.sh new file mode 100755 index 0000000..cb40544 --- /dev/null +++ b/.devcontainer/build/run.d/00_init.sh @@ -0,0 +1,12 @@ +#!/bin/sh -ex + +# shellcheck source=.devcontainer/build/sh.d/common +. ./build/sh.d/common +print_running "$0" + +# Switch default `root` user shell +sudo sed -i 's,/root:/bin/ash,/root:/bin/bash,' /etc/passwd + +# Create the `admin` group (intended for the devcontainer `remoteUser`, to +# provide write access to necessary directories) +sudo groupadd -f admin diff --git a/.devcontainer/build/run.d/01_apt.sh b/.devcontainer/build/run.d/01_apt.sh new file mode 100755 index 0000000..2cfdd9b --- /dev/null +++ b/.devcontainer/build/run.d/01_apt.sh @@ -0,0 +1,12 @@ +#!/bin/sh -ex + +# shellcheck source=.devcontainer/build/sh.d/common +. ./build/sh.d/common +print_running "$0" + +apt_install \ + acl \ + build-essential \ + cronic \ + file \ + gcc diff --git a/.devcontainer/build/run.d/02_node.sh b/.devcontainer/build/run.d/02_node.sh new file mode 100755 index 0000000..b2aa190 --- /dev/null +++ b/.devcontainer/build/run.d/02_node.sh @@ -0,0 +1,41 @@ +#!/bin/bash -ex + +# shellcheck source=.devcontainer/build/sh.d/common +. ./build/sh.d/common +print_running "$0" + +NODESOURCE_URL=https://deb.nodesource.com/setup_19.x +NODESOURCE_SCRIPT=nodesource_setup.sh + +YARN_DEB_REPO=https://dl.yarnpkg.com/debian +YARN_PUBKEY_URL="${YARN_DEB_REPO}/pubkey.gpg" +YARN_PUBKEY=pubkey.gpg +YARN_KEY_PATH="/usr/share/keyrings/yarnkey.gpg" +YARN_LIST=/etc/apt/sources.list.d/yarn.list + +tmp_dir="$(mktemp -d)" +clean() { rm -rf "${tmp_dir}"; } +trap clean EXIT + +( + cd "${tmp_dir}" + # Set up APT for latest Node.js + wget -q "${NODESOURCE_URL}" -O "${NODESOURCE_SCRIPT}" + chmod 755 "${NODESOURCE_SCRIPT}" + sudo "./${NODESOURCE_SCRIPT}" + # Set up APT for latest Yarn + wget -q "${YARN_PUBKEY_URL}" -O "${YARN_PUBKEY}" + sudo rm -f "${YARN_KEY_PATH}" + sudo gpg --dearmor --output "${YARN_KEY_PATH}" "${YARN_PUBKEY}" + echo "deb [signed-by=${YARN_KEY_PATH}] ${YARN_DEB_REPO} stable main" \ + >yarn.list + sudo mv yarn.list "${YARN_LIST}" +) + +apt_install \ + nodejs \ + yarn + +sudo yarn install --global --prefer-dedupe + +sudo yarn cache clean --global --force diff --git a/.devcontainer/build/run.d/03_brew.sh b/.devcontainer/build/run.d/03_brew.sh new file mode 100755 index 0000000..d21d3fa --- /dev/null +++ b/.devcontainer/build/run.d/03_brew.sh @@ -0,0 +1,50 @@ +#!/bin/sh -ex + +# shellcheck source=.devcontainer/build/sh.d/common +. ./build/sh.d/common +print_running "$0" + +GH_RAW_URL=https://raw.githubusercontent.com +INSTALL_SCRIPT=install.sh +INSTALL_URL="${GH_RAW_URL}/Homebrew/install/HEAD/${INSTALL_SCRIPT}" + +user_id="$(id -u)" +if test "${user_id}" = 0; then + # Let Homebrew know it's safe to run as the superuser + sudo touch /.dockerenv +fi + +# This assignment will fail if the container environtment variables are not set +homebrew_prefix="${HOMEBREW_PREFIX:?}" + +# Remove any existing Homebrew directory (to ensure a clean install) +sudo rm -rf "${homebrew_prefix}" + +tmp_dir="$(mktemp -d)" +clean() { rm -rf "${tmp_dir}"; } +trap clean EXIT + +( + cd "${tmp_dir}" + wget -q "${INSTALL_URL}" -O "${INSTALL_SCRIPT}" + chmod 755 "${INSTALL_SCRIPT}" + HOMEBREW_NO_EMOJI=1 + export HOMEBREW_NO_EMOJI + NONINTERACTIVE=true + export NONINTERACTIVE + HOMEBREW_INSTALL_FROM_API=true + export HOMEBREW_INSTALL_FROM_API + "./${INSTALL_SCRIPT}" +) + +# Copy the `Brewfile` to the Homebrew home directorys so `Brewfile.lock.json` +# is writeable +cp Brewfile "${homebrew_prefix}/Brewfile" +cd "${homebrew_prefix}" + +brew update --quiet +brew bundle install +brew doctor + +brew_cache="$(brew --cache)" +rm -rf "${brew_cache}" diff --git a/.devcontainer/build/run.d/04_python.sh b/.devcontainer/build/run.d/04_python.sh new file mode 100755 index 0000000..06d8de3 --- /dev/null +++ b/.devcontainer/build/run.d/04_python.sh @@ -0,0 +1,39 @@ +#!/bin/sh -ex + +# shellcheck source=.devcontainer/build/sh.d/common +. ./build/sh.d/common +print_running "$0" + +pipx ensurepath + +pipx_install() { + echo "${@}" | tr ' ' '\0' | xargs -0 -n1 \ + pipx install --system-site-packages --pip-args='--no-cache-dir' +} + +pipx_install \ + bandit \ + black \ + flake8 \ + ipython \ + isort \ + mypy \ + pep8 \ + pipenv \ + poetry \ + prospector \ + pylint \ + pyright \ + pyroma \ + reorder-python-imports \ + restructuredtext-lint \ + rstcheck \ + rstfmt \ + sourcery \ + tox \ + virtualenv \ + pydocstyle \ + vulture \ + yapf + +pip3 cache purge diff --git a/.devcontainer/build/run.d/05_go.sh b/.devcontainer/build/run.d/05_go.sh new file mode 100755 index 0000000..4b94c35 --- /dev/null +++ b/.devcontainer/build/run.d/05_go.sh @@ -0,0 +1,11 @@ +#!/bin/sh -ex + +# shellcheck source=.devcontainer/build/sh.d/common +. ./build/sh.d/common +print_running "$0" + +go install github.com/client9/misspell/cmd/misspell@latest +go install github.com/rif/imgdup2go@latest + +go clean --cache +go clean --modcache diff --git a/.devcontainer/build/run.d/06_haskell.sh b/.devcontainer/build/run.d/06_haskell.sh new file mode 100755 index 0000000..43231d4 --- /dev/null +++ b/.devcontainer/build/run.d/06_haskell.sh @@ -0,0 +1,27 @@ +#!/bin/sh -ex + +# shellcheck source=.devcontainer/build/sh.d/common +. ./build/sh.d/common +print_running "$0" + +BROK_URL=https://github.com/smallhadroncollider/brok +RELEASES_URL="${BROK_URL}/releases/download" +VERSION=1.1.0 + +DOWNLOAD_FILE="brok-${VERSION}_x86-64-linux.tar.gz" +DOWNLOAD_URL="${RELEASES_URL}/${VERSION}/${DOWNLOAD_FILE}" + +BIN_SCRIPT=brok +INSTALL_DIR=/usr/local/bin + +tmp_dir="$(mktemp -d)" +clean() { rm -rf "${tmp_dir}"; } +trap clean EXIT + +( + cd "${tmp_dir}" + wget -q "${DOWNLOAD_URL}" -O "${DOWNLOAD_FILE}" + tar -xvzf "${DOWNLOAD_FILE}" + chmod 755 "${BIN_SCRIPT}" + sudo mv "${BIN_SCRIPT}" "${INSTALL_DIR}" +) diff --git a/.devcontainer/build/run.d/07_rust.sh b/.devcontainer/build/run.d/07_rust.sh new file mode 100755 index 0000000..b04a755 --- /dev/null +++ b/.devcontainer/build/run.d/07_rust.sh @@ -0,0 +1,7 @@ +#!/bin/sh -ex + +# shellcheck source=.devcontainer/build/sh.d/common +. ./build/sh.d/common +print_running "$0" + +# TODO: https://github.com/rhysd/fixred diff --git a/.devcontainer/build/run.d/99_finalize.sh b/.devcontainer/build/run.d/99_finalize.sh new file mode 100755 index 0000000..83f4e7a --- /dev/null +++ b/.devcontainer/build/run.d/99_finalize.sh @@ -0,0 +1,9 @@ +#!/bin/sh -ex + +# shellcheck source=.devcontainer/build/sh.d/common +. ./build/sh.d/common +print_running "$0" + +# Ensure correct permissions of the `/usr/local` directory (so the devcontainer +# `remoteUser` will have write access) +sudo chown -R root:admin /usr/local diff --git a/.devcontainer/build/run.sh b/.devcontainer/build/run.sh new file mode 100755 index 0000000..90aad4a --- /dev/null +++ b/.devcontainer/build/run.sh @@ -0,0 +1,12 @@ +#!/bin/sh -e + +# This assigment will fail if the container environment variables are not set +workdir="${DEVCONTAINER_WORKDIR:?}" +cd "${workdir}" + +# Build specific environment variables (i.e., we don't want to leak these into +# the final container environment) +DEBIAN_FRONTEND=noninteractive +export DEBIAN_FRONTEND + +run-parts --exit-on-error --regex '\.sh$' ./build/run.d diff --git a/.devcontainer/build/sh.d/common b/.devcontainer/build/sh.d/common new file mode 100644 index 0000000..955f376 --- /dev/null +++ b/.devcontainer/build/sh.d/common @@ -0,0 +1,13 @@ +# shellcheck shell=sh + +print_running() { + # Bold text, reversed colors, and padded to 79 characters (to stand out + # from normal output) + printf "\e[1m\e[7mRUNNING: %-79s\e[0m\n" "$*" +} + +apt_install() { + sudo apt-get -qq update -y + sudo apt-get -qq install -y --no-install-recommends "$@" + sudo rm -rf /var/lib/apt/lists/* +} diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 9dd941c..3d045ce 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -3,9 +3,12 @@ "dockerfile": "Dockerfile" }, // "remoteUser": "root", + "onCreateCommand": ["${DEVCONTAINER_WORKDIR}/scripts/on_create.sh"], "updateContentCommand": [ - "/opt/devcontainer/update-content.sh", - "${containerWorkspaceFolder}" + "${DEVCONTAINER_WORKDIR}/scripts/update_content.sh" + ], + "postCreateCommand": [ + "${DEVCONTAINER_WORKDIR}/scripts/post_create.sh" ], "customizations": { "vscode": { diff --git a/.devcontainer/life_cycle/on_create.sh b/.devcontainer/life_cycle/on_create.sh new file mode 100755 index 0000000..90d6f33 --- /dev/null +++ b/.devcontainer/life_cycle/on_create.sh @@ -0,0 +1,9 @@ +#!/bin/sh -e + +# This script is run from the workspace directory when the development +# container is first created, and the results will be cached during the build +# process for subsequent container starts + +# cf. https://containers.dev/implementors/json_reference/#lifecycle-scripts + +# ============================================================================ diff --git a/.devcontainer/life_cycle/post_create.sh b/.devcontainer/life_cycle/post_create.sh new file mode 100755 index 0000000..35db6c2 --- /dev/null +++ b/.devcontainer/life_cycle/post_create.sh @@ -0,0 +1,10 @@ +#!/bin/sh -e + +# Finalize container setup when dev container is created + +# cf. https://containers.dev/implementors/json_reference/#lifecycle-scripts + +# ============================================================================ + +# TODO: Update repository with `make upgrade` (?) so the cached results are +# updated at container start time diff --git a/.devcontainer/life_cycle/update_content.sh b/.devcontainer/life_cycle/update_content.sh new file mode 100755 index 0000000..7b1c369 --- /dev/null +++ b/.devcontainer/life_cycle/update_content.sh @@ -0,0 +1,59 @@ +#!/bin/sh -e + +# Update content + +# Run whenever the contents of the workspace mount are updated +# https://containers.dev/implementors/json_reference/#lifecycle-scripts + +# ============================================================================ + +# This command is always run from the workspace directory +workspace_dir="$(pwd)" + +# Fix permissions +# ---------------------------------------------------------------------------- + +# Get current username +whoami="$(whoami)" +user_id="$(id -u)" + +# If not the superuser, add the current user to the `admin` group (alowing +# write acccess to the contents of the `/usr/local` directory) +if test "${user_id}" != 0; then + usermod -aG admin "${whoami}" +fi + +# Fix Homebrew permissions (in case the container was originally built by a +# different user) +homebrew_prefix="$(brew --prefix)" +sudo chown -R "${whoami}" "${homebrew_prefix}" + +# Fix workspace umask +# ---------------------------------------------------------------------------- + +# After applying the changes below, the current user's default umask will +# be respected for all files in the workspace directory + +# Change the ownership of the workspace directory and its contents to the +# current user +sudo chown -R "${whoami}" "${workspace_dir}" +# Remove all extended ACL entries (preserved by Docker during mount) +sudo setfacl -bnR "${workspace_dir}" + +# Allow direnv +# ---------------------------------------------------------------------------- + +# The `PATH` variable set in Dockerfile should be picked up when image is built +# and used as devcontainer (but it seems this is not the case) +echo "${PATH}" + +envrc_file="${workspace_dir}/.envrc" + +# Test for existence of `.envrc` file +if test -f "${envrc_file}"; then + # Test whether `direnv` is on the PATH + if command -v direnv; then + # Allow direnv to load `.envrc` files in the workspace mount + direnv allow "${workspace_dir}" + fi +fi diff --git a/.devcontainer/package.json b/.devcontainer/package.json new file mode 100644 index 0000000..a680d4a --- /dev/null +++ b/.devcontainer/package.json @@ -0,0 +1,27 @@ +{ + "private": true, + "dependencies": { + "@commitlint/cli": "^17.3.0", + "@commitlint/config-conventional": "^17.3.0", + "@cspell/dict-git": "^2.0.0", + "@trunkio/launcher": "^1.1.0", + "cspell-cli": "^6.16.0", + "eslint": "^8.40.0", + "eslint-plugin-jsonc": "^2.8.0", + "hint": "^7.1.8", + "htmlhint": "^1.1.4", + "jscpd": "^3.5.9", + "jsonlint": "^1.6.3", + "lintspaces-cli": "^0.8.0", + "markdown-link-check": "^3.11.2", + "npm-package-json-lint": "^6.4.0", + "prettier": "^2.8.8", + "secretlint": "^6.2.3", + "sql-formatter": "^12.2.0", + "strip-ansi-cli": "^3.0.2", + "stylelint": "^15.6.1", + "textlint": "^13.3.2", + "typescript": "^5.0.4", + "v8r": "^2.0.0" + } +} diff --git a/.devcontainer/run.d/00_apt.sh b/.devcontainer/run.d/00_apt.sh deleted file mode 100755 index 6aead8c..0000000 --- a/.devcontainer/run.d/00_apt.sh +++ /dev/null @@ -1,52 +0,0 @@ -#!/bin/sh -ex - -tmp_dir="$(mktemp -d)" -clean() { rm -rf "${tmp_dir}"; } -trap clean EXIT - -# Custom sources -# ----------------------------------------------------------------------------- - -cd "${tmp_dir}" - -NODESOURCE_URL=https://deb.nodesource.com/setup_19.x -NODESOURCE_SCRIPT=nodesource_setup.sh - -# Set up APT for latest Node.js -wget -q "${NODESOURCE_URL}" -O "${NODESOURCE_SCRIPT}" -chmod 755 "${NODESOURCE_SCRIPT}" -"./${NODESOURCE_SCRIPT}" - -YARN_DEB_REPO=https://dl.yarnpkg.com/debian -YARN_PUBKEY_URL="${YARN_DEB_REPO}/pubkey.gpg" -YARN_PUBKEY=pubkey.gpg -YARN_KEY_PATH="/usr/share/keyrings/yarnkey.gpg" -YARN_LIST=/etc/apt/sources.list.d/yarn.list - -# Set up APT for latest Yarn -wget -q "${YARN_PUBKEY_URL}" -O "${YARN_PUBKEY}" -rm -f "${YARN_KEY_PATH}" -gpg --dearmor --output "${YARN_KEY_PATH}" "${YARN_PUBKEY}" -cat >"${YARN_LIST}" <>/root/.profile <&2 - exit 1 -fi - -# Remove ACLs on files in the workspace mount so that the default system umask -# is respected -# https://github.com/orgs/community/discussions/26026#discussioncomment-3250078 -whoami="$(whoami)" -sudo chown -R "${whoami}" "${workspace_dir}" -sudo setfacl -bnR "${workspace_dir}" - -# The `PATH` variable set in Dockerfile should be picked up when image is built -# and used as devcontainer (but it seems this is not the case) -echo "${PATH}" - -# Test whether `direnv` is on the PATH -if command -v direnv; then - # Allow direnv to load `.envrc` files in the workspace mount - direnv allow "${workspace_dir}" -fi diff --git a/.editorconfig b/.editorconfig index 2eed282..aee032f 100644 --- a/.editorconfig +++ b/.editorconfig @@ -16,6 +16,10 @@ max_line_length = off [*.sh] indent_size = 4 +[Makefile] +indent_style = tab +indent_size = 4 + [LICENSE] indent_size = 2 diff --git a/.gitignore b/.gitignore index 3c3629e..e78d3e9 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,6 @@ node_modules + +# The devcontainer lock files should not be committed to the repository, as the +# dependencies should be recalculated on every run +.devcontainer/Brewfile.lock.json +.devcontainer/yarn.lock diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml index 1ea811b..2b9faaa 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -14,7 +14,7 @@ lint: - gitleaks@8.16.3 - hadolint@2.12.0 - prettier@2.8.8 - - semgrep@1.20.0 + - semgrep@1.22.0 - shellcheck@0.9.0 - shfmt@3.5.0 - yamllint@1.31.0 diff --git a/Makefile b/Makefile index 1f3ddbc..2e358e8 100644 --- a/Makefile +++ b/Makefile @@ -1,19 +1,15 @@ # ============================================================================= -# Project build +# Primary build # ============================================================================= .EXPORT_ALL_VARIABLES: -# POSIX locale -LC_ALL = C +include common.mk -# ANSI formatting -B = [1m -U = [4m -RED = [0;31m -RST = [0m - -TOP_DIR = $(patsubst %/,%,$(dir $(lastword $(MAKEFILE_LIST)))) +trunk_args= +ifeq ($(CI),true) +trunk_args += --ci --ci-progress +endif # Primary targets # ============================================================================= @@ -23,62 +19,68 @@ TOP_DIR = $(patsubst %/,%,$(dir $(lastword $(MAKEFILE_LIST)))) .DEFAULT_GOAL = help -help: - @ printf 'Usage: \e$(B)make\e$(RST) [ target ]\n\n' - @ printf 'Available targets:\n\n' - @ grep -E '^.PHONY: [a-z-]+ #' Makefile | \ - sed -E 's,^.PHONY: ([a-z-]+) # (.*),\1#\2,' | \ - column -s '#' -t | \ - sed -E "s,^([a-z-]+), \x1b$(B)\1\x1b$(RST)," - +help: _help -.PHONY: install # Install the project dependencies +.PHONY: init # Initialize the build system # ----------------------------------------------------------------------------- -install: node_modules +init: node_modules node_modules: package.json - yarn install + yarn install $(trunk_args) touch $@ -install: .git/config +init: .git/config .git/config: node_modules - yarn trunk git-hooks sync + yarn trunk git-hooks sync $(trunk_args) touch $@ -.PHONY: upgrade # Upgrade the project dependencies +.PHONY: upgrade # Upgrade the build system dependencies # ----------------------------------------------------------------------------- -upgrade: install - yarn trunk upgrade +upgrade: init + yarn trunk upgrade $(trunk_args) .PHONY: check # Check new and changed files # ----------------------------------------------------------------------------- -check: install - yarn trunk check +check: init + yarn trunk check $(trunk_args) .PHONY: check-all # Check all files in the repository # ----------------------------------------------------------------------------- -check-all: install - yarn trunk check --all +check-all: init + yarn trunk check --all $(trunk_args) .PHONY: format # Format new and changed files # ----------------------------------------------------------------------------- -format: install - yarn trunk fmt +format: init + yarn trunk fmt $(trunk_args) .PHONY: format-all # Format all files in the repository # ----------------------------------------------------------------------------- -format-all: install - yarn trunk fmt --all +format-all: init + yarn trunk fmt --all $(trunk_args) -# Clean +.PHONY: test-build # Test the devcontainer build # ----------------------------------------------------------------------------- +devcontainer_dir = $(top_dir)/.devcontainer + +test-build: init + . $(devcontainer_dir)/.env && $(devcontainer_dir)/test_build.sh + +.PHONY: ci # Make all CI targets +# ----------------------------------------------------------------------------- + +ci: + CI=true $(MAKE) init upgrade check-all format-all test-build + .PHONY: clean # Remove build artifacts +# ----------------------------------------------------------------------------- + clean: _rm-empty-dirs .PHONY: _rm-empty_-irs diff --git a/common.mk b/common.mk new file mode 100644 index 0000000..6ae0dab --- /dev/null +++ b/common.mk @@ -0,0 +1,25 @@ +# ============================================================================= +# Common setup for all Makefiles +# ============================================================================= + +LC_ALL = C # Ensure simplest POSIX locale + +top_dir = $(abspath $(patsubst %/,%,$(dir $(lastword $(MAKEFILE_LIST))))) + +# Private sub-targets +# ============================================================================= + +.PHONY: _help +# ----------------------------------------------------------------------------- + +# ANSI color codes +BOLD = [1m +NC = [0m + +_help: + @ printf 'Usage: \e$(BOLD)make\e$(NC) [ target ]\n\n' + @ printf 'Available targets:\n\n' + @ grep -E '^.PHONY: [a-z-]+ #' Makefile | \ + sed -E 's,^.PHONY: ([a-z-]+) # (.*),\1#\2,' | \ + column -s '#' -t | \ + sed -E "s,^([a-z-]+), \x1b$(BOLD)\1\x1b$(NC),"