From f27ed76bbad625b1b4fc3c15e6f77b144795d155 Mon Sep 17 00:00:00 2001 From: "Santiago M. Mola" Date: Fri, 16 Oct 2020 14:08:37 +0200 Subject: [PATCH] Add GitHub Actions CI Builds and pushes all images when their source changed. --- .ci/changed-images | 39 +++++++++++++++++++++++++ .ci/git-changed | 52 ++++++++++++++++++++++++++++++++++ .ci/tags-to-json | 23 +++++++++++++++ .github/workflows/ci.yml | 61 +++++++++++++++++++++++++++++++++++++++- clang-format/tags | 2 ++ 5 files changed, 176 insertions(+), 1 deletion(-) create mode 100755 .ci/changed-images create mode 100755 .ci/git-changed create mode 100755 .ci/tags-to-json create mode 100644 clang-format/tags diff --git a/.ci/changed-images b/.ci/changed-images new file mode 100755 index 0000000..8370e46 --- /dev/null +++ b/.ci/changed-images @@ -0,0 +1,39 @@ +#!/bin/bash +set -euo pipefail + +PATH=".ci:$PATH" + +syntax=plain +if [[ "${1:-}" = "--matrix" ]]; then + syntax=matrix +fi + +images=() +for image in * ;do + if [[ ! -d "${image}" ]]; then + continue + fi + if ! git-changed "$image" &> /dev/null; then + continue + fi + images+=("$image") +done + +if [[ "$syntax" = plain ]]; then + for image in "${images[@]}"; do + echo "$image" + done +elif [[ "$syntax" = matrix ]]; then + output='{"image":[' + first=true + for image in "${images[@]}"; do + if [[ "$first" = true ]]; then + first=false + else + output="$output," + fi + output="$output"'"'"$image"'"' + done + output="$output]}" + echo -n "$output" +fi diff --git a/.ci/git-changed b/.ci/git-changed new file mode 100755 index 0000000..b5a30af --- /dev/null +++ b/.ci/git-changed @@ -0,0 +1,52 @@ +#!/bin/bash +set -euo pipefail + +path="${1:-$(pwd)}" +old_ref="origin/master" +new_ref="HEAD" + +if [[ "$(git rev-parse "$old_ref")" = "$(git rev-parse "$new_ref")" ]]; then + old_ref="HEAD~1" +fi + +excluded_patterns=( + '.*/README.md$' +) + +is_excluded() { + local path="$1" + for excl in "${excluded_patterns[@]}"; do + if [[ "${path}" =~ ${excl} ]]; then + return 1 + fi + done + return 0 +} + +filter_excluded() { + while read line; do + if ! is_excluded "$line"; then + echo "$line" + fi + done +} + +git_changed_files() { + local old="$1" + local new="$2" + local path="$3" + git diff --name-only "$old..$new" -- "$path" +} + +mapfile -t changed_files < <(git_changed_files "$old_ref" "$new_ref" "$path" | filter_excluded) + +if [[ ${#changed_files[@]} == 0 ]]; then + echo "Nothing changed." + exit 1 +else + echo "Changes:" + for file in "${changed_files[@]}"; do + echo " $file" + done + exit 0 +fi diff --git a/.ci/tags-to-json b/.ci/tags-to-json new file mode 100755 index 0000000..0cb80d3 --- /dev/null +++ b/.ci/tags-to-json @@ -0,0 +1,23 @@ +#!/bin/bash +set -euo pipefail + +path="$1" +tags_path="$path/tags" + +if [[ ! -f "$tags_path" ]]; then + echo "$tags_path does not exist" + exit 1 +fi + +output='"' +first=true +for tag in $(<"$tags_path"); do + if [[ "$first" = true ]]; then + first=false + output="$output$tag" + else + output="$output\n$tag" + fi +done +output="$output"'"' +echo -n "$output" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 43f9768..ee8a931 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,7 +6,66 @@ on: - staging pull_request: {} jobs: + set-matrix: + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.set-matrix.outputs.matrix }} + steps: + - uses: actions/checkout@v2 + - run: '.ci/changed-images' + - id: set-matrix + run: 'echo "::set-output name=matrix::$(.ci/changed-images --matrix)"' build: + if: github.ref != 'refs/heads/master' + needs: set-matrix + runs-on: ubuntu-latest + strategy: + matrix: ${{fromJson(needs.set-matrix.outputs.matrix)}} + fail-fast: false + steps: + - uses: actions/checkout@v2 + - id: set-tags + run: 'echo "::set-output name=tags::$(.ci/tags-to-json "${{ matrix.image }}")"' + - uses: docker/setup-buildx-action@v1 + id: buildx + with: + version: latest + install: true + id: docker_build + - uses: docker/build-push-action@v2 + id: docker_build + with: + push: false + tags: ${{ steps.set-tags.outputs.tags }} + context: ${{ matrix.image }} + - name: Image digest + run: echo ${{ steps.docker_build.outputs.digest }} + build-and-push: + if: github.ref == 'refs/heads/master' + needs: set-matrix runs-on: ubuntu-latest + strategy: + matrix: ${{fromJson(needs.set-matrix.outputs.matrix)}} + fail-fast: false steps: - - run: echo "hello world" + - uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - uses: actions/checkout@v2 + - id: set-tags + run: 'echo "::set-output name=tags::$(.ci/tags-to-json "${{ matrix.image }}")"' + - uses: docker/setup-buildx-action@v1 + id: buildx + with: + version: latest + install: true + id: docker_build + - uses: docker/build-push-action@v2 + id: docker_build + with: + push: true + tags: ${{ steps.set-tags.outputs.tags }} + context: ${{ matrix.image }} + - name: Image digest + run: echo ${{ steps.docker_build.outputs.digest }} diff --git a/clang-format/tags b/clang-format/tags new file mode 100644 index 0000000..e25608b --- /dev/null +++ b/clang-format/tags @@ -0,0 +1,2 @@ +hdivsecurity/clang-format:latest +hdivsecurity/clang-format:10