From 28a225271a122ebb44a82065458a12dee41d7181 Mon Sep 17 00:00:00 2001 From: cytopia Date: Sat, 27 Mar 2021 12:51:32 +0100 Subject: [PATCH 1/2] Initial commit --- Dockerfile | 40 +++++++++++ LICENSE | 21 ++++++ Makefile | 128 ++++++++++++++++++++++++++++++++++++ tests/configmap.yml | 12 ++++ tests/deployment-dvwa.yml | 87 ++++++++++++++++++++++++ tests/deployment-mysql.yml | 66 +++++++++++++++++++ tests/secret.yml | 11 ++++ tests/service-dvwa.yml | 16 +++++ tests/service-mysql.yml | 13 ++++ tests/volumeclaim-mysql.yml | 11 ++++ 10 files changed, 405 insertions(+) create mode 100644 Dockerfile create mode 100644 LICENSE create mode 100644 Makefile create mode 100644 tests/configmap.yml create mode 100644 tests/deployment-dvwa.yml create mode 100644 tests/deployment-mysql.yml create mode 100644 tests/secret.yml create mode 100644 tests/service-dvwa.yml create mode 100644 tests/service-mysql.yml create mode 100644 tests/volumeclaim-mysql.yml diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..43bef80 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,40 @@ +FROM alpine:3.13 as builder + +RUN set -x \ + && apk add --no-cache \ + wget + +ARG VERSION +RUN set -x \ + && if [ "${VERSION}" = "latest" ]; then \ + wget "https://github.com/instrumenta/kubeval/releases/latest/download/kubeval-linux-amd64.tar.gz"; \ + else \ + wget "https://github.com/instrumenta/kubeval/releases/download/${VERSION}/kubeval-darwin-amd64.tar.gz"; \ + fi \ + && tar xf kubeval-linux-amd64.tar.gz \ + && cp kubeval /usr/bin/kubeval \ + && chmod +x /usr/bin/kubeval \ + && kubeval --version + + +FROM alpine:3.13 as production +ARG VERSION +# https://github.com/opencontainers/image-spec/blob/master/annotations.md +#LABEL "org.opencontainers.image.created"="" +#LABEL "org.opencontainers.image.version"="" +#LABEL "org.opencontainers.image.revision"="" +LABEL "maintainer"="cytopia " +LABEL "org.opencontainers.image.authors"="cytopia " +LABEL "org.opencontainers.image.vendor"="cytopia" +LABEL "org.opencontainers.image.licenses"="MIT" +LABEL "org.opencontainers.image.url"="https://github.com/cytopia/docker-kubeval" +LABEL "org.opencontainers.image.documentation"="https://github.com/cytopia/docker-kubeval" +LABEL "org.opencontainers.image.source"="https://github.com/cytopia/docker-kubeval" +LABEL "org.opencontainers.image.ref.name"="kubeval ${VERSION}" +LABEL "org.opencontainers.image.title"="kubeval ${VERSION}" +LABEL "org.opencontainers.image.description"="kubeval ${VERSION}" + +COPY --from=builder /usr/bin/kubeval /usr/bin/kubeval +WORKDIR /data +ENTRYPOINT ["kubeval"] +CMD ["--version"] diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..c8a6e85 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 cytopia + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..6ac8626 --- /dev/null +++ b/Makefile @@ -0,0 +1,128 @@ +ifneq (,) +.error This Makefile requires GNU Make. +endif + +.PHONY: lint build rebuild test tag login push pull-base-image enter + +CURRENT_DIR = $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) + +DIR = . +FILE = Dockerfile +IMAGE = cytopia/kubeval +VERSION = latest +TAG = latest +NO_CACHE = + + +# -------------------------------------------------------------------------------------------------- +# Default Target +# -------------------------------------------------------------------------------------------------- +help: + @echo "lint Lint project files and repository" + @echo "build [VERSION=...] Build bandit docker image" + @echo "rebuild [VERSION=...] Build bandit docker image without cache" + @echo "test [VERSION=...] Test built bandit docker image" + @echo "tag TAG=... Retag Docker image" + @echo "login USER=... PASS=... Login to Docker hub" + @echo "push [TAG=...] Push Docker image to Docker hub" + + +# -------------------------------------------------------------------------------------------------- +# Lint Targets +# -------------------------------------------------------------------------------------------------- +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 . + + +# -------------------------------------------------------------------------------------------------- +# Build Targets +# -------------------------------------------------------------------------------------------------- +build: + docker build $(NO_CACHE) \ + --build-arg VERSION=$(VERSION) \ + --label "org.opencontainers.image.created"="$$(date --rfc-3339=s)" \ + --label "org.opencontainers.image.revision"="$$(git rev-parse HEAD)" \ + --label "org.opencontainers.image.version"="${VERSION}" \ + -t $(IMAGE) \ + -f $(DIR)/$(FILE) $(DIR) + +rebuild: pull-base-image +rebuild: NO_CACHE=--no-cache +rebuild: build + + +# -------------------------------------------------------------------------------------------------- +# Test Targets +# -------------------------------------------------------------------------------------------------- +test: + @$(MAKE) --no-print-directory _test-version + @$(MAKE) --no-print-directory _test-run + +_test-version: + @echo "------------------------------------------------------------" + @echo "- Testing correct version" + @echo "------------------------------------------------------------" + @if [ "$(VERSION)" = "latest" ]; then \ + echo "Fetching latest version from GitHub"; \ + LATEST="$$( \ + curl -L -sS https://github.com/instrumenta/kubeval/releases/ \ + | tac | tac \ + | grep -Eo "instrumenta/kubeval/releases/tag/[.0-9]+" \ + | sed 's/.*tag\///g' \ + | sort -V \ + | tail -1 \ + | grep -Eo '[.0-9]+' \ + )"; \ + echo "Testing for latest: $${LATEST}"; \ + if ! docker run --rm $(IMAGE) --version | grep -E "$${LATEST}$$"; then \ + echo "Failed"; \ + exit 1; \ + fi; \ + else \ + echo "Testing for tag: $(VERSION)"; \ + if ! docker run --rm $(IMAGE) --version | grep -E "^$(VERSION)"; then \ + echo "Failed"; \ + exit 1; \ + fi; \ + fi; \ + echo "Success"; \ + +_test-run: + @echo "------------------------------------------------------------" + @echo "- Testing k8s files" + @echo "------------------------------------------------------------" + @if ! docker run --rm -v $(CURRENT_DIR):/data $(IMAGE) tests/*.yml ; then \ + echo "Failed"; \ + exit 1; \ + fi; \ + echo "Success"; + + +# ------------------------------------------------------------------------------------------------- +# Deploy Targets +# ------------------------------------------------------------------------------------------------- +tag: + docker tag $(IMAGE) $(IMAGE):$(TAG) + +login: + @yes | docker login --username $(USER) --password $(PASS) + +push: + docker push $(IMAGE):$(TAG) + + +# ------------------------------------------------------------------------------------------------- +# Helper Targets +# ------------------------------------------------------------------------------------------------- +pull-base-image: + @grep -E '^\s*FROM' Dockerfile \ + | sed -e 's/^FROM//g' -e 's/[[:space:]]*as[[:space:]]*.*$$//g' \ + | xargs -n1 docker pull; + +enter: + docker run --rm --name $(subst /,-,$(IMAGE)) -it --entrypoint=/bin/sh $(ARG) $(IMAGE):$(TAG) diff --git a/tests/configmap.yml b/tests/configmap.yml new file mode 100644 index 0000000..f85c98c --- /dev/null +++ b/tests/configmap.yml @@ -0,0 +1,12 @@ +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: dvwa-config +data: + RECAPTCHA_PRIV_KEY: "" + RECAPTCHA_PUB_KEY: "" + SECURITY_LEVEL: "low" + PHPIDS_ENABLED: "0" + PHPIDS_VERBOSE: "1" + PHP_DISPLAY_ERRORS: "1" diff --git a/tests/deployment-dvwa.yml b/tests/deployment-dvwa.yml new file mode 100644 index 0000000..1132021 --- /dev/null +++ b/tests/deployment-dvwa.yml @@ -0,0 +1,87 @@ +--- +apiVersion: apps/v1 +kind: Deployment + + +### +### Deployment Metadata +### +metadata: + name: dvwa-web + + +### +### Specs +### +spec: + replicas: 1 + + selector: + matchLabels: + app: dvwa-web + tier: frontend + + template: + + # Template Metadata to be used by service for discovery + metadata: + labels: + app: dvwa-web + tier: frontend + + # Container/Volume definition + spec: + containers: + - name: dvwa + image: cytopia/dvwa:php-7.2 + ports: + - containerPort: 80 + env: + - name: RECAPTCHA_PRIV_KEY + valueFrom: + configMapKeyRef: + name: dvwa-config + key: RECAPTCHA_PRIV_KEY + - name: RECAPTCHA_PUB_KEY + valueFrom: + configMapKeyRef: + name: dvwa-config + key: RECAPTCHA_PUB_KEY + - name: SECURITY_LEVEL + valueFrom: + configMapKeyRef: + name: dvwa-config + key: SECURITY_LEVEL + - name: PHPIDS_ENABLED + valueFrom: + configMapKeyRef: + name: dvwa-config + key: PHPIDS_ENABLED + - name: PHPIDS_VERBOSE + valueFrom: + configMapKeyRef: + name: dvwa-config + key: PHPIDS_VERBOSE + - name: PHP_DISPLAY_ERRORS + valueFrom: + configMapKeyRef: + name: dvwa-config + key: PHP_DISPLAY_ERRORS + + - name: MYSQL_HOSTNAME + value: dvwa-mysql-service + - name: MYSQL_DATABASE + valueFrom: + secretKeyRef: + name: dvwa-secrets + key: DVWA_DATABASE + - name: MYSQL_USERNAME + valueFrom: + secretKeyRef: + name: dvwa-secrets + key: DVWA_USERNAME + - name: MYSQL_PASSWORD + valueFrom: + secretKeyRef: + name: dvwa-secrets + key: DVWA_PASSWORD diff --git a/tests/deployment-mysql.yml b/tests/deployment-mysql.yml new file mode 100644 index 0000000..876d714 --- /dev/null +++ b/tests/deployment-mysql.yml @@ -0,0 +1,66 @@ +--- +apiVersion: apps/v1 +kind: Deployment + + +### +### Deployment Metadata +### +metadata: + name: dvwa-mysql + + +### +### Specs +### +spec: + replicas: 1 + + selector: + matchLabels: + app: dvwa-mysql + tier: backend + + template: + + # Template Metadata to be used by service for discovery + metadata: + labels: + app: dvwa-mysql + tier: backend + + # Container/Volume definition + spec: + containers: + - name: mysql + image: mariadb:10.4 + ports: + - containerPort: 3306 + volumeMounts: + - name: dvwa-mysql-vol + mountPath: /var/lib/mysql + env: + - name: MYSQL_ROOT_PASSWORD + valueFrom: + secretKeyRef: + name: dvwa-secrets + key: ROOT_PASSWORD + - name: MYSQL_USER + valueFrom: + secretKeyRef: + name: dvwa-secrets + key: DVWA_USERNAME + - name: MYSQL_PASSWORD + valueFrom: + secretKeyRef: + name: dvwa-secrets + key: DVWA_PASSWORD + - name: MYSQL_DATABASE + valueFrom: + secretKeyRef: + name: dvwa-secrets + key: DVWA_DATABASE + volumes: + - name: dvwa-mysql-vol + persistentVolumeClaim: + claimName: dvwa-mysql-data-claim diff --git a/tests/secret.yml b/tests/secret.yml new file mode 100644 index 0000000..0f0e54b --- /dev/null +++ b/tests/secret.yml @@ -0,0 +1,11 @@ +--- +apiVersion: v1 +kind: Secret +metadata: + name: dvwa-secrets +type: Opaque +data: + ROOT_PASSWORD: czNyMDB0cGE1NQ== + DVWA_USERNAME: ZHZ3YQ== + DVWA_PASSWORD: cEBzc3dvcmQ= + DVWA_DATABASE: ZHZ3YQ== diff --git a/tests/service-dvwa.yml b/tests/service-dvwa.yml new file mode 100644 index 0000000..27437f4 --- /dev/null +++ b/tests/service-dvwa.yml @@ -0,0 +1,16 @@ +--- +apiVersion: v1 +kind: Service +metadata: + name: dvwa-web-service +spec: + selector: + app: dvwa-web + tier: frontend + type: LoadBalancer + ports: + - protocol: TCP + # Port accessible inside cluster + port: 8081 + # Port to forward to inside the pod + targetPort: 80 diff --git a/tests/service-mysql.yml b/tests/service-mysql.yml new file mode 100644 index 0000000..330c9f3 --- /dev/null +++ b/tests/service-mysql.yml @@ -0,0 +1,13 @@ +--- +apiVersion: v1 +kind: Service +metadata: + name: dvwa-mysql-service +spec: + selector: + app: dvwa-mysql + tier: backend + ports: + - protocol: TCP + port: 3306 + targetPort: 3306 diff --git a/tests/volumeclaim-mysql.yml b/tests/volumeclaim-mysql.yml new file mode 100644 index 0000000..5cce22d --- /dev/null +++ b/tests/volumeclaim-mysql.yml @@ -0,0 +1,11 @@ +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: dvwa-mysql-data-claim +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi From b82517c742cd2ec92ce59964f36d3ec998a3a2d5 Mon Sep 17 00:00:00 2001 From: cytopia Date: Sat, 27 Mar 2021 12:52:26 +0100 Subject: [PATCH 2/2] Add GitHub Actions --- .github/workflows/build.yml | 166 +++++++++++++++++++++++++++++++++ .github/workflows/lint.yml | 40 ++++++++ .github/workflows/nightly.yml | 169 ++++++++++++++++++++++++++++++++++ 3 files changed, 375 insertions(+) create mode 100644 .github/workflows/build.yml create mode 100644 .github/workflows/lint.yml create mode 100644 .github/workflows/nightly.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..47a6366 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,166 @@ +--- + +# ------------------------------------------------------------------------------------------------- +# Job Name +# ------------------------------------------------------------------------------------------------- +name: build + + +# ------------------------------------------------------------------------------------------------- +# When to run +# ------------------------------------------------------------------------------------------------- +on: + # Runs on Pull Requests + pull_request: + # Runs on Push + push: + + +# ------------------------------------------------------------------------------------------------- +# What to run +# ------------------------------------------------------------------------------------------------- +jobs: + build: + name: "[ ${{ matrix.version }} ]" + runs-on: ubuntu-latest + strategy: + fail-fast: False + matrix: + version: + - 'latest' + steps: + + # ------------------------------------------------------------ + # Checkout repository + # ------------------------------------------------------------ + - name: Checkout repository + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Set variables + id: vars + run: | + # Retrieve git info (tags, etc) + git fetch --all + + # Branch, Tag or Commit + GIT_TYPE="$( \ + curl -sS https://raw.githubusercontent.com/cytopia/git-tools/master/git-info.sh \ + | sh \ + | grep '^GIT_TYPE' \ + | sed 's|.*=||g' \ + )" + # Branch name, Tag name or Commit Hash + GIT_SLUG="$( \ + curl -sS https://raw.githubusercontent.com/cytopia/git-tools/master/git-info.sh \ + | sh \ + | grep '^GIT_NAME' \ + | sed 's|.*=||g' \ + )" + # Docker Tag + if [ "${GIT_TYPE}" = "BRANCH" ] && [ "${GIT_SLUG}" = "master" ]; then + DOCKER_TAG="${VERSION}" + else + DOCKER_TAG="${VERSION}-${GIT_SLUG}" + fi + + # Output + echo "GIT_TYPE=${GIT_TYPE}" + echo "GIT_SLUG=${GIT_SLUG}" + echo "DOCKER_TAG=${DOCKER_TAG}" + + # Export variable + # https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-commands-for-github-actions#environment-files + echo "GIT_TYPE=${GIT_TYPE}" >> ${GITHUB_ENV} + echo "GIT_SLUG=${GIT_SLUG}" >> ${GITHUB_ENV} + echo "DOCKER_TAG=${DOCKER_TAG}" >> ${GITHUB_ENV} + env: + VERSION: ${{ matrix.version }} + + + # ------------------------------------------------------------ + # Build + # ------------------------------------------------------------ + - name: Build + run: | + retry() { + for n in $(seq ${RETRIES}); do + echo "[${n}/${RETRIES}] ${*}"; + if eval "${*}"; then + echo "[SUCC] ${n}/${RETRIES}"; + return 0; + fi; + sleep 2; + echo "[FAIL] ${n}/${RETRIES}"; + done; + return 1; + } + retry make build VERSION=${VERSION} + env: + VERSION: ${{ matrix.version }} + RETRIES: 20 + + - name: Test + run: | + retry() { + for n in $(seq ${RETRIES}); do + echo "[${n}/${RETRIES}] ${*}"; + if eval "${*}"; then + echo "[SUCC] ${n}/${RETRIES}"; + return 0; + fi; + sleep 2; + echo "[FAIL] ${n}/${RETRIES}"; + done; + return 1; + } + retry make test VERSION=${VERSION} + git diff --quiet || { echo "Build Changes"; git diff; git status; false; } + env: + VERSION: ${{ matrix.version }} + RETRIES: 20 + + + # ------------------------------------------------------------ + # Deploy + # ------------------------------------------------------------ + - name: Publish images (only repo owner) + run: | + retry() { + for n in $(seq ${RETRIES}); do + echo "[${n}/${RETRIES}] ${*}"; + if eval "${*}"; then + echo "[SUCC] ${n}/${RETRIES}"; + return 0; + fi; + sleep ${PAUSE}; + echo "[FAIL] ${n}/${RETRIES}"; + done; + return 1; + } + + # Output + echo "GIT_TYPE=${GIT_TYPE}" + echo "GIT_SLUG=${GIT_SLUG}" + echo "DOCKER_TAG=${DOCKER_TAG}" + + # Tag image + retry make tag TAG=${DOCKER_TAG} + docker images + + # Login and Push + retry make login USER=${{ secrets.DOCKERHUB_USERNAME }} PASS=${{ secrets.DOCKERHUB_PASSWORD }} + retry make push TAG=${DOCKER_TAG} + env: + RETRIES: 20 + PAUSE: 10 + # https://help.github.com/en/github/automating-your-workflow-with-github-actions/contexts-and-expression-syntax-for-github-actions#functions + if: github.event.pull_request.base.repo.id == github.event.pull_request.head.repo.id + && ( + (github.event_name == 'schedule' && (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/'))) + || + (github.event_name == 'push' && (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/'))) + || + (github.event_name == 'push' && startsWith(github.ref, 'refs/heads/release-')) + ) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..ae19b94 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,40 @@ +--- + +# ------------------------------------------------------------------------------------------------- +# Job Name +# ------------------------------------------------------------------------------------------------- +name: lint + + +# ------------------------------------------------------------------------------------------------- +# When to run +# ------------------------------------------------------------------------------------------------- +on: + # Runs on Pull Requests + pull_request: + + +# ------------------------------------------------------------------------------------------------- +# What to run +# ------------------------------------------------------------------------------------------------- +jobs: + lint: + name: "Lint" + runs-on: ubuntu-latest + steps: + # ------------------------------------------------------------ + # Setup repository + # ------------------------------------------------------------ + - name: Checkout repository + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + # ------------------------------------------------------------ + # Lint repository + # ------------------------------------------------------------ + - name: Lint + id: vars + run: | + make lint + diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml new file mode 100644 index 0000000..0e55717 --- /dev/null +++ b/.github/workflows/nightly.yml @@ -0,0 +1,169 @@ +--- + +# ------------------------------------------------------------------------------------------------- +# Job Name +# ------------------------------------------------------------------------------------------------- +name: nightly + + +# ------------------------------------------------------------------------------------------------- +# When to run +# ------------------------------------------------------------------------------------------------- +on: + # Runs daily + schedule: + - cron: '0 0 * * *' + + +# ------------------------------------------------------------------------------------------------- +# What to run +# ------------------------------------------------------------------------------------------------- +jobs: + nightly: + name: "[ ${{ matrix.version }} ] (ref: ${{ matrix.refs }})" + runs-on: ubuntu-latest + strategy: + fail-fast: False + matrix: + version: + - 'latest' + refs: + - 'master' + - '0.3' + steps: + + # ------------------------------------------------------------ + # Checkout repository + # ------------------------------------------------------------ + - name: Checkout repository + uses: actions/checkout@v2 + with: + fetch-depth: 0 + ref: ${{ matrix.refs }} + + - name: Set variables + id: vars + run: | + # Retrieve git info (tags, etc) + git fetch --all + + # Branch, Tag or Commit + GIT_TYPE="$( \ + curl -sS https://raw.githubusercontent.com/cytopia/git-tools/master/git-info.sh \ + | sh \ + | grep '^GIT_TYPE' \ + | sed 's|.*=||g' \ + )" + # Branch name, Tag name or Commit Hash + GIT_SLUG="$( \ + curl -sS https://raw.githubusercontent.com/cytopia/git-tools/master/git-info.sh \ + | sh \ + | grep '^GIT_NAME' \ + | sed 's|.*=||g' \ + )" + # Docker Tag + if [ "${GIT_TYPE}" = "BRANCH" ] && [ "${GIT_SLUG}" = "master" ]; then + DOCKER_TAG="${VERSION}" + else + DOCKER_TAG="${VERSION}-${GIT_SLUG}" + fi + + # Output + echo "GIT_TYPE=${GIT_TYPE}" + echo "GIT_SLUG=${GIT_SLUG}" + echo "DOCKER_TAG=${DOCKER_TAG}" + + # Export variable + # https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-commands-for-github-actions#environment-files + echo "GIT_TYPE=${GIT_TYPE}" >> ${GITHUB_ENV} + echo "GIT_SLUG=${GIT_SLUG}" >> ${GITHUB_ENV} + echo "DOCKER_TAG=${DOCKER_TAG}" >> ${GITHUB_ENV} + env: + VERSION: ${{ matrix.version }} + + + # ------------------------------------------------------------ + # Build + # ------------------------------------------------------------ + - name: Build + run: | + retry() { + for n in $(seq ${RETRIES}); do + echo "[${n}/${RETRIES}] ${*}"; + if eval "${*}"; then + echo "[SUCC] ${n}/${RETRIES}"; + return 0; + fi; + sleep 2; + echo "[FAIL] ${n}/${RETRIES}"; + done; + return 1; + } + retry make build VERSION=${VERSION} + env: + VERSION: ${{ matrix.version }} + RETRIES: 20 + + - name: Test + run: | + retry() { + for n in $(seq ${RETRIES}); do + echo "[${n}/${RETRIES}] ${*}"; + if eval "${*}"; then + echo "[SUCC] ${n}/${RETRIES}"; + return 0; + fi; + sleep 2; + echo "[FAIL] ${n}/${RETRIES}"; + done; + return 1; + } + retry make test VERSION=${VERSION} + git diff --quiet || { echo "Build Changes"; git diff; git status; false; } + env: + VERSION: ${{ matrix.version }} + RETRIES: 20 + + + # ------------------------------------------------------------ + # Deploy + # ------------------------------------------------------------ + - name: Publish images (only repo owner) + run: | + retry() { + for n in $(seq ${RETRIES}); do + echo "[${n}/${RETRIES}] ${*}"; + if eval "${*}"; then + echo "[SUCC] ${n}/${RETRIES}"; + return 0; + fi; + sleep ${PAUSE}; + echo "[FAIL] ${n}/${RETRIES}"; + done; + return 1; + } + + # Output + echo "GIT_TYPE=${GIT_TYPE}" + echo "GIT_SLUG=${GIT_SLUG}" + echo "DOCKER_TAG=${DOCKER_TAG}" + + # Tag image + retry make tag TAG=${DOCKER_TAG} + docker images + + # Login and Push + retry make login USER=${{ secrets.DOCKERHUB_USERNAME }} PASS=${{ secrets.DOCKERHUB_PASSWORD }} + retry make push TAG=${DOCKER_TAG} + env: + RETRIES: 20 + PAUSE: 10 + # https://help.github.com/en/github/automating-your-workflow-with-github-actions/contexts-and-expression-syntax-for-github-actions#functions + if: github.event.pull_request.base.repo.id == github.event.pull_request.head.repo.id + && ( + (github.event_name == 'schedule' && (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/'))) + || + (github.event_name == 'push' && (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/'))) + || + (github.event_name == 'push' && startsWith(github.ref, 'refs/heads/release-')) + )