testing actions #25
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Verify ZIPs - Checksum + CAP Structure | |
| on: | |
| pull_request: | |
| types: [opened, reopened, synchronize, edited, ready_for_review] | |
| jobs: | |
| verify-zips: | |
| runs-on: ubuntu-latest | |
| env: | |
| BASE_SHA: ${{ github.event.pull_request.base.sha }} | |
| HEAD_SHA: ${{ github.event.pull_request.head.sha }} | |
| steps: | |
| - name: Checkout PR HEAD | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Step 1 - Verify sha256 in manifest.json for changed ZIPs | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| # Collect changed ZIPs into a file that the next step can reuse | |
| : > changed_zips.txt | |
| while IFS= read -r -d '' f; do | |
| [[ "$f" == *.zip ]] && printf '%s\n' "$f" >> changed_zips.txt | |
| done < <(git diff --name-only -z "$BASE_SHA" "$HEAD_SHA") | |
| if [[ ! -s changed_zips.txt ]]; then | |
| echo "No .zip files changed in this PR. Nothing to verify." | |
| exit 0 | |
| fi | |
| echo "Changed ZIP files:" | |
| sed 's/^/ - /' changed_zips.txt | |
| while IFS= read -r zip_path; do | |
| # If deleted in PR head, skip (change if you want deletions to fail) | |
| if [[ ! -f "$zip_path" ]]; then | |
| echo "Skipping (not present in PR head): $zip_path" | |
| continue | |
| fi | |
| dir="$(dirname "$zip_path")" | |
| manifest_path="$dir/manifest.json" | |
| if [[ ! -f "$manifest_path" ]]; then | |
| echo "::error file=$manifest_path::manifest.json not found next to ZIP ($zip_path)" | |
| exit 1 | |
| fi | |
| # Compute checksum of the ZIP | |
| computed="$(sha256sum "$zip_path" | awk '{print $1}' | tr '[:upper:]' '[:lower:]')" | |
| # Read sha256 from manifest.json | |
| manifest_sha="$(jq -r '.sha256 // empty' "$manifest_path" | tr '[:upper:]' '[:lower:]')" | |
| if [[ -z "$manifest_sha" || "$manifest_sha" == "null" ]]; then | |
| echo "::error file=$manifest_path::Missing or empty \"sha256\" field in manifest.json" | |
| exit 1 | |
| fi | |
| echo "ZIP: $zip_path" | |
| echo "Computed: $computed" | |
| echo "Manifest: $manifest_sha" | |
| if [[ "$computed" != "$manifest_sha" ]]; then | |
| echo "::error file=$manifest_path::sha256 mismatch for $zip_path (computed=$computed, manifest=$manifest_sha)" | |
| exit 1 | |
| fi | |
| echo "SUCCESS - sha256 matches for $zip_path" | |
| done < changed_zips.txt | |
| - name: Step 2 - Unzip and verify root children are allowed | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| allowed=("impex" "app-configuration" "storefront-next" "cartridges") | |
| [[ -s changed_zips.txt ]] || exit 0 | |
| while IFS= read -r zip_path; do | |
| [[ -f "$zip_path" ]] || continue | |
| tmpdir="$(mktemp -d)" | |
| unzip -q "$zip_path" -d "$tmpdir" | |
| # Root should be exactly one directory (the wrapper folder) | |
| mapfile -t roots < <(find "$tmpdir" -mindepth 1 -maxdepth 1 -type d -printf '%f\n' | grep -v '^__MACOSX$' | sort -u) | |
| if [[ ${#roots[@]} -ne 1 ]]; then | |
| echo "::error file=$zip_path::Expected exactly 1 root directory after unzip, found ${#roots[@]}: ${roots[*]}" | |
| rm -rf "$tmpdir" | |
| exit 1 | |
| fi | |
| root="$tmpdir/${roots[0]}" | |
| # Check immediate child directories of root are allowed | |
| mapfile -t children < <(find "$root" -mindepth 1 -maxdepth 1 -type d -printf '%f\n' | grep -v '^__MACOSX$' | sort -u) | |
| for c in "${children[@]}"; do | |
| ok=false | |
| for a in "${allowed[@]}"; do | |
| [[ "$c" == "$a" ]] && ok=true && break | |
| done | |
| if [[ "$ok" == "false" ]]; then | |
| echo "::error file=$zip_path::Disallowed directory under root: \"$c\". Allowed: ${allowed[*]}" | |
| rm -rf "$tmpdir" | |
| exit 1 | |
| fi | |
| done | |
| rm -rf "$tmpdir" | |
| done < changed_zips.txt | |
| - name: Step 3 - Verify tax hooks exist and scripts resolve | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| required_hooks=( | |
| "dw.apps.checkout.tax.calculate" | |
| "dw.apps.checkout.tax.commit" | |
| "dw.apps.checkout.tax.cancel" | |
| ) | |
| [[ -s changed_zips.txt ]] || exit 0 | |
| while IFS= read -r zip_path; do | |
| [[ -f "$zip_path" ]] || continue | |
| tmpdir="$(mktemp -d)" | |
| trap 'rm -rf "$tmpdir"' RETURN | |
| unzip -q "$zip_path" -d "$tmpdir" | |
| # Root should be exactly one directory (wrapper) | |
| mapfile -t roots < <(find "$tmpdir" -mindepth 1 -maxdepth 1 -type d -printf '%f\n' | grep -v '^__MACOSX$' | sort -u) | |
| if [[ ${#roots[@]} -ne 1 ]]; then | |
| echo "::error file=$zip_path::Expected exactly 1 root directory after unzip, found ${#roots[@]}: ${roots[*]}" | |
| exit 1 | |
| fi | |
| root="$tmpdir/${roots[0]}" | |
| base="$root/cartridges/site_cartridges" | |
| if [[ ! -d "$base" ]]; then | |
| echo "::error file=$zip_path::Missing directory cartridges/site_cartridges in ZIP" | |
| exit 1 | |
| fi | |
| hooks_file="$(find "$base" -type f -name hooks.json -print -quit)" | |
| if [[ -z "$hooks_file" ]]; then | |
| echo "::error file=$zip_path::hooks.json not found under cartridges/site_cartridges" | |
| exit 1 | |
| fi | |
| hooks_dir="$(dirname "$hooks_file")" | |
| echo "ZIP: $zip_path" | |
| echo "hooks.json: $hooks_file" | |
| # Validate required hooks are present, and each has a script that exists | |
| for hook in "${required_hooks[@]}"; do | |
| script="$(jq -r --arg name "$hook" '.hooks[]? | select(.name == $name) | .script // empty' "$hooks_file" | head -n 1)" | |
| if [[ -z "$script" || "$script" == "null" ]]; then | |
| echo "::error file=$hooks_file::Missing hook or script for \"$hook\"" | |
| exit 1 | |
| fi | |
| # script is relative to hooks.json location (strip leading ./) | |
| rel="${script#./}" | |
| target="$hooks_dir/$rel" | |
| if [[ ! -f "$target" ]]; then | |
| echo "::error file=$hooks_file::Script for \"$hook\" points to missing file: $script (resolved: $target)" | |
| exit 1 | |
| fi | |
| done | |
| echo "SUCCESS - required tax hooks and scripts verified for $zip_path" | |
| rm -rf "$tmpdir" | |
| trap - RETURN | |
| done < changed_zips.txt |