Skip to content
124 changes: 113 additions & 11 deletions .github/actions/check-control/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,75 @@ runs:
using: composite
steps:
- id: output_sha
if: ${{ !cancelled() }}
if: ${{ (github.repository == 'reactive-firewall-org/multicast') && !cancelled() }}
env:
CI_INPUT_TARGET_SHA: '${{ inputs.sha }}'
shell: bash
run: printf "sha=%s\n" $(git rev-parse --verify '${{ inputs.sha }}') >> "$GITHUB_OUTPUT"
run: |
set -euo pipefail

raw_input="${CI_INPUT_TARGET_SHA}"

# Reject NUL or newline immediately
if printf '%s' "$raw_input" | grep -q '[^[:print:]]'; then
printf "::error title='Invalid':: %s\n" "Error: input contains disallowed control characters" >&2
exit 1
fi

# Strip one level of surrounding quotes and trim whitespace
normalize() {
local s="$1"
s="${s#"${s%%[![:space:]]*}"}"
s="${s%"${s##*[![:space:]]}"}"
if [[ (${s:0:1} == "'" && ${s: -1} == "'") || (${s:0:1} == '"' && ${s: -1} == '"') ]]; then
s="${s:1:-1}"
fi
printf '%s' "$s"
}
input="$(normalize "$raw_input")"

# Reject inputs starting with '-' (options)
if [[ "${input:0:1}" == "-" ]]; then
printf "::error title='Invalid':: %s\n" "Error: input may not start with '-'" >&2
exit 1
fi

# If it's a 40-char SHA, accept directly
if [[ "$input" =~ ^[0-9a-f]{40}$ ]]; then
resolved_sha="$input"
else
# Try explicit namespaces in order: full refs, refs/heads/, refs/tags/, then bare branch/tag
resolved_sha=""
# 1) If input is a full ref path starting with refs/, resolve only that
if [[ "$input" == refs/* ]]; then
if git rev-parse --verify "$input" >/dev/null 2>&1; then
resolved_sha="$(git rev-parse --verify "$input")"
else
printf "::error title='Invalid':: %s\n" "Error: ref not found: $input" >&2
exit 1
fi
else
# 2) Try refs/heads/<input>
if git rev-parse --verify "refs/heads/$input" >/dev/null 2>&1; then
resolved_sha="$(git rev-parse --verify "refs/heads/$input")"
# 3) Try refs/tags/<input>
elif git rev-parse --verify "refs/tags/$input" >/dev/null 2>&1; then
resolved_sha="$(git rev-parse --verify "refs/tags/$input")"
else
printf "::error title='Invalid':: %s\n" "Error: no matching branch or tag found for: $input" >&2
exit 1
fi
fi
fi

# Ensure final resolved value is a full 40-char commit SHA
if [[ ! "$resolved_sha" =~ ^[0-9a-f]{40}$ ]]; then
printf "::error title='Invalid':: %s\n" "Error: resolved value is not a full commit SHA" >&2
exit 1
fi

printf "sha=%s\n" "$resolved_sha" >> "$GITHUB_OUTPUT"

- id: output_uuid
if: ${{ !cancelled() && (inputs.check-id == '') }}
shell: bash
Expand Down Expand Up @@ -152,16 +218,25 @@ runs:
env:
GH_TOKEN: ${{ inputs.token }}
run: |
printf "%s\n" "::group::validate-name"
name_input='${{ inputs.name }}'
printf "::debug:: %s\n" "Will use name $name_input" ;
printf "%s\n" "::endgroup::"
printf "%s\n" "::group::validate-title"
title_input='${{ inputs.name }}'
printf "::debug:: %s\n" "Will use name $title_input" ;
sanitized_input_title_field=$(printf "%s%s" 'output[title]=' "$title_input" ;)
printf "%s\n" "::endgroup::"
printf "%s\n" "::group::create-new-check"
# GitHub CLI api
# https://cli.github.com/manual/gh_api
CHECK_ID=$(gh api --method POST -H "Accept: application/vnd.github+json" \
/repos/reactive-firewall-org/multicast/check-runs \
-f "name=${{ inputs.name }}" -f "head_sha=${{ steps.output_sha.outputs.sha }}" \
-f "status=${{ inputs.status }}" -f "external_id=${{ steps.output_uuid.outputs.uuid }}" \
-f "name=$name_input" -f "head_sha=${{ steps.output_sha.outputs.sha }}" \
-f 'status=${{ inputs.status }}' -f "external_id=${{ steps.output_uuid.outputs.uuid }}" \
-f "started_at=${{ steps.output_date.outputs.check_date }}Z" \
-f "details_url=${{ steps.output_check_details_url.outputs.details_url }}" \
-f 'output[title]=${{ inputs.title }}' \
-f "$sanitized_input_title_field" \
-f 'output[summary]=' -f 'output[text]=' --jq '.id');
printf "check_id=%s\n" "${CHECK_ID}" >> "$GITHUB_OUTPUT"
printf "%s\n" "::endgroup::"
Expand All @@ -172,16 +247,25 @@ runs:
env:
GH_TOKEN: ${{ inputs.token }}
run: |
printf "%s\n" "::group::validate-name"
name_input='${{ inputs.name }}'
printf "::debug:: %s\n" "Will use name $name_input" ;
printf "%s\n" "::endgroup::"
printf "%s\n" "::group::validate-title"
title_input='${{ inputs.name }}'
printf "::debug:: %s\n" "Will use name $title_input" ;
sanitized_input_title_field=$(printf "%s%s" 'output[title]=' "$title_input" ;)
printf "%s\n" "::endgroup::"
printf "%s\n" "::group::update-new-check"
# GitHub CLI api
# https://cli.github.com/manual/gh_api
CHECK_ID=$(gh api --method POST -H "Accept: application/vnd.github+json" \
/repos/reactive-firewall-org/multicast/check-runs \
-f "name=${{ inputs.name }}" -f "head_sha=${{ steps.output_sha.outputs.sha }}" \
-f "name=$input_name" -f "head_sha=${{ steps.output_sha.outputs.sha }}" \
-f "status=in_progress" -f "external_id=${{ steps.output_uuid.outputs.uuid }}" \
-f "started_at=${{ steps.output_date.outputs.check_date }}Z" \
-f "details_url=${{ steps.output_check_details_url.outputs.details_url }}" \
-f 'output[title]=${{ inputs.title }}' \
-f "$sanitized_input_title_field" \
-f 'output[summary]=Check is in progress.' -f 'output[text]=' --jq '.id');
printf "check_id=%s\n" "${CHECK_ID}" >> "$GITHUB_OUTPUT"
printf "%s\n" "::endgroup::"
Expand Down Expand Up @@ -216,15 +300,24 @@ runs:
env:
GH_TOKEN: ${{ inputs.token }}
run: |
printf "%s\n" "::group::validate-name"
name_input='${{ inputs.name }}'
printf "::debug:: %s\n" "Will use name $name_input" ;
printf "%s\n" "::endgroup::"
printf "%s\n" "::group::validate-title"
title_input='${{ inputs.name }}'
printf "::debug:: %s\n" "Will use name $title_input" ;
sanitized_input_title_field=$(printf "%s%s" 'output[title]=' "$title_input" ;)
printf "%s\n" "::endgroup::"
printf "%s\n" "::group::update-check"
# GitHub CLI api
# https://cli.github.com/manual/gh_api
gh api --method PATCH -H "Accept: application/vnd.github+json" \
/repos/reactive-firewall-org/multicast/check-runs/${{ steps.output_check_id.outputs.check_id }} \
-f "name=${{ inputs.name }}" -f "head_sha=${{ steps.output_sha.outputs.sha }}" \
-f "name=$input_name" -f "head_sha=${{ steps.output_sha.outputs.sha }}" \
-f "status=${{ inputs.status }}" \
-f "details_url=${{ steps.output_check_details_url.outputs.details_url }}" \
-f 'output[title]=${{ inputs.title }}' \
-f "$sanitized_input_title_field" \
-f 'output[summary]=${{ inputs.summary }}' -f 'output[text]=${{ inputs.text }}'
printf "%s\n" "::endgroup::"
- name: "Update Check"
Expand All @@ -234,16 +327,25 @@ runs:
env:
GH_TOKEN: ${{ inputs.token }}
run: |
printf "%s\n" "::group::validate-name"
name_input='${{ inputs.name }}'
printf "::debug:: %s\n" "Will use name $name_input" ;
printf "%s\n" "::endgroup::"
printf "%s\n" "::group::validate-title"
title_input='${{ inputs.name }}'
printf "::debug:: %s\n" "Will use name $title_input" ;
sanitized_input_title_field=$(printf "%s%s" 'output[title]=' "$title_input" ;)
printf "%s\n" "::endgroup::"
printf "%s\n" "::group::complete-check"
# GitHub CLI api
# https://cli.github.com/manual/gh_api
gh api --method PATCH -H "Accept: application/vnd.github+json" \
/repos/reactive-firewall-org/multicast/check-runs/${{ steps.output_check_id.outputs.check_id }} \
-f "name=${{ inputs.name }}" -f "head_sha=${{ steps.output_sha.outputs.sha }}" \
-f "name=$input_name" -f "head_sha=${{ steps.output_sha.outputs.sha }}" \
-f "status=completed" -f "conclusion=${{ inputs.conclusion }}" \
-f "completed_at=${{ steps.output_date.outputs.check_date }}Z" \
-f "details_url=${{ steps.output_check_details_url.outputs.details_url }}" \
-f 'output[title]=${{ inputs.title }}' \
-f "$sanitized_input_title_field" \
-f 'output[summary]=${{ inputs.summary }}' -f 'output[text]=${{ inputs.text }}'
printf "%s\n" "::endgroup::"
- name: "Report outcome of checks API"
Expand Down
4 changes: 3 additions & 1 deletion .github/actions/checkout-and-rebuild/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,11 @@ runs:
token: ${{ inputs.token }}
- name: "Checkout Target Commit by SHA"
shell: bash
env:
CI_INPUT_TARGET_SHA: ${{ inputs.sha }}
run: |
printf "%s\n" "::group::target-commit"
git checkout --force --detach ${{ inputs.sha }} --
git checkout --force --detach "${CI_INPUT_TARGET_SHA}" --
printf "%s\n" "::endgroup::"
if: ${{ (github.sha != inputs.sha) && success() }}
- id: output_branch_name
Expand Down
69 changes: 67 additions & 2 deletions .github/actions/run-minimal-acceptance-tests/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,75 @@ runs:
steps:
- name: "Calculate Commit SHA"
id: output_sha
if: ${{ !cancelled() }}
env:
CI_INPUT_TARGET_SHA: '${{ inputs.sha }}'
shell: bash
run: |
printf "sha=%s\n" $(git rev-parse --verify '${{ inputs.sha }}') >> "$GITHUB_OUTPUT"
printf "BUILD_SHA=%s\n" $(git rev-parse --verify '${{ inputs.sha }}') >> "$GITHUB_ENV"
set -euo pipefail

raw_input="${CI_INPUT_TARGET_SHA}"

# Reject NUL or newline immediately
if printf '%s' "$raw_input" | grep -q '[^[:print:]]'; then
printf "::error title='Invalid':: %s\n" "Error: input contains disallowed control characters" >&2
exit 1
fi

# Strip one level of surrounding quotes and trim whitespace
normalize() {
local s="$1"
s="${s#"${s%%[![:space:]]*}"}"
s="${s%"${s##*[![:space:]]}"}"
if [[ (${s:0:1} == "'" && ${s: -1} == "'") || (${s:0:1} == '"' && ${s: -1} == '"') ]]; then
s="${s:1:-1}"
fi
printf '%s' "$s"
}
input="$(normalize "$raw_input")"

# Reject inputs starting with '-' (options)
if [[ "${input:0:1}" == "-" ]]; then
printf "::error title='Invalid':: %s\n" "Error: input may not start with '-'" >&2
exit 1
fi

# If it's a 40-char SHA, accept directly
if [[ "$input" =~ ^[0-9a-f]{40}$ ]]; then
resolved_sha="$input"
else
# Try explicit namespaces in order: full refs, refs/heads/, refs/tags/, then bare branch/tag
resolved_sha=""
# 1) If input is a full ref path starting with refs/, resolve only that
if [[ "$input" == refs/* ]]; then
if git rev-parse --verify "$input" >/dev/null 2>&1; then
resolved_sha="$(git rev-parse --verify "$input")"
else
printf "::error title='Invalid':: %s\n" "Error: ref not found: $input" >&2
exit 1
fi
else
# 2) Try refs/heads/<input>
if git rev-parse --verify "refs/heads/$input" >/dev/null 2>&1; then
resolved_sha="$(git rev-parse --verify "refs/heads/$input")"
# 3) Try refs/tags/<input>
elif git rev-parse --verify "refs/tags/$input" >/dev/null 2>&1; then
resolved_sha="$(git rev-parse --verify "refs/tags/$input")"
else
printf "::error title='Invalid':: %s\n" "Error: no matching branch or tag found for: $input" >&2
exit 1
fi
fi
fi

# Ensure final resolved value is a full 40-char commit SHA
if [[ ! "$resolved_sha" =~ ^[0-9a-f]{40}$ ]]; then
printf "::error title='Invalid':: %s\n" "Error: resolved value is not a full commit SHA" >&2
exit 1
fi

printf "sha=%s\n" "$resolved_sha" >> "$GITHUB_OUTPUT"
printf "BUILD_SHA=%s\n" "$resolved_sha" >> "$GITHUB_ENV" ;
- name: "Setup Python"
id: output_python
if: ${{ !cancelled() }}
Expand Down
69 changes: 67 additions & 2 deletions .github/actions/setup-py-reqs/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,75 @@ runs:
steps:
- name: "Calculate Commit SHA"
id: output_sha
if: ${{ !cancelled() }}
env:
CI_INPUT_TARGET_SHA: '${{ inputs.sha }}'
shell: bash
run: |
printf "sha=%s\n" $(git rev-parse --verify '${{ inputs.sha }}') >> "$GITHUB_OUTPUT"
printf "BUILD_SHA=%s\n" $(git rev-parse --verify '${{ inputs.sha }}') >> "$GITHUB_ENV"
set -euo pipefail

raw_input="${CI_INPUT_TARGET_SHA}"

# Reject NUL or newline immediately
if printf '%s' "$raw_input" | grep -q '[^[:print:]]'; then
printf "::error title='Invalid':: %s\n" "Error: input contains disallowed control characters" >&2
exit 1
fi

# Strip one level of surrounding quotes and trim whitespace
normalize() {
local s="$1"
s="${s#"${s%%[![:space:]]*}"}"
s="${s%"${s##*[![:space:]]}"}"
if [[ (${s:0:1} == "'" && ${s: -1} == "'") || (${s:0:1} == '"' && ${s: -1} == '"') ]]; then
s="${s:1:-1}"
fi
printf '%s' "$s"
}
input="$(normalize "$raw_input")"

# Reject inputs starting with '-' (options)
if [[ "${input:0:1}" == "-" ]]; then
printf "::error title='Invalid':: %s\n" "Error: input may not start with '-'" >&2
exit 1
fi

# If it's a 40-char SHA, accept directly
if [[ "$input" =~ ^[0-9a-f]{40}$ ]]; then
resolved_sha="$input"
else
# Try explicit namespaces in order: full refs, refs/heads/, refs/tags/, then bare branch/tag
resolved_sha=""
# 1) If input is a full ref path starting with refs/, resolve only that
if [[ "$input" == refs/* ]]; then
if git rev-parse --verify "$input" >/dev/null 2>&1; then
resolved_sha="$(git rev-parse --verify "$input")"
else
printf "::error title='Invalid':: %s\n" "Error: ref not found: $input" >&2
exit 1
fi
else
# 2) Try refs/heads/<input>
if git rev-parse --verify "refs/heads/$input" >/dev/null 2>&1; then
resolved_sha="$(git rev-parse --verify "refs/heads/$input")"
# 3) Try refs/tags/<input>
elif git rev-parse --verify "refs/tags/$input" >/dev/null 2>&1; then
resolved_sha="$(git rev-parse --verify "refs/tags/$input")"
else
printf "::error title='Invalid':: %s\n" "Error: no matching branch or tag found for: $input" >&2
exit 1
fi
fi
fi

# Ensure final resolved value is a full 40-char commit SHA
if [[ ! "$resolved_sha" =~ ^[0-9a-f]{40}$ ]]; then
printf "::error title='Invalid':: %s\n" "Error: resolved value is not a full commit SHA" >&2
exit 1
fi

printf "sha=%s\n" "$resolved_sha" >> "$GITHUB_OUTPUT"
printf "BUILD_SHA=%s\n" "$resolved_sha" >> "$GITHUB_ENV" ;
- name: "Setup Python"
id: output_python
if: ${{ !cancelled() }}
Expand Down
6 changes: 4 additions & 2 deletions .github/actions/test-reporter-upload/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -345,11 +345,13 @@ runs:
env:
COVERALLS_REPO_TOKEN: ${{ github.server_url == 'https://github.com' && inputs.coveralls-token || '' }}
COVERALLS_TOOL: ${{ steps.output_upload_tools.outputs.coveralls_executable }}
COVERALLS_SERVICE_JOB_ID: ${{ github.run_id }}
COVERALLS_SERVICE_JOB_NUMBER: ${{ inputs.job_code }}
run: |
if [[ "${{ inputs.tests-outcome }}" == "success" ]] ; then
${COVERALLS_TOOL} report ${COV_CORE_DATAFILE:-./coverage.xml} --base-path="${{ github.workspace }}" --service-job-id=${{ github.run_id }} --parallel --job-flag='${{ steps.output_os.outputs.os }}-${{ steps.output_python.outputs.python-version }}' --build-number=${{ inputs.job_code }} || exit 1 ;
${COVERALLS_TOOL} report ${COV_CORE_DATAFILE:-./coverage.xml} --base-path="${{ github.workspace }}" --service-job-id=${COVERALLS_SERVICE_JOB_ID} --parallel --job-flag='${{ steps.output_os.outputs.os }}-${{ steps.output_python.outputs.python-version }}' --build-number=${COVERALLS_SERVICE_JOB_NUMBER} || exit 1 ;
else
${COVERALLS_TOOL} report ${COV_CORE_DATAFILE:-./coverage.xml} --base-path="${{ github.workspace }}" --allow-empty --service-job-id=${{ github.run_id }} --parallel --job-flag='${{ steps.output_os.outputs.os }}-${{ steps.output_python.outputs.python-version }}' --build-number=${{ inputs.job_code }} || exit 1 ;
${COVERALLS_TOOL} report ${COV_CORE_DATAFILE:-./coverage.xml} --base-path="${{ github.workspace }}" --allow-empty --service-job-id=${COVERALLS_SERVICE_JOB_ID} --parallel --job-flag='${{ steps.output_os.outputs.os }}-${{ steps.output_python.outputs.python-version }}' --build-number=${COVERALLS_SERVICE_JOB_NUMBER} || exit 1 ;
fi
- name: "Evaluate Coverage Report Task"
id: coverage_outcome
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/CI-CHGLOG.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ jobs:
echo "should_run=true" >> "$GITHUB_OUTPUT"
else
echo "should_run=false" >> "$GITHUB_OUTPUT"
exit 1 ;
fi
- id: get_trigger_id
if: ${{ (steps.check.outputs.should_run == 'true') && success() }}
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/CI-DOCS.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ jobs:
echo "should_run=true" >> "$GITHUB_OUTPUT"
else
echo "should_run=false" >> "$GITHUB_OUTPUT"
exit 1 ;
fi
- id: get_trigger_id
if: ${{ (steps.check.outputs.should_run == 'true') && success() }}
Expand Down
Loading
Loading