diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..8e85703 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,8 @@ +--- +version: 2 +updates: + # Maintain dependencies for GitHub Actions + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "daily" diff --git a/.github/labels.yml b/.github/labels.yml new file mode 100644 index 0000000..9a507e8 --- /dev/null +++ b/.github/labels.yml @@ -0,0 +1,12 @@ +# The labels in this file are automatically synced with the repository +# using the micnncim/action-label-syncer action. +--- +- name: C-dependency + color: 1abc9c + description: "Category: Dependency" +- name: PR-block + color: 3498db + description: "Pull Request: Do not merge" +- name: PR-merge + color: 3498db + description: "Pull Request: Merge when ready" diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml new file mode 100644 index 0000000..03439b4 --- /dev/null +++ b/.github/release-drafter.yml @@ -0,0 +1,33 @@ +--- +name-template: '$RESOLVED_VERSION 🌈' +tag-template: '$RESOLVED_VERSION' +version-template: '$MAJOR.$MINOR' +categories: + - title: '🚀 Features' + labels: + - 'feature' + - 'enhancement' + - title: '🐛 Bug Fixes' + labels: + - 'fix' + - 'bugfix' + - 'bug' + - title: '🧰 Maintenance' + label: 'chore' +change-template: '- $TITLE @$AUTHOR (#$NUMBER)' +change-title-escapes: '\<*_&' # You can add # and @ to disable mentions, and add ` to disable code blocks. +version-resolver: + major: + labels: + - 'major' + minor: + labels: + - 'minor' + patch: + labels: + - 'patch' + default: minor +template: | + ## Changes + + $CHANGES diff --git a/.github/workflows/action_branch.yml b/.github/workflows/action_branch.yml new file mode 100644 index 0000000..08a0c91 --- /dev/null +++ b/.github/workflows/action_branch.yml @@ -0,0 +1,38 @@ +--- + +# ------------------------------------------------------------------------------------------------- +# Job Name +# ------------------------------------------------------------------------------------------------- +name: build + + +# ------------------------------------------------------------------------------------------------- +# When to run +# ------------------------------------------------------------------------------------------------- +on: + push: + paths: + - 'Makefile' + - 'Dockerfiles/**' + - 'tests/**' + - '.github/workflows/action*.yml' + - '.github/workflows/params.yml' + +jobs: + + # (1/2) Determine repository params + params: + uses: ./.github/workflows/params.yml + + # (2/2) Build + docker: + needs: [params] + uses: devilbox/github-actions/.github/workflows/docker-name-version-flavour-arch.yml@master + with: + enabled: true + can_deploy: ${{ github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/') || startsWith(github.ref, 'refs/heads/release-') }} + matrix: ${{ needs.params.outputs.matrix }} + refs: ${{ needs.params.outputs.refs }} + secrets: + dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }} + dockerhub_password: ${{ secrets.DOCKERHUB_PASSWORD }} diff --git a/.github/workflows/action_pull_request.yml b/.github/workflows/action_pull_request.yml new file mode 100644 index 0000000..21b075b --- /dev/null +++ b/.github/workflows/action_pull_request.yml @@ -0,0 +1,35 @@ +--- + +# ------------------------------------------------------------------------------------------------- +# Job Name +# ------------------------------------------------------------------------------------------------- +name: build + + +# ------------------------------------------------------------------------------------------------- +# When to run +# ------------------------------------------------------------------------------------------------- +on: + pull_request: + + +jobs: + + # (1/2) Determine repository params + params: + uses: ./.github/workflows/params.yml + # Only run for forks (contributor) + if: github.event.pull_request.head.repo.fork + + # (2/2) Build + docker: + needs: [params] + uses: devilbox/github-actions/.github/workflows/docker-name-version-flavour-arch.yml@master + with: + enabled: true + can_deploy: false + matrix: ${{ needs.params.outputs.matrix }} + refs: ${{ needs.params.outputs.refs }} + secrets: + dockerhub_username: "" + dockerhub_password: "" diff --git a/.github/workflows/action_schedule.yml b/.github/workflows/action_schedule.yml new file mode 100644 index 0000000..c25dfa2 --- /dev/null +++ b/.github/workflows/action_schedule.yml @@ -0,0 +1,35 @@ +--- + +# ------------------------------------------------------------------------------------------------- +# Job Name +# ------------------------------------------------------------------------------------------------- +name: nightly + + +# ------------------------------------------------------------------------------------------------- +# When to run +# ------------------------------------------------------------------------------------------------- +on: + # Runs daily + schedule: + - cron: '0 0 * * *' + + +jobs: + + # (1/2) Determine repository params + params: + uses: ./.github/workflows/params.yml + + # (2/2) Build + docker: + needs: [params] + uses: devilbox/github-actions/.github/workflows/docker-name-version-flavour-arch.yml@master + with: + enabled: true + can_deploy: true + matrix: ${{ needs.params.outputs.matrix }} + refs: ${{ needs.params.outputs.refs }} + secrets: + dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }} + dockerhub_password: ${{ secrets.DOCKERHUB_PASSWORD }} diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..f83d099 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,22 @@ +--- + +# ------------------------------------------------------------------------------------------------- +# Job Name +# ------------------------------------------------------------------------------------------------- +name: lint + + +# ------------------------------------------------------------------------------------------------- +# When to run +# ------------------------------------------------------------------------------------------------- +on: + # Runs on Pull Requests + pull_request: + + +# ------------------------------------------------------------------------------------------------- +# What to run +# ------------------------------------------------------------------------------------------------- +jobs: + lint: + uses: devilbox/github-actions/.github/workflows/lint-generic.yml@master diff --git a/.github/workflows/params.yml b/.github/workflows/params.yml new file mode 100644 index 0000000..80b6492 --- /dev/null +++ b/.github/workflows/params.yml @@ -0,0 +1,80 @@ +--- + +# ------------------------------------------------------------------------------------------------- +# Job Name +# ------------------------------------------------------------------------------------------------- +name: params + + +# ------------------------------------------------------------------------------------------------- +# Custom Variables +# ------------------------------------------------------------------------------------------------- +env: + MATRIX: >- + [ + { + "NAME": "tf-fmt", + "VERSION": [ + "latest", + "1.3", + "1.2", + "1.1", + "1.0", + "0.15", + "0.14", + "0.13", + "0.12" + ], + "FLAVOUR": ["latest"], + "ARCH": ["linux/amd64", "linux/386", "linux/arm64", "linux/arm/v7", "linux/arm/v6", "linux/ppc64le", "linux/s390x"] + } + ] + + +# ------------------------------------------------------------------------------------------------- +# When to run +# ------------------------------------------------------------------------------------------------- +on: + workflow_call: + outputs: + matrix: + description: "The determined version matrix" + value: ${{ jobs.params.outputs.matrix }} + refs: + description: "The determined git ref matrix (only during scheduled run)" + value: ${{ jobs.params.outputs.refs }} + +jobs: + params: + runs-on: ubuntu-latest + + outputs: + matrix: ${{ steps.set-matrix.outputs.matrix }} + refs: ${{ steps.set-refs.outputs.matrix }} + + steps: + - name: "[Set-Output] Matrix" + id: set-matrix + run: | + echo "matrix=$( echo '${{ env.MATRIX }}' | jq -M -c )" >> $GITHUB_OUTPUT + + - name: "[Set-Output] Matrix 'Refs' (master branch and latest tag)" + id: set-refs + uses: cytopia/git-ref-matrix-action@v0.1.12 + with: + repository_default_branch: master + branches: master + num_latest_tags: 0 + if: github.event_name == 'schedule' + + - name: "[DEBUG] Show settings'" + run: | + echo 'Matrix' + echo '--------------------' + echo '${{ steps.set-matrix.outputs.matrix }}' + echo + + echo 'Matrix: Refs' + echo '--------------------' + echo '${{ steps.set-matrix-refs.outputs.matrix }}' + echo diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml new file mode 100644 index 0000000..1a63d7e --- /dev/null +++ b/.github/workflows/release-drafter.yml @@ -0,0 +1,19 @@ +--- +name: Release Drafter + +on: + push: + # branches to consider in the event; optional, defaults to all + branches: + - master + +jobs: + update_release_draft: + runs-on: ubuntu-latest + steps: + # Drafts your next Release notes as Pull Requests are merged into "master" + - uses: release-drafter/release-drafter@v5 + with: + publish: true + env: + GITHUB_TOKEN: ${{ secrets.RELEASE_DRAFTER_TOKEN }} diff --git a/.github/workflows/repository.yml b/.github/workflows/repository.yml new file mode 100644 index 0000000..ca21e7d --- /dev/null +++ b/.github/workflows/repository.yml @@ -0,0 +1,25 @@ +--- +name: Repository + +on: + push: + branches: + - master + paths: + - .github/labels.yml + +jobs: + labels: + name: Labels + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Sync labels + uses: micnncim/action-label-syncer@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + manifest: .github/labels.yml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7457dff --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +Makefile.docker +Makefile.lint diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 15f2b94..0000000 --- a/.travis.yml +++ /dev/null @@ -1,73 +0,0 @@ ---- - -### -### Enable sudo (required for docker service) -### -sudo: required - - -### -### Language -### -language: minimal - - -### -### Add services -### -services: - - docker - - -### -### Build Matrix -### -env: - matrix: - - VERSION=0.12 - - VERSION=latest - - -### -### Install requirements -### -install: - - retry() { - for ((n=0; n<10; n++)); do - echo "[${n}] ${*}"; - if eval "${*}"; then - return 0; - fi; - done; - return 1; - } - - -### -### Check generation changes, build and test -### -before_script: - - retry make lint - - retry make build TAG=${VERSION} - - retry make test TAG=${VERSION} - - -### -### Push to Dockerhub -### -script: - # Push to docker hub on success - - if [ "${TRAVIS_PULL_REQUEST}" == "false" ]; then - while ! make login USER="${DOCKER_USERNAME}" PASS="${DOCKER_PASSWORD}"; do sleep 1; done; - if [ -n "${TRAVIS_TAG}" ]; then - while ! make push TAG="${VERSION}-${TRAVIS_TAG}"; do sleep 1; done; - elif [ "${TRAVIS_BRANCH}" == "master" ]; then - while ! make push TAG=${VERSION}; do sleep 1; done; - elif [[ ${TRAVIS_BRANCH} =~ ^(release-[.0-9]+)$ ]]; then - while ! make push TAG="${VERSION}-${TRAVIS_BRANCH}"; do sleep 1; done; - else - echo "Skipping branch ${TRAVIS_BRANCH}"; - fi - else - echo "Skipping push on PR"; - fi diff --git a/.yamllint b/.yamllint new file mode 100644 index 0000000..2c7758f --- /dev/null +++ b/.yamllint @@ -0,0 +1,13 @@ +--- +extends: default + +ignore: | + .yamllint + + +rules: + truthy: + allowed-values: ['true', 'false'] + check-keys: False + level: error + line-length: disable diff --git a/Dockerfile b/Dockerfiles/Dockerfile similarity index 73% rename from Dockerfile rename to Dockerfiles/Dockerfile index be2b9d8..1b9e3bf 100644 --- a/Dockerfile +++ b/Dockerfiles/Dockerfile @@ -1,17 +1,17 @@ -FROM debian:stable-slim as builder +FROM alpine:3.16 as builder # Install build dependencies RUN set -eux \ - && DEBIAN_FRONTEND=noninteractive apt-get update -qq \ - && DEBIAN_FRONTEND=noninteractive apt-get install -qq -y --no-install-recommends --no-install-suggests \ + && apk add --no-cache \ ca-certificates \ + coreutils \ curl \ unzip # Get Terraform -ARG TF_VERSION=latest +ARG VERSION=latest RUN set -eux \ - && if [ "${TF_VERSION}" = "latest" ]; then \ + && if [ "${VERSION}" = "latest" ]; then \ VERSION="$( curl -sS https://releases.hashicorp.com/terraform/ \ | tac | tac \ | grep -Eo '/[.0-9]+/' \ @@ -21,7 +21,7 @@ RUN set -eux \ else \ VERSION="$( curl -sS https://releases.hashicorp.com/terraform/ \ | tac | tac \ - | grep -Eo "/${TF_VERSION}\.[.0-9]+/" \ + | grep -Eo "/${VERSION}\.[.0-9]+/" \ | grep -Eo '[.0-9]+' \ | sort -V \ | tail -1 )"; \ @@ -30,13 +30,16 @@ RUN set -eux \ https://releases.hashicorp.com/terraform/${VERSION}/terraform_${VERSION}_linux_amd64.zip \ && unzip terraform_${VERSION}_linux_amd64.zip \ && mv terraform /usr/bin/terraform \ - && chmod +x /usr/bin/terraform + && chmod +x /usr/bin/terraform \ + \ + && terraform --version # Use a clean tiny image to store artifacts in -FROM alpine:3.8 +FROM alpine:3.16 as production LABEL \ maintainer="cytopia " \ repo="https://github.com/cytopia/docker-terragrunt-fmt" + COPY --from=builder /usr/bin/terraform /usr/bin/terraform COPY data/terragrunt-fmt.sh /terragrunt-fmt.sh COPY data/fmt.sh /fmt.sh diff --git a/data/fmt.sh b/Dockerfiles/data/fmt.sh similarity index 94% rename from data/fmt.sh rename to Dockerfiles/data/fmt.sh index f0fab61..a9d5339 100755 --- a/data/fmt.sh +++ b/Dockerfiles/data/fmt.sh @@ -57,8 +57,8 @@ if [ "${_write}" = "1" ]; then _PERM="$(stat -c %a "${_file}")" # Adjust permissions of temporary file - chown ${_UID}:${_GID} "${_temp}" - chmod ${_PERM} "${_temp}" + chown "${_UID}:${_GID}" "${_temp}" + chmod "${_PERM}" "${_temp}" # Overwrite existing file mv -f "${_temp}" "${_file}" diff --git a/data/terragrunt-fmt.sh b/Dockerfiles/data/terragrunt-fmt.sh similarity index 100% rename from data/terragrunt-fmt.sh rename to Dockerfiles/data/terragrunt-fmt.sh diff --git a/Makefile b/Makefile index 00d277d..ecd54cd 100644 --- a/Makefile +++ b/Makefile @@ -2,40 +2,116 @@ ifneq (,) .error This Makefile requires GNU Make. endif -.PHONY: build rebuild lint test _test-tf-version _test-fmt-ok _test-fmt-none _test-fmt-fail tag pull login push enter - -CURRENT_DIR = $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) - -DIR = . -FILE = Dockerfile -IMAGE = cytopia/terragrunt-fmt +# Ensure additional Makefiles are present +MAKEFILES = Makefile.docker Makefile.lint +$(MAKEFILES): URL=https://raw.githubusercontent.com/devilbox/makefiles/master/$(@) +$(MAKEFILES): + @if ! (curl --fail -sS -o $(@) $(URL) || wget -O $(@) $(URL)); then \ + echo "Error, curl or wget required."; \ + echo "Exiting."; \ + false; \ + fi +include $(MAKEFILES) + +# Set default Target +.DEFAULT_GOAL := help + + +# ------------------------------------------------------------------------------------------------- +# Default configuration +# ------------------------------------------------------------------------------------------------- +# Own vars TAG = latest -build: - docker build --build-arg TF_VERSION=$(TAG) -t $(IMAGE) -f $(DIR)/$(FILE) $(DIR) +# Makefile.docker overwrites +NAME = tg-fmt +VERSION = latest +IMAGE = cytopia/terragrunt-fmt +FLAVOUR = latest +DIR = Dockerfiles -rebuild: pull - docker build --no-cache --build-arg TF_VERSION=$(TAG) -t $(IMAGE) -f $(DIR)/$(FILE) $(DIR) - -lint: - @docker run --rm -v $(CURRENT_DIR):/data cytopia/file-lint file-cr --text --ignore '.git/,.github/,tests/' --path . - @docker run --rm -v $(CURRENT_DIR):/data cytopia/file-lint file-crlf --text --ignore '.git/,.github/,tests/' --path . - @docker run --rm -v $(CURRENT_DIR):/data cytopia/file-lint file-trailing-single-newline --text --ignore '.git/,.github/,tests/' --path . - @docker run --rm -v $(CURRENT_DIR):/data cytopia/file-lint file-trailing-space --text --ignore '.git/,.github/,tests/' --path . - @docker run --rm -v $(CURRENT_DIR):/data cytopia/file-lint file-utf8 --text --ignore '.git/,.github/,tests/' --path . - @docker run --rm -v $(CURRENT_DIR):/data cytopia/file-lint file-utf8-bom --text --ignore '.git/,.github/,tests/' --path . +FILE = Dockerfile -test: - @$(MAKE) --no-print-directory _test-tf-version - @$(MAKE) --no-print-directory _test-fmt-ok - @$(MAKE) --no-print-directory _test-fmt-none - @$(MAKE) --no-print-directory _test-fmt-fail +# Building from master branch: Tag == 'latest' +ifeq ($(strip $(TAG)),latest) + ifeq ($(strip $(VERSION)),latest) + DOCKER_TAG = latest + else + DOCKER_TAG = $(VERSION) + endif +# Building from any other branch or tag: Tag == '' +else + ifeq ($(strip $(VERSION)),latest) + DOCKER_TAG = latest-$(TAG) + else + DOCKER_TAG = $(VERSION)-$(TAG) + endif +endif +# Makefile.lint overwrites +FL_IGNORES = .git/,.github/ +SC_IGNORES = .git/,.github/ +JL_IGNORES = .git/,.github/ + + +# ------------------------------------------------------------------------------------------------- +# Default Target +# ------------------------------------------------------------------------------------------------- +.PHONY: help +help: + @echo "lint Lint project files and repository" + @echo + @echo "build [ARCH=...] [TAG=...] Build Docker image" + @echo "rebuild [ARCH=...] [TAG=...] Build Docker image without cache" + @echo "push [ARCH=...] [TAG=...] Push Docker image to Docker hub" + @echo + @echo "manifest-create [ARCHES=...] [TAG=...] Create multi-arch manifest" + @echo "manifest-push [TAG=...] Push multi-arch manifest" + @echo + @echo "test [ARCH=...] Test built Docker image" + @echo + + +# ------------------------------------------------------------------------------------------------- +# Docker Targets +# ------------------------------------------------------------------------------------------------- +.PHONY: build +build: ARGS+=--build-arg VERSION=$(VERSION) +build: docker-arch-build + +.PHONY: rebuild +rebuild: ARGS+=--build-arg VERSION=$(VERSION) +rebuild: docker-arch-rebuild + +.PHONY: push +push: docker-arch-push + + +# ------------------------------------------------------------------------------------------------- +# Manifest Targets +# ------------------------------------------------------------------------------------------------- +.PHONY: manifest-create +manifest-create: docker-manifest-create + +.PHONY: manifest-push +manifest-push: docker-manifest-push + + +# ------------------------------------------------------------------------------------------------- +# Test Targets +# ------------------------------------------------------------------------------------------------- +.PHONY: test +test: _test-tf-version +test: _test-fmt-ok +test: _test-fmt-none +test: _test-fmt-fail + +.PHONY: _test-tf-version _test-tf-version: @echo "------------------------------------------------------------" @echo "- Testing correct Terraform version" @echo "------------------------------------------------------------" - @if [ "$(TAG)" = "latest" ]; then \ + @if [ "$(VERSION)" = "latest" ]; then \ echo "Fetching latest version from HashiCorp release page"; \ LATEST="$$( \ curl -L -sS https://releases.hashicorp.com/terraform/ \ @@ -46,24 +122,27 @@ _test-tf-version: | tail -1 \ )"; \ echo "Testing for latest: $${LATEST}"; \ - if ! docker run --rm $(IMAGE) --version | grep -E "^Terraform[[:space:]]*v?$${LATEST}$$"; then \ + if ! docker run --rm --platform $(ARCH) $(IMAGE):$(DOCKER_TAG) --version | grep -E "^Terraform[[:space:]]*v?$${LATEST}$$"; then \ + docker run --rm --platform $(ARCH) $(IMAGE):$(DOCKER_TAG) --version; \ echo "Failed"; \ exit 1; \ fi; \ else \ - echo "Testing for tag: $(TAG)"; \ - if ! docker run --rm $(IMAGE) --version | grep -E "^Terraform[[:space:]]*v?$(TAG)\.[.0-9]+$$"; then \ + echo "Testing for tag: $(VERSION)"; \ + if ! docker run --rm --platform $(ARCH) $(IMAGE):$(DOCKER_TAG) --version | grep -E "^Terraform[[:space:]]*v?$(VERSION)\.[.0-9]+$$"; then \ + docker run --rm --platform $(ARCH) $(IMAGE):$(DOCKER_TAG) --version; \ echo "Failed"; \ exit 1; \ fi; \ fi; \ echo "Success"; \ +.PHONY: _test-fmt-ok _test-fmt-ok: @echo "------------------------------------------------------------" @echo "- Testing terragrunt-fmt (OK) [recursive]" @echo "------------------------------------------------------------" - @if ! docker run --rm -v $(CURRENT_DIR)/tests/ok:/data $(IMAGE) -write=false -list=true -check -diff -recursive; then \ + @if ! docker run --rm --platform $(ARCH) -v $(CURRENT_DIR)/tests/ok:/data $(IMAGE):$(DOCKER_TAG) -write=false -list=true -check -diff -recursive; then \ echo "Failed"; \ exit 1; \ fi; \ @@ -71,7 +150,7 @@ _test-fmt-ok: @echo "------------------------------------------------------------" @echo "- Testing terragrunt-fmt (OK) [dir]" @echo "------------------------------------------------------------" - @if ! docker run --rm -v $(CURRENT_DIR)/tests/ok:/data $(IMAGE) -write=false -list=true -check -diff; then \ + @if ! docker run --rm --platform $(ARCH) -v $(CURRENT_DIR)/tests/ok:/data $(IMAGE):$(DOCKER_TAG) -write=false -list=true -check -diff; then \ echo "Failed"; \ exit 1; \ fi; \ @@ -79,17 +158,18 @@ _test-fmt-ok: @echo "------------------------------------------------------------" @echo "- Testing terragrunt-fmt (OK) [file]" @echo "------------------------------------------------------------" - @if ! docker run --rm -v $(CURRENT_DIR)/tests/ok:/data $(IMAGE) -write=false -list=true -check -diff terragrunt.hcl; then \ + @if ! docker run --rm --platform $(ARCH) -v $(CURRENT_DIR)/tests/ok:/data $(IMAGE):$(DOCKER_TAG) -write=false -list=true -check -diff terragrunt.hcl; then \ echo "Failed"; \ exit 1; \ fi; \ echo "Success"; +.PHONY: _test-fmt-none _test-fmt-none: @echo "------------------------------------------------------------" @echo "- Testing terragrunt-fmt (NONE) [recursive]" @echo "------------------------------------------------------------" - @if ! docker run --rm -v $(CURRENT_DIR)/data:/data $(IMAGE) -write=false -list=true -check -diff -recursive; then \ + @if ! docker run --rm --platform $(ARCH) -v $(CURRENT_DIR)/Dockerfiles/data:/data $(IMAGE):$(DOCKER_TAG) -write=false -list=true -check -diff -recursive; then \ echo "Failed"; \ exit 1; \ fi; \ @@ -97,17 +177,18 @@ _test-fmt-none: @echo "------------------------------------------------------------" @echo "- Testing terragrunt-fmt (NONE) [dir]" @echo "------------------------------------------------------------" - @if ! docker run --rm -v $(CURRENT_DIR)/data:/data $(IMAGE) -write=false -list=true -check -diff; then \ + @if ! docker run --rm --platform $(ARCH) -v $(CURRENT_DIR)/Dockerfiles/data:/data $(IMAGE):$(DOCKER_TAG) -write=false -list=true -check -diff; then \ echo "Failed"; \ exit 1; \ fi; \ echo "Success"; +.PHONY: _test-fmt-fail _test-fmt-fail: @echo "------------------------------------------------------------" @echo "- Testing terragrunt-fmt (FAIL) [recursive]" @echo "------------------------------------------------------------" - @if docker run --rm -v $(CURRENT_DIR)/tests/fail:/data $(IMAGE) -write=false -list=true -check -diff -recursive; then \ + @if docker run --rm --platform $(ARCH) -v $(CURRENT_DIR)/tests/fail:/data $(IMAGE):$(DOCKER_TAG) -write=false -list=true -check -diff -recursive; then \ echo "Failed"; \ exit 1; \ fi; \ @@ -115,7 +196,7 @@ _test-fmt-fail: @echo "------------------------------------------------------------" @echo "- Testing terragrunt-fmt (FAIL) [dir]" @echo "------------------------------------------------------------" - @if docker run --rm -v $(CURRENT_DIR)/tests/fail:/data $(IMAGE) -write=false -list=true -check -diff; then \ + @if docker run --rm --platform $(ARCH) -v $(CURRENT_DIR)/tests/fail:/data $(IMAGE):$(DOCKER_TAG) -write=false -list=true -check -diff; then \ echo "Failed"; \ exit 1; \ fi; \ @@ -123,26 +204,8 @@ _test-fmt-fail: @echo "------------------------------------------------------------" @echo "- Testing terragrunt-fmt (FAIL) [file]" @echo "------------------------------------------------------------" - @if docker run --rm -v $(CURRENT_DIR)/tests/fail:/data $(IMAGE) -write=false -list=true -check -diff terragrunt.hcl; then \ + @if docker run --rm --platform $(ARCH) -v $(CURRENT_DIR)/tests/fail:/data $(IMAGE):$(DOCKER_TAG) -write=false -list=true -check -diff terragrunt.hcl; then \ echo "Failed"; \ exit 1; \ fi; \ echo "Success"; - -tag: - docker tag $(IMAGE) $(IMAGE):$(TAG) - -pull: - @grep -E '^\s*FROM' Dockerfile \ - | sed -e 's/^FROM//g' -e 's/[[:space:]]*as[[:space:]]*.*$$//g' \ - | xargs -n1 docker pull; - -login: - yes | docker login --username $(USER) --password $(PASS) - -push: - @$(MAKE) tag TAG=$(TAG) - docker push $(IMAGE):$(TAG) - -enter: - docker run --rm --name $(subst /,-,$(IMAGE)) -it --entrypoint=/bin/sh $(ARG) $(IMAGE):$(TAG) diff --git a/README.md b/README.md index e652dcd..d53cf23 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,20 @@ # Docker image for `terragrunt-fmt` -[![Build Status](https://travis-ci.com/cytopia/docker-terragrunt-fmt.svg?branch=master)](https://travis-ci.com/cytopia/docker-terragrunt-fmt) [![Tag](https://img.shields.io/github/tag/cytopia/docker-terragrunt-fmt.svg)](https://github.com/cytopia/docker-terragrunt-fmt/releases) -[![](https://images.microbadger.com/badges/version/cytopia/terragrunt-fmt:latest.svg?&kill_cache=1)](https://microbadger.com/images/cytopia/terragrunt-fmt:latest "terragrunt-fmt") -[![](https://images.microbadger.com/badges/image/cytopia/terragrunt-fmt:latest.svg?&kill_cache=1)](https://microbadger.com/images/cytopia/terragrunt-fmt:latest "terragrunt-fmt") -[![](https://img.shields.io/docker/pulls/cytopia/terragrunt-fmt.svg)](https://hub.docker.com/r/cytopia/terragrunt-fmt) [![](https://img.shields.io/badge/github-cytopia%2Fdocker--terragrunt--fmt-red.svg)](https://github.com/cytopia/docker-terragrunt-fmt "github.com/cytopia/docker-terragrunt-fmt") [![License](https://img.shields.io/badge/license-MIT-%233DA639.svg)](https://opensource.org/licenses/MIT) +[![lint](https://github.com/cytopia/docker-terragrunt-fmt/workflows/lint/badge.svg)](https://github.com/cytopia/docker-terragrunt-fmt/actions?query=workflow%3Alint) +[![build](https://github.com/cytopia/docker-terragrunt-fmt/workflows/build/badge.svg)](https://github.com/cytopia/docker-terragrunt-fmt/actions?query=workflow%3Abuild) +[![nightly](https://github.com/cytopia/docker-terragrunt-fmt/workflows/nightly/badge.svg)](https://github.com/cytopia/docker-terragrunt-fmt/actions?query=workflow%3Anightly) + + > #### All [#awesome-ci](https://github.com/topics/awesome-ci) Docker images > -> [ansible][ansible-git-lnk] **•** > [ansible-lint][alint-git-lnk] **•** +> [ansible][ansible-git-lnk] **•** > [awesome-ci][aci-git-lnk] **•** +> [bandit][bandit-git-lnk] **•** > [black][black-git-lnk] **•** > [checkmake][cm-git-lnk] **•** > [eslint][elint-git-lnk] **•** @@ -21,25 +23,26 @@ > [goimports][gimp-git-lnk] **•** > [golint][glint-git-lnk] **•** > [jsonlint][jlint-git-lnk] **•** +> [kubeval][kubeval-git-lnk] **•** +> [linkcheck][linkcheck-git-lnk] **•** +> [mypy][mypy-git-lnk] **•** +> [php-cs-fixer][pcsf-git-lnk] **•** > [phpcbf][pcbf-git-lnk] **•** > [phpcs][pcs-git-lnk] **•** > [phplint][plint-git-lnk] **•** -> [php-cs-fixer][pcsf-git-lnk] **•** > [pycodestyle][pycs-git-lnk] **•** +> [pydocstyle][pyds-git-lnk] **•** > [pylint][pylint-git-lnk] **•** > [terraform-docs][tfdocs-git-lnk] **•** -> [terragrunt][tg-git-lnk] **•** > [terragrunt-fmt][tgfmt-git-lnk] **•** +> [terragrunt][tg-git-lnk] **•** > [yamlfmt][yfmt-git-lnk] **•** > [yamllint][ylint-git-lnk] -> #### All [#awesome-ci](https://github.com/topics/awesome-ci) Makefiles -> -> Visit **[cytopia/makefiles](https://github.com/cytopia/makefiles)** for seamless project integration, minimum required best-practice code linting and CI. +View **[Dockerfiles](https://github.com/cytopia/docker-terragrunt-fmt/blob/master/Dockerfiles/)** on GitHub. -View **[Dockerfile](https://github.com/cytopia/docker-terragrunt-fmt/blob/master/Dockerfile)** on GitHub. -[![Docker hub](http://dockeri.co/image/cytopia/terragrunt-fmt?&kill_cache=1)](https://hub.docker.com/r/cytopia/terragrunt-fmt) +**Available Architectures:** `amd64`, `i386`, `arm64`, `arm/v7`, `arm/v6`, `ppc64le`, `s390x` Tiny Alpine-based multistage-build dockerized version of [Terraform](https://github.com/hashicorp/terraform)[1] with the ability to do `terraform fmt` on Terragrunt files (`.hcl`). This is achieved by creating a temporary file within the container with an `.tf` extension and then running `terraform fmt` on it. @@ -48,192 +51,57 @@ The image is built nightly against multiple stable versions and pushed to Docker [1] Official project: https://github.com/hashicorp/terraform +## :whale: Available Docker image versions -## Available Docker image versions - -The following Docker image tags are rolling releases and built and updated nightly. This means -they always contain the latest stable version as shown below. - -| Docker tag | Terraform version | -|--------------|------------------------| -| `latest` | latest stable | -| `0.12` | latest stable `0.12.x` | - - -## Docker mounts - -The working directory inside the Docker container is **`/data/`** and should be mounted to your local filesystem where your Terragrant project resides. -(See [Examples](#examples) for mount location usage.) - - -## Usage -``` -$ docker run --rm cytopia/terragrunt-fmt --help -``` -``` -Usage: cytopia/terragrunt-fmt [options] [DIR] - cytopia/terragrunt-fmt --help - cytopia/terragrunt-fmt --version - - Rewrites all Terragrunt configuration files to a canonical format. All - hcl configuration files (.hcl) are updated. - - If DIR is not specified then the current working directory will be used. - -Options: - - -list=true List files whose formatting differs - - -write=false Don't write to source files - (always disabled if using -check) - - -diff Display diffs of formatting changes - - -check Check if the input is formatted. Exit status will be 0 if all - input is properly formatted and non-zero otherwise. - - -recursive Also process files in subdirectories. By default, only the - given directory (or current directory) is processed. - - -ignore=a,b Comma separated list of paths to ignore. - The wildcard character '*' is supported. -``` - - -## Examples - -### List filenames that need to be fixed -```bash -$ docker run --rm -v $(pwd):/data cytopia/terragrunt-fmt -list - -[INFO] Finding files: for file in *.hcl; do -terraform fmt -list=true -write=true validate.hcl -../tmp/validate.hcl.tf -``` - -### Show diff of files that need to be fixed -```bash -$ docker run --rm -v $(pwd):/data cytopia/terragrunt-fmt -diff - -[INFO] Finding files: for file in *.hcl; do -terraform fmt -list=true -write=false -diff validate.hcl -../tmp/validate.hcl.tf ---- old/../tmp/validate.hcl.tf -+++ new/../tmp/validate.hcl.tf -@@ -35,9 +35,9 @@ - # which is not being used (disable_init) - remote_state { - backend = "s3" -- config = { -- bucket = "none" -- key = "none" -+ config = { -+ bucket = "none" -+ key = "none" - region = "eu-central-1" - } -``` +[![](https://img.shields.io/docker/pulls/cytopia/terragrunt-fmt.svg)](https://hub.docker.com/r/cytopia/terragrunt-fmt) +[![Docker](https://badgen.net/badge/icon/:latest?icon=docker&label=cytopia/terragrunt-fmt)](https://hub.docker.com/r/cytopia/terragrunt-fmt) -### Fix files -```bash -$ docker run --rm -v $(pwd):/data cytopia/terragrunt-fmt -write +#### Rolling releaess -[INFO] Finding files: for file in *.hcl; do -terraform fmt -list=true -write=true validate.hcl -../tmp/validate.hcl.tf -``` +The following Docker image tags are rolling releases and are built and updated every night. -### Fix files and show diff -```bash -$ docker run --rm -v $(pwd):/data cytopia/terragrunt-fmt -write -diff - -[INFO] Finding files: for file in *.hcl; do -terraform fmt -list=true -write=false -diff validate.hcl -../tmp/validate.hcl.tf ---- old/../tmp/validate.hcl.tf -+++ new/../tmp/validate.hcl.tf -@@ -35,9 +35,9 @@ - # which is not being used (disable_init) - remote_state { - backend = "s3" -- config = { -- bucket = "none" -- key = "none" -+ config = { -+ bucket = "none" -+ key = "none" - region = "eu-central-1" - } -``` +[![nightly](https://github.com/cytopia/docker-terragrunt-fmt/workflows/nightly/badge.svg)](https://github.com/cytopia/docker-terragrunt-fmt/actions?query=workflow%3Anightly) -### List filenames that need to be fixed recursively -```bash -$ docker run --rm -v $(pwd):/data cytopia/terragrunt-fmt -list -recursive +| Docker Tag | Git Ref | terraform | Available Architectures | +|----------------------|-----------|--------------|----------------------------------------------| +| `latest` | master | latest | `amd64`, `i386`, `arm64`, `arm/v7`, `arm/v6`, `ppc64le`, `s390x` | +| `1.3` | master | **`1.3.x`** | `amd64`, `i386`, `arm64`, `arm/v7`, `arm/v6`, `ppc64le`, `s390x` | +| `1.2` | master | **`1.2.x`** | `amd64`, `i386`, `arm64`, `arm/v7`, `arm/v6`, `ppc64le`, `s390x` | +| `1.1` | master | **`1.1.x`** | `amd64`, `i386`, `arm64`, `arm/v7`, `arm/v6`, `ppc64le`, `s390x` | +| `1.0` | master | **`1.0.x`** | `amd64`, `i386`, `arm64`, `arm/v7`, `arm/v6`, `ppc64le`, `s390x` | +| `0.15` | master | **`0.15.x`** | `amd64`, `i386`, `arm64`, `arm/v7`, `arm/v6`, `ppc64le`, `s390x` | +| `0.14` | master | **`0.14.x`** | `amd64`, `i386`, `arm64`, `arm/v7`, `arm/v6`, `ppc64le`, `s390x` | +| `0.13` | master | **`0.13.x`** | `amd64`, `i386`, `arm64`, `arm/v7`, `arm/v6`, `ppc64le`, `s390x` | +| `0.12` | master | **`0.12.x`** | `amd64`, `i386`, `arm64`, `arm/v7`, `arm/v6`, `ppc64le`, `s390x` | -[INFO] Finding files: find . -name '*.hcl' -type f -terraform fmt -list=true -write=false ./prod/eu-central-1/microservice/terragrunt.hcl -../tmp/terragrunt.hcl.tf -terraform fmt -list=true -write=false ./prod/eu-central-1/infra/terragrunt.hcl -../tmp/terragrunt.hcl.tf -``` +#### Point in time releases -### Show diff of files that need to be fixed recursively -```bash -$ docker run --rm -v $(pwd):/data cytopia/terragrunt-fmt -diff -recursive +The following Docker image tags are built once and can be used for reproducible builds. Its version never changes so you will have to update tags in your pipelines from time to time in order to stay up-to-date. -[INFO] Finding files: find . -name '*.hcl' -type f -terraform fmt -list=true -write=false -diff ./prod/eu-central-1/microservice/terragrunt.hcl -../tmp/terragrunt.hcl.tf ---- old/../tmp/terragrunt.hcl.tf -+++ new/../tmp/terragrunt.hcl.tf -@@ -1,5 +1,5 @@ - terraform { -- source = "github.com/cytopia/terraform-aws-iam-cross-account?ref=v0.1.3" -+ source = "github.com/cytopia/terraform-aws-iam-cross-account?ref=v0.1.3" - } -terraform fmt -list=true -write=false -diff ./prod/eu-central-1/infra/terragrunt.hcl -../tmp/terragrunt.hcl.tf ---- old/../tmp/terragrunt.hcl.tf -+++ new/../tmp/terragrunt.hcl.tf -@@ -1,5 +1,5 @@ - terraform { -- source = "github.com/cytopia/terraform-aws-iam-cross-account?ref=v0.1.3" -+ source = "github.com/cytopia/terraform-aws-iam-cross-account?ref=v0.1.3" - } -``` +[![build](https://github.com/cytopia/docker-terragrunt-fmt/workflows/build/badge.svg)](https://github.com/cytopia/docker-terragrunt-fmt/actions?query=workflow%3Abuild) -### Fix recursively -```bash -$ docker run --rm -v $(pwd):/data cytopia/terragrunt-fmt -write -recursive +| Docker Tag | Git Ref | terraform | Available Architectures | +|----------------------|--------------|--------------|----------------------------------------------| +| `latest-` | tag: `` | latest | `amd64`, `i386`, `arm64`, `arm/v7`, `arm/v6`, `ppc64le`, `s390x` | +| `1.3-` | tag: `` | **`1.3.x`** | `amd64`, `i386`, `arm64`, `arm/v7`, `arm/v6`, `ppc64le`, `s390x` | +| `1.2-` | tag: `` | **`1.2.x`** | `amd64`, `i386`, `arm64`, `arm/v7`, `arm/v6`, `ppc64le`, `s390x` | +| `1.1-` | tag: `` | **`1.1.x`** | `amd64`, `i386`, `arm64`, `arm/v7`, `arm/v6`, `ppc64le`, `s390x` | +| `1.0-` | tag: `` | **`1.0.x`** | `amd64`, `i386`, `arm64`, `arm/v7`, `arm/v6`, `ppc64le`, `s390x` | +| `0.15-` | tag: `` | **`0.15.x`** | `amd64`, `i386`, `arm64`, `arm/v7`, `arm/v6`, `ppc64le`, `s390x` | +| `0.14-` | tag: `` | **`0.14.x`** | `amd64`, `i386`, `arm64`, `arm/v7`, `arm/v6`, `ppc64le`, `s390x` | +| `0.13-` | tag: `` | **`0.13.x`** | `amd64`, `i386`, `arm64`, `arm/v7`, `arm/v6`, `ppc64le`, `s390x` | +| `0.12-` | tag: `` | **`0.12.x`** | `amd64`, `i386`, `arm64`, `arm/v7`, `arm/v6`, `ppc64le`, `s390x` | -[INFO] Finding files: find . -name '*.hcl' -type f -terraform fmt -list=true -write=true ./prod/eu-central-1/microservice/terragrunt.hcl -../tmp/terragrunt.hcl.tf -terraform fmt -list=true -write=true ./prod/eu-central-1/infra/terragrunt.hcl -../tmp/terragrunt.hcl.tf -``` +> Where `` refers to the chosen git tag from this repository. -### Ignore files and directories -Ignore all files named `terragrunt.hcl`. -```bash -$ docker run --rm -v $(pwd):/data cytopia/terragrunt-fmt -recursive -ignore=*terragrunt.hcl +## :open_file_folder: Docker mounts -[INFO] Finding files: find . -not \( -path "./*terragrunt.hcl*" \) -name '*.hcl' -type f -terraform fmt -list=true -write=false ./aws/validate.hcl -../tmp/validate.hcl.tf -``` +The working directory inside the Docker container is **`/data/`** and should be mounted locally to +the root of your project. -Ignore all directories named `dev/` and everything inside. -```bash -$ docker run --rm -v $(pwd):/data cytopia/terragrunt-fmt -recursive -ignore=*/dev/ -[INFO] Finding files: find . -not \( -path "./*/dev/*" \) -name '*.hcl' -type f -terraform fmt -list=true -write=false ./prod/eu-central-1/microservice/terragrunt.hcl -../tmp/terragrunt.hcl.tf -terraform fmt -list=true -write=false ./prod/eu-central-1/infra/terragrunt.hcl -../tmp/terragrunt.hcl.tf -``` +## :computer: Usage Ignore all directories named `dev/` and `testing/` and everything inside. ```bash @@ -296,7 +164,7 @@ script: ``` -## Related [#awesome-ci](https://github.com/topics/awesome-ci) projects +## :arrows_counterclockwise: Related [#awesome-ci](https://github.com/topics/awesome-ci) projects ### Docker images @@ -307,6 +175,7 @@ linter below for reproducible local or remote CI tests: |--------|-----------|------|-------------| | [awesome-ci][aci-git-lnk] | [![aci-hub-img]][aci-hub-lnk] | Basic | Tools for git, file and static source code analysis | | [file-lint][flint-git-lnk] | [![flint-hub-img]][flint-hub-lnk] | Basic | Baisc source code analysis | +| [linkcheck][linkcheck-git-lnk] | [![linkcheck-hub-img]][flint-hub-lnk] | Basic | Search for URLs in files and validate their HTTP status code | | [ansible][ansible-git-lnk] | [![ansible-hub-img]][ansible-hub-lnk] | Ansible | Multiple versions and flavours of Ansible | | [ansible-lint][alint-git-lnk] | [![alint-hub-img]][alint-hub-lnk] | Ansible | Lint Ansible | | [gofmt][gfmt-git-lnk] | [![gfmt-hub-img]][gfmt-hub-lnk] | Go | Format Go source code **[1]** | @@ -314,13 +183,17 @@ linter below for reproducible local or remote CI tests: | [golint][glint-git-lnk] | [![glint-hub-img]][glint-hub-lnk] | Go | Lint Go code | | [eslint][elint-git-lnk] | [![elint-hub-img]][elint-hub-lnk] | Javascript | Lint Javascript code | | [jsonlint][jlint-git-lnk] | [![jlint-hub-img]][jlint-hub-lnk] | JSON | Lint JSON files **[1]** | +| [kubeval][kubeval-git-lnk] | [![kubeval-hub-img]][kubeval-hub-lnk] | K8s | Lint Kubernetes files | | [checkmake][cm-git-lnk] | [![cm-hub-img]][cm-hub-lnk] | Make | Lint Makefiles | | [phpcbf][pcbf-git-lnk] | [![pcbf-hub-img]][pcbf-hub-lnk] | PHP | PHP Code Beautifier and Fixer | | [phpcs][pcs-git-lnk] | [![pcs-hub-img]][pcs-hub-lnk] | PHP | PHP Code Sniffer | | [phplint][plint-git-lnk] | [![plint-hub-img]][plint-hub-lnk] | PHP | PHP Code Linter **[1]** | | [php-cs-fixer][pcsf-git-lnk] | [![pcsf-hub-img]][pcsf-hub-lnk] | PHP | PHP Coding Standards Fixer | +| [bandit][bandit-git-lnk] | [![bandit-hub-img]][bandit-hub-lnk] | Python | A security linter from PyCQA | [black][black-git-lnk] | [![black-hub-img]][black-hub-lnk] | Python | The uncompromising Python code formatter | +| [mypy][mypy-git-lnk] | [![mypy-hub-img]][mypy-hub-lnk] | Python | Static source code analysis | | [pycodestyle][pycs-git-lnk] | [![pycs-hub-img]][pycs-hub-lnk] | Python | Python style guide checker | +| [pydocstyle][pyds-git-lnk] | [![pyds-hub-img]][pyds-hub-lnk] | Python | Python docstyle checker | | [pylint][pylint-git-lnk] | [![pylint-hub-img]][pylint-hub-lnk] | Python | Python source code, bug and quality checker | | [terraform-docs][tfdocs-git-lnk] | [![tfdocs-hub-img]][tfdocs-hub-lnk] | Terraform | Terraform doc generator (TF 0.12 ready) **[1]** | | [terragrunt][tg-git-lnk] | [![tg-hub-img]][tg-hub-lnk] | Terraform | Terragrunt and Terraform | @@ -338,6 +211,10 @@ linter below for reproducible local or remote CI tests: [flint-hub-img]: https://img.shields.io/docker/pulls/cytopia/file-lint.svg [flint-hub-lnk]: https://hub.docker.com/r/cytopia/file-lint +[linkcheck-git-lnk]: https://github.com/cytopia/docker-linkcheck +[linkcheck-hub-img]: https://img.shields.io/docker/pulls/cytopia/linkcheck.svg +[linkcheck-hub-lnk]: https://hub.docker.com/r/cytopia/linkcheck + [jlint-git-lnk]: https://github.com/cytopia/docker-jsonlint [jlint-hub-img]: https://img.shields.io/docker/pulls/cytopia/jsonlint.svg [jlint-hub-lnk]: https://hub.docker.com/r/cytopia/jsonlint @@ -350,6 +227,10 @@ linter below for reproducible local or remote CI tests: [alint-hub-img]: https://img.shields.io/docker/pulls/cytopia/ansible-lint.svg [alint-hub-lnk]: https://hub.docker.com/r/cytopia/ansible-lint +[kubeval-git-lnk]: https://github.com/cytopia/docker-kubeval +[kubeval-hub-img]: https://img.shields.io/docker/pulls/cytopia/kubeval.svg +[kubeval-hub-lnk]: https://hub.docker.com/r/cytopia/kubeval + [gfmt-git-lnk]: https://github.com/cytopia/docker-gofmt [gfmt-hub-img]: https://img.shields.io/docker/pulls/cytopia/gofmt.svg [gfmt-hub-lnk]: https://hub.docker.com/r/cytopia/gofmt @@ -386,14 +267,26 @@ linter below for reproducible local or remote CI tests: [pcsf-hub-img]: https://img.shields.io/docker/pulls/cytopia/php-cs-fixer.svg [pcsf-hub-lnk]: https://hub.docker.com/r/cytopia/php-cs-fixer +[bandit-git-lnk]: https://github.com/cytopia/docker-bandit +[bandit-hub-img]: https://img.shields.io/docker/pulls/cytopia/bandit.svg +[bandit-hub-lnk]: https://hub.docker.com/r/cytopia/bandit + [black-git-lnk]: https://github.com/cytopia/docker-black [black-hub-img]: https://img.shields.io/docker/pulls/cytopia/black.svg [black-hub-lnk]: https://hub.docker.com/r/cytopia/black +[mypy-git-lnk]: https://github.com/cytopia/docker-mypy +[mypy-hub-img]: https://img.shields.io/docker/pulls/cytopia/mypy.svg +[mypy-hub-lnk]: https://hub.docker.com/r/cytopia/mypy + [pycs-git-lnk]: https://github.com/cytopia/docker-pycodestyle [pycs-hub-img]: https://img.shields.io/docker/pulls/cytopia/pycodestyle.svg [pycs-hub-lnk]: https://hub.docker.com/r/cytopia/pycodestyle +[pyds-git-lnk]: https://github.com/cytopia/docker-pydocstyle +[pyds-hub-img]: https://img.shields.io/docker/pulls/cytopia/pydocstyle.svg +[pyds-hub-lnk]: https://hub.docker.com/r/cytopia/pydocstyle + [pylint-git-lnk]: https://github.com/cytopia/docker-pylint [pylint-hub-img]: https://img.shields.io/docker/pulls/cytopia/pylint.svg [pylint-hub-lnk]: https://hub.docker.com/r/cytopia/pylint @@ -425,7 +318,8 @@ Visit **[cytopia/makefiles](https://github.com/cytopia/makefiles)** for dependen The provided Makefiles will only require GNU Make and Docker itself removing the need to install anything else. -## License +## :page_facing_up: License + **[MIT License](LICENSE)**