diff --git a/.github/scripts/check-path-length.sh b/.github/scripts/check-path-length.sh new file mode 100755 index 0000000..cafef96 --- /dev/null +++ b/.github/scripts/check-path-length.sh @@ -0,0 +1,52 @@ +#!/usr/bin/env bash +# Fails when a file path in the gallery is too long to be installed on Windows. +# +# The product stores the gallery under +# C:\ProgramData\inray\OPC Router 5\config\solution-gallery\\ +# where is 8 characters (24 in versions before tp#354132), so up to +# 83 characters precede every path of this repository. Windows limits a full +# path to 259 characters (MAX_PATH 260 including the terminating NUL). That +# leaves 176 characters. The default limit keeps a small safety margin. +set -euo pipefail + +export LC_ALL=C.UTF-8 + +# Allow the default safety margin to be adjusted through an environment variable. +limit="${MAX_SOLUTION_PATH_LENGTH:-170}" +failed=0 +longest=0 + +# Measure paths from the repository root, regardless of where this script is run. +cd "$(git rev-parse --show-toplevel)" + +# Read the NUL-delimited paths emitted by find -print0: +# IFS= preserves leading and trailing whitespace. +# -r treats backslashes literally. +# -d '' uses NUL as the delimiter, allowing newlines within filenames. +# Process substitution (< <(...)) keeps the loop in this shell so updates to +# failed and longest remain available after the loop. +while IFS= read -r -d '' file; do + # Exclude find's leading ./ from the repository-relative path length. + rel="${file#./}" + len=${#rel} + + if (( len > longest )); then + longest=$len + fi + + if (( len > limit )); then + # Emit a GitHub Actions error annotation, then keep checking the other files. + echo "::error file=${rel}::Path is ${len} characters long (limit ${limit}). Shorten the Solution, Flow or parameter names so the Solution can be installed on Windows." + failed=1 + fi +done < <( + # Exclude repository metadata, CI configuration, and image assets. + find . -type f \ + -not -path './.git/*' \ + -not -path './.github/*' \ + -not -path './img/*' \ + -print0 +) + +echo "Longest path: ${longest} characters (limit ${limit})." +exit $failed diff --git a/.github/workflows/check path length.yml b/.github/workflows/check path length.yml new file mode 100644 index 0000000..2b6665e --- /dev/null +++ b/.github/workflows/check path length.yml @@ -0,0 +1,22 @@ +name: Check path length + +on: + pull_request: + push: + branches: + - main + workflow_dispatch: + +permissions: + contents: read + +jobs: + check-path-length: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Check that all paths fit the Windows path length limit + run: bash .github/scripts/check-path-length.sh diff --git a/.github/workflows/create release.yml b/.github/workflows/create release.yml index 6c0be9c..0b90ddb 100644 --- a/.github/workflows/create release.yml +++ b/.github/workflows/create release.yml @@ -20,6 +20,9 @@ jobs: with: ref: main + - name: Check that all paths fit the Windows path length limit + run: bash .github/scripts/check-path-length.sh + - name: Create ZIP without .git and .github run: | zip -r solutions.zip . \ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ea945ad..b89fdb4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -38,6 +38,7 @@ A guide on how to create your own Solutions can be found in the [documentation]( - The **configuration files must be located in a `config` subdirectory**, mirroring the structure used by the products - For reference you can take a look at the Solutions in this Repository - Each Solution must include a `solution.yaml` file +- File paths from the repository root (for example, `My Solution/config/versioned/...`) must be **170 characters or fewer**. Longer paths cannot be installed because Solutions are deployed under a deep Windows directory. CI enforces this limit. ### Metadata and Parameter Requirements