From 36c966a847ba591d8ebd3411419aac2a52508668 Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Thu, 12 Dec 2024 07:48:12 +0100 Subject: [PATCH 1/9] Run test pipeline also on Windows and macOS. --- .github/workflows/ArtifactsUpload.yml | 178 ++++++++++++++------------ action.yml | 32 ++--- 2 files changed, 112 insertions(+), 98 deletions(-) diff --git a/.github/workflows/ArtifactsUpload.yml b/.github/workflows/ArtifactsUpload.yml index febdd6d..6dfe3e8 100644 --- a/.github/workflows/ArtifactsUpload.yml +++ b/.github/workflows/ArtifactsUpload.yml @@ -22,8 +22,15 @@ on: jobs: Build-1: - name: Build 1 - Upload artifact - runs-on: ubuntu-24.04 + name: ${{ matrix.os.icon }} Build 1 on ${{ matrix.os.name }} - Upload artifact + runs-on: ${{ matrix.os.image }} + strategy: + fail-fast: false + matrix: + os: + - {'icon': '🐧', 'name': 'Ubuntu', 'image': 'ubuntu-24.04'} + - {'icon': '🍏', 'name': 'macOS', 'image': 'macos-14' } + - {'icon': 'πŸͺŸ', 'name': 'Windows', 'image': 'windows-2022'} steps: - name: πŸ–‰ Build 1 @@ -31,19 +38,19 @@ jobs: echo "Document 1 $(date --utc '+%d.%m.%Y - %H:%M:%S')" > document1.txt echo "Analysis log $(date --utc '+%d.%m.%Y - %H:%M:%S')" > analysis.log echo "Build log $(date --utc '+%d.%m.%Y - %H:%M:%S')" > build.log - + mkdir -p bin echo "Program $(date --utc '+%d.%m.%Y - %H:%M:%S')" > bin/program.py chmod u+x bin/program.py echo "Tool $(date --utc '+%d.%m.%Y - %H:%M:%S')" > bin/tool.py chmod g+x bin/tool.py - + mkdir -p lib echo "Library 1 $(date --utc '+%d.%m.%Y - %H:%M:%S')" > lib/common.py chmod +x lib/common.py echo "Library 2 $(date --utc '+%d.%m.%Y - %H:%M:%S')" > lib/shared.py chmod +x lib/shared.py - + mkdir -p lib/gui echo "Library 3 $(date --utc '+%d.%m.%Y - %H:%M:%S')" > lib/gui/main.py chmod +x lib/gui/main.py @@ -54,184 +61,191 @@ jobs: run: | tree . - - name: πŸ“€ Upload artifact 'github-release' + - name: πŸ“€ Upload artifact '${{ matrix.os.name }}-github-release' uses: pyTooling/upload-artifact@dev continue-on-error: true with: - name: github-release + name: ${{ matrix.os.name }}-github-release path: | document1.txt *.log bin/*.py lib/ - - name: πŸ“€ Upload artifact 'pyTooling-release' + - name: πŸ“€ Upload artifact '${{ matrix.os.name }}-pyTooling-release' uses: pyTooling/upload-artifact@dev continue-on-error: true with: - name: pyTooling-release + name: ${{ matrix.os.name }}-pyTooling-release path: | document1.txt *.log bin/*.py lib/ - - name: πŸ“€ Upload artifact 'pyTooling-lib' + - name: πŸ“€ Upload artifact '${{ matrix.os.name }}-pyTooling-lib' uses: pyTooling/upload-artifact@dev continue-on-error: true with: - name: pyTooling-lib + name: ${{ matrix.os.name }}-pyTooling-lib working-directory: lib path: | **/*.py - - name: πŸ“€ Upload artifact 'github-single-file' + - name: πŸ“€ Upload artifact '${{ matrix.os.name }}-github-single-file' uses: actions/upload-artifact@v4 continue-on-error: true with: - name: github-single-file + name: ${{ matrix.os.name }}-github-single-file path: | document1.txt - - name: πŸ“€ Upload artifact 'pyTooling-single-file' + - name: πŸ“€ Upload artifact '${{ matrix.os.name }}-pyTooling-single-file' uses: pyTooling/upload-artifact@dev continue-on-error: true with: - name: pyTooling-single-file + name: ${{ matrix.os.name }}-pyTooling-single-file path: | document1.txt - - name: πŸ“€ Upload artifact 'github-single-file-in-directory' + - name: πŸ“€ Upload artifact '${{ matrix.os.name }}-github-single-file-in-directory' uses: actions/upload-artifact@v4 continue-on-error: true with: - name: github-single-file-in-directory + name: ${{ matrix.os.name }}-github-single-file-in-directory path: | bin/program.py - - name: πŸ“€ Upload artifact 'pyTooling-single-file-in-directory' + - name: πŸ“€ Upload artifact '${{ matrix.os.name }}-pyTooling-single-file-in-directory' uses: pyTooling/upload-artifact@dev continue-on-error: true with: - name: pyTooling-single-file-in-directory + name: ${{ matrix.os.name }}-pyTooling-single-file-in-directory path: | bin/program.py - - name: πŸ“€ Upload artifact 'github-double-file-in-directory' + - name: πŸ“€ Upload artifact '${{ matrix.os.name }}-github-double-file-in-directory' uses: actions/upload-artifact@v4 continue-on-error: true with: - name: github-double-file-in-directory + name: ${{ matrix.os.name }}-github-double-file-in-directory path: | bin/program.py bin/tool.py - - name: πŸ“€ Upload artifact 'pyTooling-double-file-in-directory' + - name: πŸ“€ Upload artifact '${{ matrix.os.name }}-pyTooling-double-file-in-directory' uses: pyTooling/upload-artifact@dev continue-on-error: true with: - name: pyTooling-double-file-in-directory + name: ${{ matrix.os.name }}-pyTooling-double-file-in-directory path: | bin/program.py bin/tool.py - - name: πŸ“€ Upload artifact 'github-triple-file-in-directory' + - name: πŸ“€ Upload artifact '${{ matrix.os.name }}-github-triple-file-in-directory' uses: actions/upload-artifact@v4 continue-on-error: true with: - name: github-triple-file-in-directory + name: ${{ matrix.os.name }}-github-triple-file-in-directory path: | lib/common.py lib/gui/main.py lib/gui/dialog.py - - name: πŸ“€ Upload artifact 'pyTooling-triple-file-in-directory' + - name: πŸ“€ Upload artifact '${{ matrix.os.name }}-pyTooling-triple-file-in-directory' uses: pyTooling/upload-artifact@dev continue-on-error: true with: - name: pyTooling-triple-file-in-directory + name: ${{ matrix.os.name }}-pyTooling-triple-file-in-directory path: | lib/common.py lib/gui/main.py lib/gui/dialog.py - - name: πŸ“€ Upload artifact 'github-double-file-in-deep-directory' + - name: πŸ“€ Upload artifact '${{ matrix.os.name }}-github-double-file-in-deep-directory' uses: actions/upload-artifact@v4 continue-on-error: true with: - name: github-double-file-in-deep-directory + name: ${{ matrix.os.name }}-github-double-file-in-deep-directory path: | lib/gui/main.py lib/gui/dialog.py - - name: πŸ“€ Upload artifact 'pyTooling-double-file-in-deep-directory' + - name: πŸ“€ Upload artifact '${{ matrix.os.name }}-pyTooling-double-file-in-deep-directory' uses: pyTooling/upload-artifact@dev continue-on-error: true with: - name: pyTooling-double-file-in-deep-directory + name: ${{ matrix.os.name }}-pyTooling-double-file-in-deep-directory path: | lib/gui/main.py lib/gui/dialog.py - - name: πŸ“€ Upload artifact 'github-single-directory' + - name: πŸ“€ Upload artifact '${{ matrix.os.name }}-github-single-directory' uses: actions/upload-artifact@v4 continue-on-error: true with: - name: github-single-directory + name: ${{ matrix.os.name }}-github-single-directory path: | bin - - name: πŸ“€ Upload artifact 'pyTooling-single-directory' + - name: πŸ“€ Upload artifact '${{ matrix.os.name }}-pyTooling-single-directory' uses: pyTooling/upload-artifact@dev continue-on-error: true with: - name: pyTooling-single-directory + name: ${{ matrix.os.name }}-pyTooling-single-directory path: | bin - - name: πŸ“€ Upload artifact 'github-double-directory' + - name: πŸ“€ Upload artifact '${{ matrix.os.name }}-github-double-directory' uses: actions/upload-artifact@v4 continue-on-error: true with: - name: github-double-directory + name: ${{ matrix.os.name }}-github-double-directory path: | bin lib - - name: πŸ“€ Upload artifact 'pyTooling-double-directory' + - name: πŸ“€ Upload artifact '${{ matrix.os.name }}-pyTooling-double-directory' uses: pyTooling/upload-artifact@dev continue-on-error: true with: - name: pyTooling-double-directory + name: ${{ matrix.os.name }}-pyTooling-double-directory path: | bin lib - - name: πŸ“€ Upload artifact 'github-unpredictable-wildcard' + - name: πŸ“€ Upload artifact '${{ matrix.os.name }}-github-unpredictable-wildcard' uses: actions/upload-artifact@v4 continue-on-error: true with: - name: github-unpredictable-wildcard + name: ${{ matrix.os.name }}-github-unpredictable-wildcard path: | lib/gui/main.py lib/gui/dialog.py *.foo - - name: πŸ“€ Upload artifact 'pyTooling-unpredictable-wildcard' + - name: πŸ“€ Upload artifact '${{ matrix.os.name }}-pyTooling-unpredictable-wildcard' uses: pyTooling/upload-artifact@dev continue-on-error: true with: - name: pyTooling-unpredictable-wildcard + name: ${{ matrix.os.name }}-pyTooling-unpredictable-wildcard path: | lib/gui/main.py lib/gui/dialog.py *.foo Verify-0: - name: Verify artifact content - runs-on: ubuntu-24.04 + name: ${{ matrix.os.icon }} Verify artifact content on ${{ matrix.os.name }} + runs-on: ${{ matrix.os.image }} needs: - Build-1 + strategy: + fail-fast: false + matrix: + os: + - {'icon': '🐧', 'name': 'Ubuntu', 'image': 'ubuntu-24.04'} + - {'icon': '🍏', 'name': 'macOS', 'image': 'macos-14' } + - {'icon': 'πŸͺŸ', 'name': 'Windows', 'image': 'windows-2022'} steps: - name: πŸ“₯ Download artifact @@ -243,37 +257,37 @@ jobs: run: | set +e - ANSI_LIGHT_RED="\e[91m" - ANSI_LIGHT_GREEN="\e[92m" - ANSI_NOCOLOR="\e[0m" - + ANSI_LIGHT_RED="\x1b[91m" + ANSI_LIGHT_GREEN="\x1b[92m" + ANSI_NOCOLOR="\x1b[0m" + echo "List directory content" - ls -lAh . + ls -lAh . echo "----------------------------------------" - + echo -n "Does tarball exist ... " if [[ ! -f __pyTooling_upload_artifact__.tar ]]; then - echo -e "${ANSI_LIGHT_RED}[FAILED]${ANSI_NOCOLOR}" - echo -e "${ANSI_LIGHT_RED}Artifact doesn't contain a tar file named '__pyTooling_upload_artifact__.tar'.${ANSI_NOCOLOR}" + echo "${ANSI_LIGHT_RED}[FAILED]${ANSI_NOCOLOR}" + echo "${ANSI_LIGHT_RED}Artifact doesn't contain a tar file named '__pyTooling_upload_artifact__.tar'.${ANSI_NOCOLOR}" exit 1 else - echo -e "${ANSI_LIGHT_GREEN}[OK]${ANSI_NOCOLOR}" + echo "${ANSI_LIGHT_GREEN}[OK]${ANSI_NOCOLOR}" fi - name: πŸ“¦ Extract tarball run: | set +e - ANSI_LIGHT_RED="\e[91m" - ANSI_LIGHT_GREEN="\e[92m" - ANSI_NOCOLOR="\e[0m" - + ANSI_LIGHT_RED="\x1b[91m" + ANSI_LIGHT_GREEN="\x1b[92m" + ANSI_NOCOLOR="\x1b[0m" + echo -n "Extracting tarball ... " tar -xf __pyTooling_upload_artifact__.tar if [[ $? -ne 0 ]]; then - echo -e "${ANSI_LIGHT_RED}[FAILED]${ANSI_NOCOLOR}" + echo "${ANSI_LIGHT_RED}[FAILED]${ANSI_NOCOLOR}" else - echo -e "${ANSI_LIGHT_GREEN}[OK]${ANSI_NOCOLOR}" + echo "${ANSI_LIGHT_GREEN}[OK]${ANSI_NOCOLOR}" fi - name: πŸ”Ž Inspect extracted tarball @@ -284,9 +298,9 @@ jobs: run: | set +e - ANSI_LIGHT_RED="\e[91m" - ANSI_LIGHT_GREEN="\e[92m" - ANSI_NOCOLOR="\e[0m" + ANSI_LIGHT_RED="\x1b[91m" + ANSI_LIGHT_GREEN="\x1b[92m" + ANSI_NOCOLOR="\x1b[0m" expected=( "document1.txt" @@ -296,57 +310,57 @@ jobs: "lib/common.py" ) - errors=0 + errors=0 for file in "${expected[@]}"; do echo -n "Checking '${file}' ... " if [[ -f "$file" ]]; then - echo -e "${ANSI_LIGHT_GREEN}[PASSED]${ANSI_NOCOLOR}" + echo "${ANSI_LIGHT_GREEN}[PASSED]${ANSI_NOCOLOR}" else - echo -e "${ANSI_LIGHT_RED}[FAILED]${ANSI_NOCOLOR}" - echo -e "${ANSI_LIGHT_RED}Extracted artifact doesn't contain file '${file}'.${ANSI_NOCOLOR}" + echo "${ANSI_LIGHT_RED}[FAILED]${ANSI_NOCOLOR}" + echo "${ANSI_LIGHT_RED}Extracted artifact doesn't contain file '${file}'.${ANSI_NOCOLOR}" errors=$((errors + 1)) - fi + fi done - + echo "" if [[ $errors -ne 0 ]]; then - echo -e "${ANSI_LIGHT_RED}Counted ${errors} errors.${ANSI_NOCOLOR}" + echo "${ANSI_LIGHT_RED}Counted ${errors} errors.${ANSI_NOCOLOR}" exit 1 else - echo -e "${ANSI_LIGHT_GREEN}No errors found.${ANSI_NOCOLOR}" + echo "${ANSI_LIGHT_GREEN}No errors found.${ANSI_NOCOLOR}" fi - name: πŸ“‹ Verify file permissions run: | set +e - ANSI_LIGHT_RED="\e[91m" - ANSI_LIGHT_GREEN="\e[92m" - ANSI_NOCOLOR="\e[0m" + ANSI_LIGHT_RED="\x1b[91m" + ANSI_LIGHT_GREEN="\x1b[92m" + ANSI_NOCOLOR="\x1b[0m" expected=( "bin/program.py" "lib/common.py" ) - errors=0 + errors=0 for file in "${expected[@]}"; do echo -n "Checking '${file}' ... " if [[ -x "$file" ]]; then - echo -e "${ANSI_LIGHT_GREEN}[PASSED]${ANSI_NOCOLOR}" + echo "${ANSI_LIGHT_GREEN}[PASSED]${ANSI_NOCOLOR}" else - echo -e "${ANSI_LIGHT_RED}[FAILED]${ANSI_NOCOLOR}" - echo -e "${ANSI_LIGHT_RED}File '${file}' isn't executable.${ANSI_NOCOLOR}" + echo "${ANSI_LIGHT_RED}[FAILED]${ANSI_NOCOLOR}" + echo "${ANSI_LIGHT_RED}File '${file}' isn't executable.${ANSI_NOCOLOR}" errors=$((errors + 1)) - fi + fi done - + echo "" if [[ $errors -ne 0 ]]; then - echo -e "${ANSI_LIGHT_RED}Counted ${errors} errors.${ANSI_NOCOLOR}" + echo "${ANSI_LIGHT_RED}Counted ${errors} errors.${ANSI_NOCOLOR}" exit 1 else - echo -e "${ANSI_LIGHT_GREEN}No errors found.${ANSI_NOCOLOR}" + echo "${ANSI_LIGHT_GREEN}No errors found.${ANSI_NOCOLOR}" fi Inspect-1: diff --git a/action.yml b/action.yml index 8802e4a..0f14de7 100644 --- a/action.yml +++ b/action.yml @@ -106,20 +106,20 @@ runs: run: | set +e - ANSI_LIGHT_RED="\e[91m" - ANSI_LIGHT_GREEN="\e[92m" - ANSI_CYAN="\e[36m" - ANSI_NOCOLOR="\e[0m" + ANSI_LIGHT_RED="\x1b[91m" + ANSI_LIGHT_GREEN="\x1b[92m" + ANSI_CYAN="\x1b[36m" + ANSI_NOCOLOR="\x1b[0m" if [[ "${{ inputs.working-directory }}" != "" ]]; then echo -n "Changing artifact root directory to '${{ inputs.working-directory }}' ... " if [[ -d "${{ inputs.working-directory }}" ]]; then pushd "${{ inputs.working-directory }}" > /dev/null if [[ $? -ne 0 ]]; then - echo -e "${ANSI_LIGHT_RED}[FAILED]${ANSI_NOCOLOR}" + echo "${ANSI_LIGHT_RED}[FAILED]${ANSI_NOCOLOR}" exit 1 else - echo -e "${ANSI_LIGHT_GREEN}[OK]${ANSI_NOCOLOR}" + echo "${ANSI_LIGHT_GREEN}[OK]${ANSI_NOCOLOR}" dir="${{ inputs.working-directory }}" tarDirectory="" @@ -130,7 +130,7 @@ runs: echo " tarDirectory: ${tarDirectory}" fi else - echo -e "echo -e ${ANSI_LIGHT_RED}[NO DIRECTORY]${ANSI_NOCOLOR}" + echo "echo ${ANSI_LIGHT_RED}[NO DIRECTORY]${ANSI_NOCOLOR}" exit 1 fi else @@ -145,7 +145,7 @@ runs: PATTERNS+=("$pattern") done <<<'${{ inputs.path }}' - echo -e "${ANSI_LIGHT_GREEN}[DONE]${ANSI_NOCOLOR}" + echo "${ANSI_LIGHT_GREEN}[DONE]${ANSI_NOCOLOR}" print_files_unique() { for i in "$@"; do @@ -153,10 +153,10 @@ runs: done | sort | uniq } - echo -e "Checking tar ($(which tar)): ${ANSI_CYAN}$(tar --version | head -n 1)${ANSI_NOCOLOR}" + echo "Checking tar ($(which tar)): ${ANSI_CYAN}$(tar --version | head -n 1)${ANSI_NOCOLOR}" echo -n "Assemble OS specific tar command line options ... " if [[ "${{ runner.os }}" == "macOS" ]]; then - echo -e "${ANSI_Y}[macOS]${ANSI_NOCOLOR}" + echo "${ANSI_Y}[macOS]${ANSI_NOCOLOR}" # Options for BSD tar tarOptions=() @@ -164,7 +164,7 @@ runs: # Option to read filenames from file filesFrom=("-T") elif [[ "${{ runner.os }}" == "Linux" || "${{ runner.os }}" == "Windows" ]]; then - echo -e "${ANSI_LIGHT_GREEN}[${{ runner.os }}]${ANSI_NOCOLOR}" + echo "${ANSI_LIGHT_GREEN}[${{ runner.os }}]${ANSI_NOCOLOR}" # Options for GNU tar tarOptions=("--owner=0" "--group=0") @@ -172,14 +172,14 @@ runs: # Option to read filenames from file filesFrom=("--verbatim-files-from" "--files-from") else - echo -e "${ANSI_LIGHT_RED}[UNSUPPORTED]${ANSI_NOCOLOR}" + echo "${ANSI_LIGHT_RED}[UNSUPPORTED]${ANSI_NOCOLOR}" exit 1 fi echo -n "Creating temporary tarball '${tarDirectory}${{ inputs.tarball-name }}' ... " tar -cf "${tarDirectory}${{ inputs.tarball-name }}" "${tarOptions[@]}" "${filesFrom[@]}" <(print_files_unique "${PATTERNS[@]}") if [[ $? -ne 0 ]]; then - echo -e "${ANSI_LIGHT_RED}[FAILED]${ANSI_NOCOLOR}" + echo "${ANSI_LIGHT_RED}[FAILED]${ANSI_NOCOLOR}" exit 1 else echo -e "${ANSI_LIGHT_GREEN}[OK]${ANSI_NOCOLOR}" @@ -206,9 +206,9 @@ runs: run: | set +e - ANSI_LIGHT_RED="\e[91m" - ANSI_LIGHT_GREEN="\e[92m" - ANSI_NOCOLOR="\e[0m" + ANSI_LIGHT_RED="\x1b[91m" + ANSI_LIGHT_GREEN="\x1b[92m" + ANSI_NOCOLOR="\x1b[0m" echo -n "Removing temporary tarball ... " rm -f "${{ inputs.tarball-name }}" From dacdd33ffea32e50fdd5cb2047ad611a744850bd Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Thu, 12 Dec 2024 08:13:53 +0100 Subject: [PATCH 2/9] Use local actions to verify directory contents and file permissions. --- .../check-directory-content/action.yml | 41 +++++ .github/actions/file-is-executable/action.yml | 41 +++++ .github/workflows/ArtifactsUpload.yml | 162 +++++++----------- 3 files changed, 142 insertions(+), 102 deletions(-) create mode 100644 .github/actions/check-directory-content/action.yml create mode 100644 .github/actions/file-is-executable/action.yml diff --git a/.github/actions/check-directory-content/action.yml b/.github/actions/check-directory-content/action.yml new file mode 100644 index 0000000..039a795 --- /dev/null +++ b/.github/actions/check-directory-content/action.yml @@ -0,0 +1,41 @@ +name: Check-Directory-Content +description: Check if directory contains the listed files. +inputs: + files: + description: List of filenames. + type: string + +runs: + using: composite + steps: + - name: πŸ“‹ Verify extracted tarball content + shell: bash + run: | + set +e + + ANSI_LIGHT_RED="\x1b[91m" + ANSI_LIGHT_GREEN="\x1b[92m" + ANSI_NOCOLOR="\x1b[0m" + + errors=0 + while IFS=$'\r\n' read -r file; do + # skip empty or comment lines + [[ "${file}" == "" || "${file:0:1}" == "#" ]] && continue + + echo -n "Checking '${file}' ... " + if [[ -f "$file" ]]; then + echo "${ANSI_LIGHT_GREEN}[PASSED]${ANSI_NOCOLOR}" + else + echo "${ANSI_LIGHT_RED}[FAILED]${ANSI_NOCOLOR}" + echo "${ANSI_LIGHT_RED}Extracted artifact doesn't contain file '${file}'.${ANSI_NOCOLOR}" + errors=$((errors + 1)) + fi + done <<<'${{ inputs.files }}' + + echo "" + if [[ $errors -ne 0 ]]; then + echo "${ANSI_LIGHT_RED}Counted ${errors} errors.${ANSI_NOCOLOR}" + exit 1 + else + echo "${ANSI_LIGHT_GREEN}No errors found.${ANSI_NOCOLOR}" + fi diff --git a/.github/actions/file-is-executable/action.yml b/.github/actions/file-is-executable/action.yml new file mode 100644 index 0000000..e09048a --- /dev/null +++ b/.github/actions/file-is-executable/action.yml @@ -0,0 +1,41 @@ +name: File-Is-Executable +description: Check if listed files are executable. +inputs: + files: + description: List of filenames. + type: string + +runs: + using: composite + steps: + - name: πŸ“‹ Verify file permissions + shell: bash + run: | + set +e + + ANSI_LIGHT_RED="\x1b[91m" + ANSI_LIGHT_GREEN="\x1b[92m" + ANSI_NOCOLOR="\x1b[0m" + + errors=0 + while IFS=$'\r\n' read -r file; do + # skip empty or comment lines + [[ "${file}" == "" || "${file:0:1}" == "#" ]] && continue + + echo -n "Checking '${file}' ... " + if [[ -x "$file" ]]; then + echo "${ANSI_LIGHT_GREEN}[PASSED]${ANSI_NOCOLOR}" + else + echo "${ANSI_LIGHT_RED}[FAILED]${ANSI_NOCOLOR}" + echo "${ANSI_LIGHT_RED}File '${file}' isn't executable.${ANSI_NOCOLOR}" + errors=$((errors + 1)) + fi + done <<<'${{ inputs.files }}' + + echo "" + if [[ $errors -ne 0 ]]; then + echo "${ANSI_LIGHT_RED}Counted ${errors} errors.${ANSI_NOCOLOR}" + exit 1 + else + echo "${ANSI_LIGHT_GREEN}No errors found.${ANSI_NOCOLOR}" + fi diff --git a/.github/workflows/ArtifactsUpload.yml b/.github/workflows/ArtifactsUpload.yml index 6dfe3e8..0c2ab7a 100644 --- a/.github/workflows/ArtifactsUpload.yml +++ b/.github/workflows/ArtifactsUpload.yml @@ -58,6 +58,7 @@ jobs: chmod +x lib/gui/dialog.py - name: πŸ”Ž Inspect directory structure + if: runner.os != 'macOS' run: | tree . @@ -248,10 +249,13 @@ jobs: - {'icon': 'πŸͺŸ', 'name': 'Windows', 'image': 'windows-2022'} steps: + - name: ⏬ Checkout repository to use local actions + uses: actions/checkout@v4 + - name: πŸ“₯ Download artifact uses: actions/download-artifact@v4 with: - name: github-release + name: ${{ matrix.os.name }}-github-release - name: πŸ”Ž Inspect downloaded artifact content run: | @@ -291,94 +295,66 @@ jobs: fi - name: πŸ”Ž Inspect extracted tarball + if: runner.os != 'macOS' run: | tree . - name: πŸ“‹ Verify extracted tarball content - run: | - set +e - - ANSI_LIGHT_RED="\x1b[91m" - ANSI_LIGHT_GREEN="\x1b[92m" - ANSI_NOCOLOR="\x1b[0m" - - expected=( - "document1.txt" - "analysis.log" - "build.log" - "bin/program.py" - "lib/common.py" - ) - - errors=0 - for file in "${expected[@]}"; do - echo -n "Checking '${file}' ... " - if [[ -f "$file" ]]; then - echo "${ANSI_LIGHT_GREEN}[PASSED]${ANSI_NOCOLOR}" - else - echo "${ANSI_LIGHT_RED}[FAILED]${ANSI_NOCOLOR}" - echo "${ANSI_LIGHT_RED}Extracted artifact doesn't contain file '${file}'.${ANSI_NOCOLOR}" - errors=$((errors + 1)) - fi - done - - echo "" - if [[ $errors -ne 0 ]]; then - echo "${ANSI_LIGHT_RED}Counted ${errors} errors.${ANSI_NOCOLOR}" - exit 1 - else - echo "${ANSI_LIGHT_GREEN}No errors found.${ANSI_NOCOLOR}" - fi + uses: ./.github/actions/check-directory-content + with: + files: | + document1.txt + analysis.log + build.log + bin/program.py + lib/common.py - name: πŸ“‹ Verify file permissions - run: | - set +e - - ANSI_LIGHT_RED="\x1b[91m" - ANSI_LIGHT_GREEN="\x1b[92m" - ANSI_NOCOLOR="\x1b[0m" - - expected=( - "bin/program.py" - "lib/common.py" - ) - - errors=0 - for file in "${expected[@]}"; do - echo -n "Checking '${file}' ... " - if [[ -x "$file" ]]; then - echo "${ANSI_LIGHT_GREEN}[PASSED]${ANSI_NOCOLOR}" - else - echo "${ANSI_LIGHT_RED}[FAILED]${ANSI_NOCOLOR}" - echo "${ANSI_LIGHT_RED}File '${file}' isn't executable.${ANSI_NOCOLOR}" - errors=$((errors + 1)) - fi - done - - echo "" - if [[ $errors -ne 0 ]]; then - echo "${ANSI_LIGHT_RED}Counted ${errors} errors.${ANSI_NOCOLOR}" - exit 1 - else - echo "${ANSI_LIGHT_GREEN}No errors found.${ANSI_NOCOLOR}" - fi + uses: ./.github/actions/file-is-executable + with: + files: | + bin/program.py + lib/common.py Inspect-1: - name: Inspect single file - runs-on: ubuntu-24.04 + name: ${{ matrix.os.icon }} Single file ${{ matrix.task.action }} on ${{ matrix.os.name }} + runs-on: ${{ matrix.os.image }} needs: - Build-1 + strategy: + fail-fast: false + matrix: + os: + - {'icon': '🐧', 'name': 'Ubuntu', 'image': 'ubuntu-24.04'} + task: + - {'name': 'inspect', 'action': 'actions/upload-artifact'} + - {'name': 'verify' , 'action': 'pyTooling/upload-artifact'} steps: - name: πŸ“₯ Download artifact uses: actions/download-artifact@v4 + if: matrix.task.name == 'inspect' with: - name: github-single-file + name: ${{ matrix.os.name }}-github-single-file - name: πŸ”Ž Inspect extracted tarball + if: matrix.task.name == 'inspect' run: | tree . + - name: πŸ“₯ Download artifact + uses: actions/download-artifact@v4 + if: matrix.task.name == 'verify' + with: + name: ${{ matrix.os.name }}-pyTooling-single-file + + - name: πŸ”Ž Inspect extracted tarball + if: matrix.task.name == 'verify' + run: | + tar -xf "__pyTooling_upload_artifact__.tar" + rm __pyTooling_upload_artifact__.tar + tree . + Inspect-2: name: Inspect single file in directory runs-on: ubuntu-24.04 @@ -389,7 +365,7 @@ jobs: - name: πŸ“₯ Download artifact uses: actions/download-artifact@v4 with: - name: github-single-file-in-directory + name: ${{ matrix.os.name }}-github-single-file-in-directory - name: πŸ”Ž Inspect extracted tarball run: | @@ -405,7 +381,7 @@ jobs: - name: πŸ“₯ Download artifact uses: actions/download-artifact@v4 with: - name: github-double-file-in-directory + name: ${{ matrix.os.name }}-github-double-file-in-directory - name: πŸ”Ž Inspect extracted tarball run: | @@ -421,7 +397,7 @@ jobs: - name: πŸ“₯ Download artifact uses: actions/download-artifact@v4 with: - name: github-triple-file-in-directory + name: ${{ matrix.os.name }}-github-triple-file-in-directory - name: πŸ”Ž Inspect extracted tarball run: | @@ -437,7 +413,7 @@ jobs: - name: πŸ“₯ Download artifact uses: actions/download-artifact@v4 with: - name: github-double-file-in-deep-directory + name: ${{ matrix.os.name }}-github-double-file-in-deep-directory - name: πŸ”Ž Inspect extracted tarball run: | @@ -453,7 +429,7 @@ jobs: - name: πŸ“₯ Download artifact uses: actions/download-artifact@v4 with: - name: github-single-directory + name: ${{ matrix.os.name }}-github-single-directory - name: πŸ”Ž Inspect extracted tarball run: | @@ -469,7 +445,7 @@ jobs: - name: πŸ“₯ Download artifact uses: actions/download-artifact@v4 with: - name: github-double-directory + name: ${{ matrix.os.name }}-github-double-directory - name: πŸ”Ž Inspect extracted tarball run: | @@ -485,28 +461,10 @@ jobs: - name: πŸ“₯ Download artifact uses: actions/download-artifact@v4 with: - name: github-unpredictable-wildcard - - - name: πŸ”Ž Inspect extracted tarball - run: | - tree . - - Verify-1: - name: Verify single file - runs-on: ubuntu-24.04 - needs: - - Inspect-1 - - steps: - - name: πŸ“₯ Download artifact - uses: actions/download-artifact@v4 - with: - name: pyTooling-single-file + name: ${{ matrix.os.name }}-github-unpredictable-wildcard - name: πŸ”Ž Inspect extracted tarball run: | - tar -xf "__pyTooling_upload_artifact__.tar" - rm __pyTooling_upload_artifact__.tar tree . Verify-2: @@ -519,7 +477,7 @@ jobs: - name: πŸ“₯ Download artifact uses: actions/download-artifact@v4 with: - name: pyTooling-single-file-in-directory + name: ${{ matrix.os.name }}-pyTooling-single-file-in-directory - name: πŸ”Ž Inspect extracted tarball run: | @@ -537,7 +495,7 @@ jobs: - name: πŸ“₯ Download artifact uses: actions/download-artifact@v4 with: - name: pyTooling-double-file-in-directory + name: ${{ matrix.os.name }}-pyTooling-double-file-in-directory - name: πŸ”Ž Inspect extracted tarball run: | @@ -555,7 +513,7 @@ jobs: - name: πŸ“₯ Download artifact uses: actions/download-artifact@v4 with: - name: pyTooling-triple-file-in-directory + name: ${{ matrix.os.name }}-pyTooling-triple-file-in-directory - name: πŸ”Ž Inspect extracted tarball run: | @@ -573,7 +531,7 @@ jobs: - name: πŸ“₯ Download artifact uses: actions/download-artifact@v4 with: - name: pyTooling-double-file-in-deep-directory + name: ${{ matrix.os.name }}-pyTooling-double-file-in-deep-directory - name: πŸ”Ž Inspect extracted tarball run: | @@ -591,7 +549,7 @@ jobs: - name: πŸ“₯ Download artifact uses: actions/download-artifact@v4 with: - name: pyTooling-single-directory + name: ${{ matrix.os.name }}-pyTooling-single-directory - name: πŸ”Ž Inspect extracted tarball run: | @@ -609,7 +567,7 @@ jobs: - name: πŸ“₯ Download artifact uses: actions/download-artifact@v4 with: - name: pyTooling-double-directory + name: ${{ matrix.os.name }}-pyTooling-double-directory - name: πŸ”Ž Inspect extracted tarball run: | @@ -627,7 +585,7 @@ jobs: - name: πŸ“₯ Download artifact uses: actions/download-artifact@v4 with: - name: pyTooling-unpredictable-wildcard + name: ${{ matrix.os.name }}-pyTooling-unpredictable-wildcard - name: πŸ”Ž Inspect extracted tarball run: | @@ -645,7 +603,7 @@ jobs: - name: πŸ“₯ Download artifact uses: actions/download-artifact@v4 with: - name: pyTooling-lib + name: ${{ matrix.os.name }}-pyTooling-lib - name: πŸ”Ž Inspect extracted tarball run: | From 78d6d3ba5c16ea508721d4c6e17de2d491f2f4fd Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Thu, 12 Dec 2024 19:28:46 +0100 Subject: [PATCH 3/9] Fixed Bash color codes. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit co-authored-by: Sven KΓΆhler --- .../check-directory-content/action.yml | 6 ++--- .github/actions/file-is-executable/action.yml | 22 +++++++++---------- .github/workflows/ArtifactsUpload.yml | 12 +++++----- README.md | 10 +++++++++ action.yml | 17 +++++++------- 5 files changed, 39 insertions(+), 28 deletions(-) diff --git a/.github/actions/check-directory-content/action.yml b/.github/actions/check-directory-content/action.yml index 039a795..1cba6a7 100644 --- a/.github/actions/check-directory-content/action.yml +++ b/.github/actions/check-directory-content/action.yml @@ -13,9 +13,9 @@ runs: run: | set +e - ANSI_LIGHT_RED="\x1b[91m" - ANSI_LIGHT_GREEN="\x1b[92m" - ANSI_NOCOLOR="\x1b[0m" + ANSI_LIGHT_RED=$'\x1b[91m' + ANSI_LIGHT_GREEN=$'\x1b[92m' + ANSI_NOCOLOR=$'\x1b[0m' errors=0 while IFS=$'\r\n' read -r file; do diff --git a/.github/actions/file-is-executable/action.yml b/.github/actions/file-is-executable/action.yml index e09048a..2b0efa3 100644 --- a/.github/actions/file-is-executable/action.yml +++ b/.github/actions/file-is-executable/action.yml @@ -13,29 +13,29 @@ runs: run: | set +e - ANSI_LIGHT_RED="\x1b[91m" - ANSI_LIGHT_GREEN="\x1b[92m" - ANSI_NOCOLOR="\x1b[0m" + ANSI_LIGHT_RED=$'\x1b[91m' + ANSI_LIGHT_GREEN=$'\x1b[92m' + ANSI_NOCOLOR=$'\x1b[0m' errors=0 while IFS=$'\r\n' read -r file; do # skip empty or comment lines [[ "${file}" == "" || "${file:0:1}" == "#" ]] && continue - - echo -n "Checking '${file}' ... " + + printf "%s" "Checking '${file}' ... " if [[ -x "$file" ]]; then - echo "${ANSI_LIGHT_GREEN}[PASSED]${ANSI_NOCOLOR}" + printf "%s\n" "${ANSI_LIGHT_GREEN}[PASSED]${ANSI_NOCOLOR}" else - echo "${ANSI_LIGHT_RED}[FAILED]${ANSI_NOCOLOR}" - echo "${ANSI_LIGHT_RED}File '${file}' isn't executable.${ANSI_NOCOLOR}" + printf "%s\n" "${ANSI_LIGHT_RED}[FAILED]${ANSI_NOCOLOR}" + printf "%s\n" "${ANSI_LIGHT_RED}File '${file}' isn't executable.${ANSI_NOCOLOR}" errors=$((errors + 1)) fi done <<<'${{ inputs.files }}' - echo "" + printf "\n" if [[ $errors -ne 0 ]]; then - echo "${ANSI_LIGHT_RED}Counted ${errors} errors.${ANSI_NOCOLOR}" + printf "%s\n" "${ANSI_LIGHT_RED}Counted ${errors} errors.${ANSI_NOCOLOR}" exit 1 else - echo "${ANSI_LIGHT_GREEN}No errors found.${ANSI_NOCOLOR}" + printf "%s\n" "${ANSI_LIGHT_GREEN}No errors found.${ANSI_NOCOLOR}" fi diff --git a/.github/workflows/ArtifactsUpload.yml b/.github/workflows/ArtifactsUpload.yml index 0c2ab7a..e6d38dc 100644 --- a/.github/workflows/ArtifactsUpload.yml +++ b/.github/workflows/ArtifactsUpload.yml @@ -261,9 +261,9 @@ jobs: run: | set +e - ANSI_LIGHT_RED="\x1b[91m" - ANSI_LIGHT_GREEN="\x1b[92m" - ANSI_NOCOLOR="\x1b[0m" + ANSI_LIGHT_RED=$'\x1b[91m' + ANSI_LIGHT_GREEN=$'\x1b[92m' + ANSI_NOCOLOR=$'\x1b[0m' echo "List directory content" ls -lAh . @@ -282,9 +282,9 @@ jobs: run: | set +e - ANSI_LIGHT_RED="\x1b[91m" - ANSI_LIGHT_GREEN="\x1b[92m" - ANSI_NOCOLOR="\x1b[0m" + ANSI_LIGHT_RED=$'\x1b[91m' + ANSI_LIGHT_GREEN=$'\x1b[92m' + ANSI_NOCOLOR=$'\x1b[0m' echo -n "Extracting tarball ... " tar -xf __pyTooling_upload_artifact__.tar diff --git a/README.md b/README.md index 8218ba9..ecef168 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,16 @@ the implementation of such a feature, but this actions is demonstrating a workin See [pyTooling/download-artifact](https://github.com/pyTooling/download-artifact) for the matching download action. +## Advantages Compared to Competing GitHub Actions + +* Support all parameters of `actions/upload-artifact`. + (Others support only a subset.) +* Supports Ubuntu, Windows and macOS GitHub Runner images. + (Others are created for Linux only.) +* Well-defined behavior of tarball internal directory/file structure. + (No silent and "unpredictable" removal of common prefixes.) +* Store files in tarball without owner and group information. +* Testcases implemented as a pipeline verifying uploads/downloads using a tarball. ## Usage diff --git a/action.yml b/action.yml index 0f14de7..f1c057c 100644 --- a/action.yml +++ b/action.yml @@ -106,10 +106,11 @@ runs: run: | set +e - ANSI_LIGHT_RED="\x1b[91m" - ANSI_LIGHT_GREEN="\x1b[92m" - ANSI_CYAN="\x1b[36m" - ANSI_NOCOLOR="\x1b[0m" + ANSI_LIGHT_RED=$'\x1b[91m' + ANSI_LIGHT_GREEN=$'\x1b[92m' + ANSI_LIGHT_YELLOW=$'\x1b[93m' + ANSI_CYAN=$'\x1b[36m' + ANSI_NOCOLOR=$'\x1b[0m' if [[ "${{ inputs.working-directory }}" != "" ]]; then echo -n "Changing artifact root directory to '${{ inputs.working-directory }}' ... " @@ -156,7 +157,7 @@ runs: echo "Checking tar ($(which tar)): ${ANSI_CYAN}$(tar --version | head -n 1)${ANSI_NOCOLOR}" echo -n "Assemble OS specific tar command line options ... " if [[ "${{ runner.os }}" == "macOS" ]]; then - echo "${ANSI_Y}[macOS]${ANSI_NOCOLOR}" + echo "${ANSI_LIGHT_YELLOW}[macOS]${ANSI_NOCOLOR}" # Options for BSD tar tarOptions=() @@ -206,9 +207,9 @@ runs: run: | set +e - ANSI_LIGHT_RED="\x1b[91m" - ANSI_LIGHT_GREEN="\x1b[92m" - ANSI_NOCOLOR="\x1b[0m" + ANSI_LIGHT_RED=$'\x1b[91m' + ANSI_LIGHT_GREEN=$'\x1b[92m' + ANSI_NOCOLOR=$'\x1b[0m' echo -n "Removing temporary tarball ... " rm -f "${{ inputs.tarball-name }}" From f59d0fd5a01de0fd1414f53a655bcd3693e6bd70 Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Thu, 12 Dec 2024 19:45:50 +0100 Subject: [PATCH 4/9] Improved owner and group names/ids for BSD tar. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit co-authored-by: Sven KΓΆhler --- action.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/action.yml b/action.yml index f1c057c..3dfe341 100644 --- a/action.yml +++ b/action.yml @@ -160,7 +160,7 @@ runs: echo "${ANSI_LIGHT_YELLOW}[macOS]${ANSI_NOCOLOR}" # Options for BSD tar - tarOptions=() + tarOptions=("--gname=root" "--gid=0" "--uname=root" "--uid=0") # Option to read filenames from file filesFrom=("-T") @@ -168,7 +168,7 @@ runs: echo "${ANSI_LIGHT_GREEN}[${{ runner.os }}]${ANSI_NOCOLOR}" # Options for GNU tar - tarOptions=("--owner=0" "--group=0") + tarOptions=("--owner=root:0" "--group=root:0") # Option to read filenames from file filesFrom=("--verbatim-files-from" "--files-from") From 8b56f1893d0c3a32fb606c14c46234b84250df27 Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Thu, 12 Dec 2024 19:51:18 +0100 Subject: [PATCH 5/9] Replaced echo by printf. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit co-authored-by: Sven KΓΆhler --- .../check-directory-content/action.yml | 14 ++++---- .github/workflows/ArtifactsUpload.yml | 36 +++++++++---------- action.yml | 30 ++++++++-------- 3 files changed, 40 insertions(+), 40 deletions(-) diff --git a/.github/actions/check-directory-content/action.yml b/.github/actions/check-directory-content/action.yml index 1cba6a7..774c739 100644 --- a/.github/actions/check-directory-content/action.yml +++ b/.github/actions/check-directory-content/action.yml @@ -22,20 +22,20 @@ runs: # skip empty or comment lines [[ "${file}" == "" || "${file:0:1}" == "#" ]] && continue - echo -n "Checking '${file}' ... " + printf "%s" "Checking '${file}' ... " if [[ -f "$file" ]]; then - echo "${ANSI_LIGHT_GREEN}[PASSED]${ANSI_NOCOLOR}" + printf "%s\n" "${ANSI_LIGHT_GREEN}[PASSED]${ANSI_NOCOLOR}" else - echo "${ANSI_LIGHT_RED}[FAILED]${ANSI_NOCOLOR}" - echo "${ANSI_LIGHT_RED}Extracted artifact doesn't contain file '${file}'.${ANSI_NOCOLOR}" + printf "%s\n" "${ANSI_LIGHT_RED}[FAILED]${ANSI_NOCOLOR}" + printf "%s\n" "${ANSI_LIGHT_RED}Extracted artifact doesn't contain file '${file}'.${ANSI_NOCOLOR}" errors=$((errors + 1)) fi done <<<'${{ inputs.files }}' - echo "" + printf "%s\n" "" if [[ $errors -ne 0 ]]; then - echo "${ANSI_LIGHT_RED}Counted ${errors} errors.${ANSI_NOCOLOR}" + printf "%s\n" "${ANSI_LIGHT_RED}Counted ${errors} errors.${ANSI_NOCOLOR}" exit 1 else - echo "${ANSI_LIGHT_GREEN}No errors found.${ANSI_NOCOLOR}" + printf "%s\n" "${ANSI_LIGHT_GREEN}No errors found.${ANSI_NOCOLOR}" fi diff --git a/.github/workflows/ArtifactsUpload.yml b/.github/workflows/ArtifactsUpload.yml index e6d38dc..7f61318 100644 --- a/.github/workflows/ArtifactsUpload.yml +++ b/.github/workflows/ArtifactsUpload.yml @@ -35,26 +35,26 @@ jobs: steps: - name: πŸ–‰ Build 1 run: | - echo "Document 1 $(date --utc '+%d.%m.%Y - %H:%M:%S')" > document1.txt - echo "Analysis log $(date --utc '+%d.%m.%Y - %H:%M:%S')" > analysis.log - echo "Build log $(date --utc '+%d.%m.%Y - %H:%M:%S')" > build.log + printf "%s\n" "Document 1 $(date --utc '+%d.%m.%Y - %H:%M:%S')" > document1.txt + printf "%s\n" "Analysis log $(date --utc '+%d.%m.%Y - %H:%M:%S')" > analysis.log + printf "%s\n" "Build log $(date --utc '+%d.%m.%Y - %H:%M:%S')" > build.log mkdir -p bin - echo "Program $(date --utc '+%d.%m.%Y - %H:%M:%S')" > bin/program.py + printf "%s\n" "Program $(date --utc '+%d.%m.%Y - %H:%M:%S')" > bin/program.py chmod u+x bin/program.py - echo "Tool $(date --utc '+%d.%m.%Y - %H:%M:%S')" > bin/tool.py + printf "%s\n" "Tool $(date --utc '+%d.%m.%Y - %H:%M:%S')" > bin/tool.py chmod g+x bin/tool.py mkdir -p lib - echo "Library 1 $(date --utc '+%d.%m.%Y - %H:%M:%S')" > lib/common.py + printf "%s\n" "Library 1 $(date --utc '+%d.%m.%Y - %H:%M:%S')" > lib/common.py chmod +x lib/common.py - echo "Library 2 $(date --utc '+%d.%m.%Y - %H:%M:%S')" > lib/shared.py + printf "%s\n" "Library 2 $(date --utc '+%d.%m.%Y - %H:%M:%S')" > lib/shared.py chmod +x lib/shared.py mkdir -p lib/gui - echo "Library 3 $(date --utc '+%d.%m.%Y - %H:%M:%S')" > lib/gui/main.py + printf "%s\n" "Library 3 $(date --utc '+%d.%m.%Y - %H:%M:%S')" > lib/gui/main.py chmod +x lib/gui/main.py - echo "Library 4 $(date --utc '+%d.%m.%Y - %H:%M:%S')" > lib/gui/dialog.py + printf "%s\n" "Library 4 $(date --utc '+%d.%m.%Y - %H:%M:%S')" > lib/gui/dialog.py chmod +x lib/gui/dialog.py - name: πŸ”Ž Inspect directory structure @@ -265,17 +265,17 @@ jobs: ANSI_LIGHT_GREEN=$'\x1b[92m' ANSI_NOCOLOR=$'\x1b[0m' - echo "List directory content" + printf "%s\n" "List directory content" ls -lAh . - echo "----------------------------------------" + printf "%s\n" "----------------------------------------" - echo -n "Does tarball exist ... " + printf "%s" "Does tarball exist ... " if [[ ! -f __pyTooling_upload_artifact__.tar ]]; then - echo "${ANSI_LIGHT_RED}[FAILED]${ANSI_NOCOLOR}" - echo "${ANSI_LIGHT_RED}Artifact doesn't contain a tar file named '__pyTooling_upload_artifact__.tar'.${ANSI_NOCOLOR}" + printf "%s\n" "${ANSI_LIGHT_RED}[FAILED]${ANSI_NOCOLOR}" + printf "%s\n" "${ANSI_LIGHT_RED}Artifact doesn't contain a tar file named '__pyTooling_upload_artifact__.tar'.${ANSI_NOCOLOR}" exit 1 else - echo "${ANSI_LIGHT_GREEN}[OK]${ANSI_NOCOLOR}" + printf "%s\n" "${ANSI_LIGHT_GREEN}[OK]${ANSI_NOCOLOR}" fi - name: πŸ“¦ Extract tarball @@ -286,12 +286,12 @@ jobs: ANSI_LIGHT_GREEN=$'\x1b[92m' ANSI_NOCOLOR=$'\x1b[0m' - echo -n "Extracting tarball ... " + printf "%s" "Extracting tarball ... " tar -xf __pyTooling_upload_artifact__.tar if [[ $? -ne 0 ]]; then - echo "${ANSI_LIGHT_RED}[FAILED]${ANSI_NOCOLOR}" + printf "%s\n" "${ANSI_LIGHT_RED}[FAILED]${ANSI_NOCOLOR}" else - echo "${ANSI_LIGHT_GREEN}[OK]${ANSI_NOCOLOR}" + printf "%s\n" "${ANSI_LIGHT_GREEN}[OK]${ANSI_NOCOLOR}" fi - name: πŸ”Ž Inspect extracted tarball diff --git a/action.yml b/action.yml index 3dfe341..103714c 100644 --- a/action.yml +++ b/action.yml @@ -113,14 +113,14 @@ runs: ANSI_NOCOLOR=$'\x1b[0m' if [[ "${{ inputs.working-directory }}" != "" ]]; then - echo -n "Changing artifact root directory to '${{ inputs.working-directory }}' ... " + printf "%s" "Changing artifact root directory to '${{ inputs.working-directory }}' ... " if [[ -d "${{ inputs.working-directory }}" ]]; then pushd "${{ inputs.working-directory }}" > /dev/null if [[ $? -ne 0 ]]; then - echo "${ANSI_LIGHT_RED}[FAILED]${ANSI_NOCOLOR}" + printf "%s\n" "${ANSI_LIGHT_RED}[FAILED]${ANSI_NOCOLOR}" exit 1 else - echo "${ANSI_LIGHT_GREEN}[OK]${ANSI_NOCOLOR}" + printf "%s\n" "${ANSI_LIGHT_GREEN}[OK]${ANSI_NOCOLOR}" dir="${{ inputs.working-directory }}" tarDirectory="" @@ -128,17 +128,17 @@ runs: tarDirectory="../${tarDirectory}" dir=$(dirname -- "${dir}") done - echo " tarDirectory: ${tarDirectory}" + printf "%s\n" " tarDirectory: ${tarDirectory}" fi else - echo "echo ${ANSI_LIGHT_RED}[NO DIRECTORY]${ANSI_NOCOLOR}" + printf "%s\n" "echo ${ANSI_LIGHT_RED}[NO DIRECTORY]${ANSI_NOCOLOR}" exit 1 fi else tarDirectory="" fi - echo -n "Convert provided file patterns to a single line ... " + printf "%s" "Convert provided file patterns to a single line ... " PATTERNS=() while IFS=$'\r\n' read -r pattern; do # skip empty or comment lines @@ -146,7 +146,7 @@ runs: PATTERNS+=("$pattern") done <<<'${{ inputs.path }}' - echo "${ANSI_LIGHT_GREEN}[DONE]${ANSI_NOCOLOR}" + printf "%s\n" "${ANSI_LIGHT_GREEN}[DONE]${ANSI_NOCOLOR}" print_files_unique() { for i in "$@"; do @@ -154,10 +154,10 @@ runs: done | sort | uniq } - echo "Checking tar ($(which tar)): ${ANSI_CYAN}$(tar --version | head -n 1)${ANSI_NOCOLOR}" - echo -n "Assemble OS specific tar command line options ... " + printf "%s\n" "Checking tar ($(which tar)): ${ANSI_CYAN}$(tar --version | head -n 1)${ANSI_NOCOLOR}" + printf "%s" "Assemble OS specific tar command line options ... " if [[ "${{ runner.os }}" == "macOS" ]]; then - echo "${ANSI_LIGHT_YELLOW}[macOS]${ANSI_NOCOLOR}" + printf "%s\n" "${ANSI_LIGHT_YELLOW}[macOS]${ANSI_NOCOLOR}" # Options for BSD tar tarOptions=("--gname=root" "--gid=0" "--uname=root" "--uid=0") @@ -165,7 +165,7 @@ runs: # Option to read filenames from file filesFrom=("-T") elif [[ "${{ runner.os }}" == "Linux" || "${{ runner.os }}" == "Windows" ]]; then - echo "${ANSI_LIGHT_GREEN}[${{ runner.os }}]${ANSI_NOCOLOR}" + printf "%s\n" "${ANSI_LIGHT_GREEN}[${{ runner.os }}]${ANSI_NOCOLOR}" # Options for GNU tar tarOptions=("--owner=root:0" "--group=root:0") @@ -173,14 +173,14 @@ runs: # Option to read filenames from file filesFrom=("--verbatim-files-from" "--files-from") else - echo "${ANSI_LIGHT_RED}[UNSUPPORTED]${ANSI_NOCOLOR}" + printf "%s\n" "${ANSI_LIGHT_RED}[UNSUPPORTED]${ANSI_NOCOLOR}" exit 1 fi - echo -n "Creating temporary tarball '${tarDirectory}${{ inputs.tarball-name }}' ... " + printf "%s" "Creating temporary tarball '${tarDirectory}${{ inputs.tarball-name }}' ... " tar -cf "${tarDirectory}${{ inputs.tarball-name }}" "${tarOptions[@]}" "${filesFrom[@]}" <(print_files_unique "${PATTERNS[@]}") if [[ $? -ne 0 ]]; then - echo "${ANSI_LIGHT_RED}[FAILED]${ANSI_NOCOLOR}" + printf "%s\n" "${ANSI_LIGHT_RED}[FAILED]${ANSI_NOCOLOR}" exit 1 else echo -e "${ANSI_LIGHT_GREEN}[OK]${ANSI_NOCOLOR}" @@ -211,7 +211,7 @@ runs: ANSI_LIGHT_GREEN=$'\x1b[92m' ANSI_NOCOLOR=$'\x1b[0m' - echo -n "Removing temporary tarball ... " + printf "%s" "Removing temporary tarball ... " rm -f "${{ inputs.tarball-name }}" if [[ $? -ne 0 ]]; then echo -e "${ANSI_LIGHT_RED}[FAILED]${ANSI_NOCOLOR}" From baffe53003613b033c78d1624a7525b762665aeb Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Fri, 13 Dec 2024 00:36:54 +0100 Subject: [PATCH 6/9] Improved pipeline testcases. --- .github/actions/create-files/action.yml | 40 ++ .github/workflows/ArtifactsUpload.yml | 491 +++++++++++++++--------- 2 files changed, 341 insertions(+), 190 deletions(-) create mode 100644 .github/actions/create-files/action.yml diff --git a/.github/actions/create-files/action.yml b/.github/actions/create-files/action.yml new file mode 100644 index 0000000..a6f3bca --- /dev/null +++ b/.github/actions/create-files/action.yml @@ -0,0 +1,40 @@ +name: Create test files +description: Create an artificial directory and file structure + +runs: + using: composite + steps: + - name: πŸ–‰ Create some artificial file and directory structures + shell: bash + run: | + printf "%s\n" "Root" + printf "%s\n" "Document 1 $(date --utc '+%d.%m.%Y - %H:%M:%S')" > document1.txt + printf "%s\n" "Analysis log $(date --utc '+%d.%m.%Y - %H:%M:%S')" > analysis.log + printf "%s\n" "Build log $(date --utc '+%d.%m.%Y - %H:%M:%S')" > build.log + + printf "%s\n" "bin/" + mkdir -p bin + printf "%s\n" "Program $(date --utc '+%d.%m.%Y - %H:%M:%S')" > bin/program.py + chmod u+x bin/program.py + printf "%s\n" "Tool $(date --utc '+%d.%m.%Y - %H:%M:%S')" > bin/tool.py + chmod g+x bin/tool.py + + printf "%s\n" "lib/" + mkdir -p lib + printf "%s\n" "Library 1 $(date --utc '+%d.%m.%Y - %H:%M:%S')" > lib/common.py + chmod +x lib/common.py + printf "%s\n" "Library 2 $(date --utc '+%d.%m.%Y - %H:%M:%S')" > lib/shared.py + chmod +x lib/shared.py + + printf "%s\n" "lib/gui/" + mkdir -p lib/gui + printf "%s\n" "Library 3 $(date --utc '+%d.%m.%Y - %H:%M:%S')" > lib/gui/main.py + chmod +x lib/gui/main.py + printf "%s\n" "Library 4 $(date --utc '+%d.%m.%Y - %H:%M:%S')" > lib/gui/dialog.py + chmod +x lib/gui/dialog.py + + - name: πŸ”Ž Inspect directory structure + if: runner.os != 'macOS' && runner.os != 'Windows' + shell: bash + run: | + tree . diff --git a/.github/workflows/ArtifactsUpload.yml b/.github/workflows/ArtifactsUpload.yml index 7f61318..088c980 100644 --- a/.github/workflows/ArtifactsUpload.yml +++ b/.github/workflows/ArtifactsUpload.yml @@ -33,34 +33,10 @@ jobs: - {'icon': 'πŸͺŸ', 'name': 'Windows', 'image': 'windows-2022'} steps: - - name: πŸ–‰ Build 1 - run: | - printf "%s\n" "Document 1 $(date --utc '+%d.%m.%Y - %H:%M:%S')" > document1.txt - printf "%s\n" "Analysis log $(date --utc '+%d.%m.%Y - %H:%M:%S')" > analysis.log - printf "%s\n" "Build log $(date --utc '+%d.%m.%Y - %H:%M:%S')" > build.log - - mkdir -p bin - printf "%s\n" "Program $(date --utc '+%d.%m.%Y - %H:%M:%S')" > bin/program.py - chmod u+x bin/program.py - printf "%s\n" "Tool $(date --utc '+%d.%m.%Y - %H:%M:%S')" > bin/tool.py - chmod g+x bin/tool.py - - mkdir -p lib - printf "%s\n" "Library 1 $(date --utc '+%d.%m.%Y - %H:%M:%S')" > lib/common.py - chmod +x lib/common.py - printf "%s\n" "Library 2 $(date --utc '+%d.%m.%Y - %H:%M:%S')" > lib/shared.py - chmod +x lib/shared.py - - mkdir -p lib/gui - printf "%s\n" "Library 3 $(date --utc '+%d.%m.%Y - %H:%M:%S')" > lib/gui/main.py - chmod +x lib/gui/main.py - printf "%s\n" "Library 4 $(date --utc '+%d.%m.%Y - %H:%M:%S')" > lib/gui/dialog.py - chmod +x lib/gui/dialog.py - - - name: πŸ”Ž Inspect directory structure - if: runner.os != 'macOS' - run: | - tree . + - name: ⏬ Checkout repository to use local actions + uses: actions/checkout@v4 + + - uses: ./.github/actions/create-files - name: πŸ“€ Upload artifact '${{ matrix.os.name }}-github-release' uses: pyTooling/upload-artifact@dev @@ -327,286 +303,421 @@ jobs: os: - {'icon': '🐧', 'name': 'Ubuntu', 'image': 'ubuntu-24.04'} task: - - {'name': 'inspect', 'action': 'actions/upload-artifact'} - - {'name': 'verify' , 'action': 'pyTooling/upload-artifact'} + - {'name': 'inspect', 'artifact': 'github', 'action': 'actions/upload-artifact'} + - {'name': 'verify' , 'artifact': 'pyTooling', 'action': 'pyTooling/upload-artifact'} steps: - - name: πŸ“₯ Download artifact - uses: actions/download-artifact@v4 - if: matrix.task.name == 'inspect' - with: - name: ${{ matrix.os.name }}-github-single-file - - - name: πŸ”Ž Inspect extracted tarball - if: matrix.task.name == 'inspect' - run: | - tree . + - name: ⏬ Checkout repository to use local actions + uses: actions/checkout@v4 - - name: πŸ“₯ Download artifact + - name: πŸ“₯ Download artifact uploaded via '${{ matrix.task.action }}' uses: actions/download-artifact@v4 - if: matrix.task.name == 'verify' with: - name: ${{ matrix.os.name }}-pyTooling-single-file + name: ${{ matrix.os.name }}-${{ matrix.task.artifact }}-single-file - - name: πŸ”Ž Inspect extracted tarball + - name: πŸ”Ž Extract tarball if: matrix.task.name == 'verify' run: | tar -xf "__pyTooling_upload_artifact__.tar" rm __pyTooling_upload_artifact__.tar + + - name: πŸ”Ž Inspect directory + run: | tree . + - name: πŸ“‹ Verify artifact content + uses: ./.github/actions/check-directory-content + with: + files: | + document1.txt + Inspect-2: - name: Inspect single file in directory - runs-on: ubuntu-24.04 + name: ${{ matrix.os.icon }} Inspect single file in directory ${{ matrix.task.action }} on ${{ matrix.os.name }} + runs-on: ${{ matrix.os.image }} needs: - Build-1 + strategy: + fail-fast: false + matrix: + os: + - {'icon': '🐧', 'name': 'Ubuntu', 'image': 'ubuntu-24.04'} + task: + - {'name': 'inspect', 'artifact': 'github', 'action': 'actions/upload-artifact'} + - {'name': 'verify' , 'artifact': 'pyTooling', 'action': 'pyTooling/upload-artifact'} steps: - - name: πŸ“₯ Download artifact + - name: ⏬ Checkout repository to use local actions + uses: actions/checkout@v4 + + - name: πŸ“₯ Download artifact uploaded via '${{ matrix.task.action }}' uses: actions/download-artifact@v4 with: - name: ${{ matrix.os.name }}-github-single-file-in-directory + name: ${{ matrix.os.name }}-${{ matrix.task.artifact }}-single-file-in-directory - - name: πŸ”Ž Inspect extracted tarball + - name: πŸ”Ž Extract tarball + if: matrix.task.name == 'verify' run: | - tree . - - Inspect-3: - name: Inspect double file in directory - runs-on: ubuntu-24.04 - needs: - - Build-1 - - steps: - - name: πŸ“₯ Download artifact - uses: actions/download-artifact@v4 - with: - name: ${{ matrix.os.name }}-github-double-file-in-directory + tar -xf "__pyTooling_upload_artifact__.tar" + rm __pyTooling_upload_artifact__.tar - - name: πŸ”Ž Inspect extracted tarball + - name: πŸ”Ž Inspect directory run: | tree . - Inspect-4: - name: Inspect triple file in directory - runs-on: ubuntu-24.04 - needs: - - Build-1 - - steps: - - name: πŸ“₯ Download artifact - uses: actions/download-artifact@v4 + - name: πŸ“‹ Verify artifact content downloaded via 'actions/download-artifact' + uses: ./.github/actions/check-directory-content + if: matrix.task.name == 'inspect' with: - name: ${{ matrix.os.name }}-github-triple-file-in-directory + files: | + program.py - - name: πŸ”Ž Inspect extracted tarball - run: | - tree . + - name: πŸ“‹ Verify extracted tarball content + uses: ./.github/actions/check-directory-content + if: matrix.task.name == 'verify' + with: + files: | + bin/program.py - Inspect-5: - name: Inspect double file in deep directory - runs-on: ubuntu-24.04 + Inspect-3: + name: ${{ matrix.os.icon }} Inspect double file in directory ${{ matrix.task.action }} on ${{ matrix.os.name }} + runs-on: ${{ matrix.os.image }} needs: - Build-1 + strategy: + fail-fast: false + matrix: + os: + - {'icon': '🐧', 'name': 'Ubuntu', 'image': 'ubuntu-24.04'} + task: + - {'name': 'inspect', 'artifact': 'github', 'action': 'actions/upload-artifact'} + - {'name': 'verify' , 'artifact': 'pyTooling', 'action': 'pyTooling/upload-artifact'} steps: - - name: πŸ“₯ Download artifact + - name: ⏬ Checkout repository to use local actions + uses: actions/checkout@v4 + + - name: πŸ“₯ Download artifact uploaded via '${{ matrix.task.action }}' uses: actions/download-artifact@v4 with: - name: ${{ matrix.os.name }}-github-double-file-in-deep-directory + name: ${{ matrix.os.name }}-${{ matrix.task.artifact }}-double-file-in-directory - - name: πŸ”Ž Inspect extracted tarball + - name: πŸ”Ž Extract tarball + if: matrix.task.name == 'verify' run: | - tree . + tar -xf "__pyTooling_upload_artifact__.tar" + rm __pyTooling_upload_artifact__.tar - Inspect-6: - name: Inspect single directory - runs-on: ubuntu-24.04 - needs: - - Build-1 + - name: πŸ”Ž Inspect directory + run: | + tree . - steps: - - name: πŸ“₯ Download artifact - uses: actions/download-artifact@v4 + - name: πŸ“‹ Verify artifact content downloaded via 'actions/download-artifact' + uses: ./.github/actions/check-directory-content + if: matrix.task.name == 'inspect' with: - name: ${{ matrix.os.name }}-github-single-directory + files: | + program.py + tool.py - - name: πŸ”Ž Inspect extracted tarball - run: | - tree . + - name: πŸ“‹ Verify extracted tarball content + uses: ./.github/actions/check-directory-content + if: matrix.task.name == 'verify' + with: + files: | + bin/program.py + bin/tool.py - Inspect-7: - name: Inspect double directory - runs-on: ubuntu-24.04 + Inspect-4: + name: ${{ matrix.os.icon }} Inspect triple file in directory ${{ matrix.task.action }} on ${{ matrix.os.name }} + runs-on: ${{ matrix.os.image }} needs: - Build-1 + strategy: + fail-fast: false + matrix: + os: + - {'icon': '🐧', 'name': 'Ubuntu', 'image': 'ubuntu-24.04'} + task: + - {'name': 'inspect', 'artifact': 'github', 'action': 'actions/upload-artifact'} + - {'name': 'verify' , 'artifact': 'pyTooling', 'action': 'pyTooling/upload-artifact'} steps: - - name: πŸ“₯ Download artifact + - name: ⏬ Checkout repository to use local actions + uses: actions/checkout@v4 + + - name: πŸ“₯ Download artifact uploaded via '${{ matrix.task.action }}' uses: actions/download-artifact@v4 with: - name: ${{ matrix.os.name }}-github-double-directory + name: ${{ matrix.os.name }}-${{ matrix.task.artifact }}-triple-file-in-directory - - name: πŸ”Ž Inspect extracted tarball + - name: πŸ”Ž Extract tarball + if: matrix.task.name == 'verify' run: | - tree . + tar -xf "__pyTooling_upload_artifact__.tar" + rm __pyTooling_upload_artifact__.tar - Inspect-8: - name: Inspect Unpredictable Wildcard - runs-on: ubuntu-24.04 - needs: - - Build-1 + - name: πŸ”Ž Inspect directory + run: | + tree . - steps: - - name: πŸ“₯ Download artifact - uses: actions/download-artifact@v4 + - name: πŸ“‹ Verify artifact content downloaded via 'actions/download-artifact' + uses: ./.github/actions/check-directory-content + if: matrix.task.name == 'inspect' with: - name: ${{ matrix.os.name }}-github-unpredictable-wildcard + files: | + common.py + gui/main.py + gui/dialog.py - - name: πŸ”Ž Inspect extracted tarball - run: | - tree . + - name: πŸ“‹ Verify extracted tarball content + uses: ./.github/actions/check-directory-content + if: matrix.task.name == 'verify' + with: + files: | + lib/common.py + lib/gui/main.py + lib/gui/dialog.py - Verify-2: - name: Verify single file in directory - runs-on: ubuntu-24.04 + Inspect-5: + name: ${{ matrix.os.icon }} Inspect double file in deep directory ${{ matrix.task.action }} on ${{ matrix.os.name }} + runs-on: ${{ matrix.os.image }} needs: - - Inspect-2 + - Build-1 + strategy: + fail-fast: false + matrix: + os: + - {'icon': '🐧', 'name': 'Ubuntu', 'image': 'ubuntu-24.04'} + task: + - {'name': 'inspect', 'artifact': 'github', 'action': 'actions/upload-artifact'} + - {'name': 'verify' , 'artifact': 'pyTooling', 'action': 'pyTooling/upload-artifact'} steps: - - name: πŸ“₯ Download artifact + - name: ⏬ Checkout repository to use local actions + uses: actions/checkout@v4 + + - name: πŸ“₯ Download artifact uploaded via '${{ matrix.task.action }}' uses: actions/download-artifact@v4 with: - name: ${{ matrix.os.name }}-pyTooling-single-file-in-directory + name: ${{ matrix.os.name }}-${{ matrix.task.artifact }}-double-file-in-deep-directory - - name: πŸ”Ž Inspect extracted tarball + - name: πŸ”Ž Extract tarball + if: matrix.task.name == 'verify' run: | tar -xf "__pyTooling_upload_artifact__.tar" rm __pyTooling_upload_artifact__.tar - tree . - Verify-3: - name: Verify double file in directory - runs-on: ubuntu-24.04 - needs: - - Inspect-3 + - name: πŸ”Ž Inspect directory + run: | + tree . - steps: - - name: πŸ“₯ Download artifact - uses: actions/download-artifact@v4 + - name: πŸ“‹ Verify artifact content downloaded via 'actions/download-artifact' + uses: ./.github/actions/check-directory-content + if: matrix.task.name == 'inspect' with: - name: ${{ matrix.os.name }}-pyTooling-double-file-in-directory + files: | + main.py + dialog.py - - name: πŸ”Ž Inspect extracted tarball - run: | - tar -xf "__pyTooling_upload_artifact__.tar" - rm __pyTooling_upload_artifact__.tar - tree . + - name: πŸ“‹ Verify extracted tarball content + uses: ./.github/actions/check-directory-content + if: matrix.task.name == 'verify' + with: + files: | + lib/gui/main.py + lib/gui/dialog.py - Verify-4: - name: Verify triple file in directory - runs-on: ubuntu-24.04 + Inspect-6: + name: ${{ matrix.os.icon }} Inspect single directory ${{ matrix.task.action }} on ${{ matrix.os.name }} + runs-on: ${{ matrix.os.image }} needs: - - Inspect-4 + - Build-1 + strategy: + fail-fast: false + matrix: + os: + - {'icon': '🐧', 'name': 'Ubuntu', 'image': 'ubuntu-24.04'} + task: + - {'name': 'inspect', 'artifact': 'github', 'action': 'actions/upload-artifact'} + - {'name': 'verify' , 'artifact': 'pyTooling', 'action': 'pyTooling/upload-artifact'} steps: - - name: πŸ“₯ Download artifact + - name: ⏬ Checkout repository to use local actions + uses: actions/checkout@v4 + + - name: πŸ“₯ Download artifact uploaded via '${{ matrix.task.action }}' uses: actions/download-artifact@v4 with: - name: ${{ matrix.os.name }}-pyTooling-triple-file-in-directory + name: ${{ matrix.os.name }}-${{ matrix.task.artifact }}-single-directory - - name: πŸ”Ž Inspect extracted tarball + - name: πŸ”Ž Extract tarball + if: matrix.task.name == 'verify' run: | tar -xf "__pyTooling_upload_artifact__.tar" rm __pyTooling_upload_artifact__.tar - tree . - Verify-5: - name: Verify double file in deep directory - runs-on: ubuntu-24.04 - needs: - - Inspect-5 + - name: πŸ”Ž Inspect directory + run: | + tree . - steps: - - name: πŸ“₯ Download artifact - uses: actions/download-artifact@v4 + - name: πŸ“‹ Verify artifact content downloaded via 'actions/download-artifact' + uses: ./.github/actions/check-directory-content + if: matrix.task.name == 'inspect' with: - name: ${{ matrix.os.name }}-pyTooling-double-file-in-deep-directory + files: | + program.py + tool.py - - name: πŸ”Ž Inspect extracted tarball - run: | - tar -xf "__pyTooling_upload_artifact__.tar" - rm __pyTooling_upload_artifact__.tar - tree . + - name: πŸ“‹ Verify extracted tarball content + uses: ./.github/actions/check-directory-content + if: matrix.task.name == 'verify' + with: + files: | + bin/program.py + bin/tool.py - Verify-6: - name: Verify single directory - runs-on: ubuntu-24.04 + Inspect-7: + name: ${{ matrix.os.icon }} Inspect double directory ${{ matrix.task.action }} on ${{ matrix.os.name }} + runs-on: ${{ matrix.os.image }} needs: - - Inspect-6 + - Build-1 + strategy: + fail-fast: false + matrix: + os: + - {'icon': '🐧', 'name': 'Ubuntu', 'image': 'ubuntu-24.04'} + task: + - {'name': 'inspect', 'artifact': 'github', 'action': 'actions/upload-artifact'} + - {'name': 'verify' , 'artifact': 'pyTooling', 'action': 'pyTooling/upload-artifact'} steps: - - name: πŸ“₯ Download artifact + - name: ⏬ Checkout repository to use local actions + uses: actions/checkout@v4 + + - name: πŸ“₯ Download artifact uploaded via '${{ matrix.task.action }}' uses: actions/download-artifact@v4 with: - name: ${{ matrix.os.name }}-pyTooling-single-directory + name: ${{ matrix.os.name }}-${{ matrix.task.artifact }}-double-directory - - name: πŸ”Ž Inspect extracted tarball + - name: πŸ”Ž Extract tarball + if: matrix.task.name == 'verify' run: | tar -xf "__pyTooling_upload_artifact__.tar" rm __pyTooling_upload_artifact__.tar - tree . - Verify-7: - name: Verify double directory - runs-on: ubuntu-24.04 - needs: - - Inspect-7 + - name: πŸ”Ž Inspect directory + run: | + tree . - steps: - - name: πŸ“₯ Download artifact - uses: actions/download-artifact@v4 + - name: πŸ“‹ Verify artifact content downloaded via 'actions/download-artifact' + uses: ./.github/actions/check-directory-content + if: matrix.task.name == 'inspect' with: - name: ${{ matrix.os.name }}-pyTooling-double-directory + files: | + bin/program.py + bin/tool.py + lib/common.py + lib/shared.py + lib/gui/main.py + lib/gui/dialog.py - - name: πŸ”Ž Inspect extracted tarball - run: | - tar -xf "__pyTooling_upload_artifact__.tar" - rm __pyTooling_upload_artifact__.tar - tree . + - name: πŸ“‹ Verify extracted tarball content + uses: ./.github/actions/check-directory-content + if: matrix.task.name == 'verify' + with: + files: | + bin/program.py + bin/tool.py + lib/common.py + lib/shared.py + lib/gui/main.py + lib/gui/dialog.py - Verify-8: - name: Verify Unpredictable Wildcard - runs-on: ubuntu-24.04 + Inspect-8: + name: ${{ matrix.os.icon }} Unpredictable Wildcard ${{ matrix.task.action }} on ${{ matrix.os.name }} + runs-on: ${{ matrix.os.image }} needs: - - Inspect-8 + - Build-1 + strategy: + fail-fast: false + matrix: + os: + - {'icon': '🐧', 'name': 'Ubuntu', 'image': 'ubuntu-24.04'} + task: + - {'name': 'inspect', 'artifact': 'github', 'action': 'actions/upload-artifact'} + - {'name': 'verify' , 'artifact': 'pyTooling', 'action': 'pyTooling/upload-artifact'} steps: - - name: πŸ“₯ Download artifact + - name: ⏬ Checkout repository to use local actions + uses: actions/checkout@v4 + + - name: πŸ“₯ Download artifact uploaded via '${{ matrix.task.action }}' uses: actions/download-artifact@v4 with: - name: ${{ matrix.os.name }}-pyTooling-unpredictable-wildcard + name: ${{ matrix.os.name }}-${{ matrix.task.artifact }}-unpredictable-wildcard - - name: πŸ”Ž Inspect extracted tarball + - name: πŸ”Ž Extract tarball + if: matrix.task.name == 'verify' run: | tar -xf "__pyTooling_upload_artifact__.tar" rm __pyTooling_upload_artifact__.tar + + - name: πŸ”Ž Inspect directory + run: | tree . + - name: πŸ“‹ Verify artifact content downloaded via 'actions/download-artifact' + uses: ./.github/actions/check-directory-content + if: matrix.task.name == 'inspect' + with: + files: | + common.py + + - name: πŸ“‹ Verify extracted tarball content + uses: ./.github/actions/check-directory-content + if: matrix.task.name == 'verify' + with: + files: | + common.py + Verify-9: name: Verify lib directory runs-on: ubuntu-24.04 needs: - Build-1 + strategy: + fail-fast: false + matrix: + os: + - {'icon': '🐧', 'name': 'Ubuntu', 'image': 'ubuntu-24.04'} + task: +# - {'name': 'inspect', 'artifact': 'github', 'action': 'actions/upload-artifact'} + - {'name': 'verify' , 'artifact': 'pyTooling', 'action': 'pyTooling/upload-artifact'} steps: - - name: πŸ“₯ Download artifact + - name: ⏬ Checkout repository to use local actions + uses: actions/checkout@v4 + + - name: πŸ“₯ Download artifact uploaded via '${{ matrix.task.action }}' uses: actions/download-artifact@v4 with: - name: ${{ matrix.os.name }}-pyTooling-lib + name: ${{ matrix.os.name }}-${{ matrix.task.artifact }}-lib - - name: πŸ”Ž Inspect extracted tarball + - name: πŸ”Ž Extract tarball + if: matrix.task.name == 'verify' run: | tar -xf "__pyTooling_upload_artifact__.tar" rm __pyTooling_upload_artifact__.tar + + - name: πŸ”Ž Inspect directory + run: | tree . + + - name: πŸ“‹ Verify artifact content downloaded via 'actions/download-artifact' + uses: ./.github/actions/check-directory-content + with: + files: | + common.py + shared.py + gui/dialog.py + gui/main.py From 7b62203edf38fbd374f20c34fcec652a28361e7e Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Sat, 14 Dec 2024 22:51:27 +0100 Subject: [PATCH 7/9] Enabled globstar option. --- .github/workflows/ArtifactsUpload.yml | 29 ++++++++++++++------------- action.yml | 1 + 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/.github/workflows/ArtifactsUpload.yml b/.github/workflows/ArtifactsUpload.yml index 088c980..95d5a16 100644 --- a/.github/workflows/ArtifactsUpload.yml +++ b/.github/workflows/ArtifactsUpload.yml @@ -21,7 +21,7 @@ on: workflow_dispatch: jobs: - Build-1: + Build: name: ${{ matrix.os.icon }} Build 1 on ${{ matrix.os.name }} - Upload artifact runs-on: ${{ matrix.os.image }} strategy: @@ -215,7 +215,7 @@ jobs: name: ${{ matrix.os.icon }} Verify artifact content on ${{ matrix.os.name }} runs-on: ${{ matrix.os.image }} needs: - - Build-1 + - Build strategy: fail-fast: false matrix: @@ -296,7 +296,7 @@ jobs: name: ${{ matrix.os.icon }} Single file ${{ matrix.task.action }} on ${{ matrix.os.name }} runs-on: ${{ matrix.os.image }} needs: - - Build-1 + - Build strategy: fail-fast: false matrix: @@ -335,7 +335,7 @@ jobs: name: ${{ matrix.os.icon }} Inspect single file in directory ${{ matrix.task.action }} on ${{ matrix.os.name }} runs-on: ${{ matrix.os.image }} needs: - - Build-1 + - Build strategy: fail-fast: false matrix: @@ -382,7 +382,7 @@ jobs: name: ${{ matrix.os.icon }} Inspect double file in directory ${{ matrix.task.action }} on ${{ matrix.os.name }} runs-on: ${{ matrix.os.image }} needs: - - Build-1 + - Build strategy: fail-fast: false matrix: @@ -431,7 +431,7 @@ jobs: name: ${{ matrix.os.icon }} Inspect triple file in directory ${{ matrix.task.action }} on ${{ matrix.os.name }} runs-on: ${{ matrix.os.image }} needs: - - Build-1 + - Build strategy: fail-fast: false matrix: @@ -482,7 +482,7 @@ jobs: name: ${{ matrix.os.icon }} Inspect double file in deep directory ${{ matrix.task.action }} on ${{ matrix.os.name }} runs-on: ${{ matrix.os.image }} needs: - - Build-1 + - Build strategy: fail-fast: false matrix: @@ -531,7 +531,7 @@ jobs: name: ${{ matrix.os.icon }} Inspect single directory ${{ matrix.task.action }} on ${{ matrix.os.name }} runs-on: ${{ matrix.os.image }} needs: - - Build-1 + - Build strategy: fail-fast: false matrix: @@ -580,7 +580,7 @@ jobs: name: ${{ matrix.os.icon }} Inspect double directory ${{ matrix.task.action }} on ${{ matrix.os.name }} runs-on: ${{ matrix.os.image }} needs: - - Build-1 + - Build strategy: fail-fast: false matrix: @@ -637,7 +637,7 @@ jobs: name: ${{ matrix.os.icon }} Unpredictable Wildcard ${{ matrix.task.action }} on ${{ matrix.os.name }} runs-on: ${{ matrix.os.image }} needs: - - Build-1 + - Build strategy: fail-fast: false matrix: @@ -671,27 +671,28 @@ jobs: if: matrix.task.name == 'inspect' with: files: | - common.py + lib/gui/main.py + lib/gui/dialog.py - name: πŸ“‹ Verify extracted tarball content uses: ./.github/actions/check-directory-content if: matrix.task.name == 'verify' with: files: | - common.py + lib/gui/main.py + lib/gui/dialog.py Verify-9: name: Verify lib directory runs-on: ubuntu-24.04 needs: - - Build-1 + - Build strategy: fail-fast: false matrix: os: - {'icon': '🐧', 'name': 'Ubuntu', 'image': 'ubuntu-24.04'} task: -# - {'name': 'inspect', 'artifact': 'github', 'action': 'actions/upload-artifact'} - {'name': 'verify' , 'artifact': 'pyTooling', 'action': 'pyTooling/upload-artifact'} steps: diff --git a/action.yml b/action.yml index 103714c..fe57037 100644 --- a/action.yml +++ b/action.yml @@ -105,6 +105,7 @@ runs: shell: bash run: | set +e + shopt -s globstar ANSI_LIGHT_RED=$'\x1b[91m' ANSI_LIGHT_GREEN=$'\x1b[92m' From b859b6a282fe4a2e427a1ee3ab4fc12e35cff539 Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Sat, 14 Dec 2024 23:04:31 +0100 Subject: [PATCH 8/9] Updated README. --- README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index ecef168..e711c0d 100644 --- a/README.md +++ b/README.md @@ -90,8 +90,8 @@ This action uses `tar` as provided by the GitHub runner's operating system image To ensure files starting with a dash aren't considered command line options to `tar`, `tar` is called with `--verbatim-files-from` option. -To ensure files are extracted and assigned to the owner/group of the extracting user, options `--owner=0` and -`--group=0` are used when creating the tarball. +To ensure files are extracted and assigned to the owner/group of the extracting user, options `--owner=root:0` and +`--group=root:0` are used when creating the tarball. ### On macOS (BSD tar) @@ -108,7 +108,8 @@ as a command line option. > > Source: https://man.freebsd.org/cgi/man.cgi?tar(1) -⚠ BSD tar doesn't support a `--owner=0` and `--group=0` option. +To ensure files are extracted and assigned to the owner/group of the extracting user, options `--gname=root`, `--gid=0`, +`--uname=root` and `--uid=0` are used when creating the tarball. ### On Windows (GNU tar) @@ -116,8 +117,8 @@ as a command line option. To ensure files starting with a dash aren't considered command line options to `tar`, `tar` is called with `--verbatim-files-from` option. -To ensure files are extracted and assigned to the owner/group of the extracting user, options `--owner=0` and -`--group=0` are used when creating the tarball. +To ensure files are extracted and assigned to the owner/group of the extracting user, options `--owner=root:0` and +`--group=root:0` are used when creating the tarball. ## Dependencies From 6ffebce11174ad4b00b1f025f497fba130462d15 Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Sat, 14 Dec 2024 23:08:13 +0100 Subject: [PATCH 9/9] Added missing license headers. --- .../actions/check-directory-content/action.yml | 16 ++++++++++++++++ .github/actions/create-files/action.yml | 16 ++++++++++++++++ .github/actions/file-is-executable/action.yml | 16 ++++++++++++++++ 3 files changed, 48 insertions(+) diff --git a/.github/actions/check-directory-content/action.yml b/.github/actions/check-directory-content/action.yml index 774c739..9a259cd 100644 --- a/.github/actions/check-directory-content/action.yml +++ b/.github/actions/check-directory-content/action.yml @@ -1,3 +1,19 @@ +# The MIT License (MIT) +# +# Copyright Β© 2024 The pyTooling Authors +# +# 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. name: Check-Directory-Content description: Check if directory contains the listed files. inputs: diff --git a/.github/actions/create-files/action.yml b/.github/actions/create-files/action.yml index a6f3bca..2b938a7 100644 --- a/.github/actions/create-files/action.yml +++ b/.github/actions/create-files/action.yml @@ -1,3 +1,19 @@ +# The MIT License (MIT) +# +# Copyright Β© 2024 The pyTooling Authors +# +# 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. name: Create test files description: Create an artificial directory and file structure diff --git a/.github/actions/file-is-executable/action.yml b/.github/actions/file-is-executable/action.yml index 2b0efa3..1733c2a 100644 --- a/.github/actions/file-is-executable/action.yml +++ b/.github/actions/file-is-executable/action.yml @@ -1,3 +1,19 @@ +# The MIT License (MIT) +# +# Copyright Β© 2024 The pyTooling Authors +# +# 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. name: File-Is-Executable description: Check if listed files are executable. inputs: