mirror of
https://github.com/alexbelgium/hassio-addons.git
synced 2026-09-17 15:19:08 +02:00
chore: apply PR 2897 review fixes
This commit is contained in:
272
.github/workflows/pr2897_fix_review_comments.yml
vendored
Normal file
272
.github/workflows/pr2897_fix_review_comments.yml
vendored
Normal file
@@ -0,0 +1,272 @@
|
||||
# yamllint disable rule:line-length
|
||||
---
|
||||
name: Apply PR 2897 review fixes
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- agent/ai-issue-triage-fixes
|
||||
paths:
|
||||
- .github/workflows/pr2897_fix_review_comments.yml
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
apply:
|
||||
if: github.actor != 'github-actions[bot]'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout PR branch
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Apply reviewed fixes
|
||||
run: |
|
||||
set -euo pipefail
|
||||
python3 <<'PY'
|
||||
from pathlib import Path
|
||||
|
||||
def replace_exact(text: str, old: str, new: str, *, count: int = 1) -> str:
|
||||
actual = text.count(old)
|
||||
if actual < count:
|
||||
raise SystemExit(f"Expected at least {count} occurrence(s), found {actual}: {old[:80]!r}")
|
||||
return text.replace(old, new, count)
|
||||
|
||||
validator_path = Path('.github/scripts/validate_ai_patch.sh')
|
||||
validator = validator_path.read_text()
|
||||
validator = replace_exact(
|
||||
validator,
|
||||
'''}
|
||||
|
||||
mapfile -t changed_files < <(
|
||||
git diff --cached --name-only --diff-filter=ACMRDTUXB "$base_ref" -- |
|
||||
sed '/^$/d'
|
||||
)
|
||||
''',
|
||||
'''}
|
||||
|
||||
version_is_greater() {
|
||||
local old_version="$1"
|
||||
local new_version="$2"
|
||||
|
||||
ruby -e '\''
|
||||
require "rubygems"
|
||||
old_version = Gem::Version.new(ARGV.fetch(0))
|
||||
new_version = Gem::Version.new(ARGV.fetch(1))
|
||||
exit(new_version > old_version ? 0 : 1)
|
||||
'\'' "$old_version" "$new_version"
|
||||
}
|
||||
|
||||
mapfile -d '\''\0'\'' -t changed_files < <(
|
||||
git diff --cached --no-renames --name-only -z \\
|
||||
--diff-filter=ACMRDTUXB "$base_ref" --
|
||||
)
|
||||
''')
|
||||
validator = replace_exact(
|
||||
validator,
|
||||
'git diff --cached --numstat "$base_ref" -- |',
|
||||
'git diff --cached --no-renames --numstat "$base_ref" -- |')
|
||||
validator = replace_exact(
|
||||
validator,
|
||||
''' if ! printf '%s\\n' "${changed_files[@]}" | grep -Fxq "$addon/CHANGELOG.md"; then
|
||||
echo "Changed add-on '$addon' must update CHANGELOG.md." >&2
|
||||
exit 1
|
||||
fi
|
||||
''',
|
||||
''' changelog_changed=false
|
||||
for file in "${changed_files[@]}"; do
|
||||
if [[ "$file" == "$addon/CHANGELOG.md" ]]; then
|
||||
changelog_changed=true
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [[ "$changelog_changed" != true ]]; then
|
||||
echo "Changed add-on '$addon' must update CHANGELOG.md." >&2
|
||||
exit 1
|
||||
fi
|
||||
''')
|
||||
validator = replace_exact(
|
||||
validator,
|
||||
''' if [[ -z "$new_version" || "$old_version" == "$new_version" ]]; then
|
||||
echo "Changed add-on '$addon' must change its version value." >&2
|
||||
exit 1
|
||||
fi
|
||||
''',
|
||||
''' if [[ -z "$old_version" || -z "$new_version" ]]; then
|
||||
echo "Changed add-on '$addon' must have readable old and new version values." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! version_is_greater "$old_version" "$new_version"; then
|
||||
echo "Changed add-on '$addon' must increase its version value ($old_version -> $new_version)." >&2
|
||||
exit 1
|
||||
fi
|
||||
''')
|
||||
validator_path.write_text(validator)
|
||||
|
||||
workflow_path = Path('.github/workflows/on_issues_ai.yml')
|
||||
workflow = workflow_path.read_text()
|
||||
workflow = replace_exact(
|
||||
workflow,
|
||||
''' - name: Checkout repository
|
||||
uses: actions/checkout@v7
|
||||
''',
|
||||
''' - name: Checkout repository
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
persist-credentials: false
|
||||
''',
|
||||
count=2)
|
||||
workflow = replace_exact(
|
||||
workflow,
|
||||
''' category="$(jq -r '.category' "$RUNNER_TEMP/triage.json")"
|
||||
addon="$(jq -r '.addon // ""' "$RUNNER_TEMP/triage.json")"
|
||||
existing_addon=false
|
||||
if [[ -n "$addon" && "$addon" != */* && "$addon" != "." && "$addon" != ".." ]] &&
|
||||
[[ -f "$addon/config.yaml" || -f "$addon/config.json" ]]; then
|
||||
existing_addon=true
|
||||
fi
|
||||
|
||||
echo "addon=$addon" >> "$GITHUB_OUTPUT"
|
||||
echo "category=$category" >> "$GITHUB_OUTPUT"
|
||||
echo "confidence=$(jq -r '.confidence' "$RUNNER_TEMP/triage.json")" >> "$GITHUB_OUTPUT"
|
||||
echo "existing_addon=$existing_addon" >> "$GITHUB_OUTPUT"
|
||||
echo "risk=$(jq -r '.risk' "$RUNNER_TEMP/triage.json")" >> "$GITHUB_OUTPUT"
|
||||
''',
|
||||
''' category="$(jq -r '.category' "$RUNNER_TEMP/triage.json")"
|
||||
addon="$(jq -r '.addon // ""' "$RUNNER_TEMP/triage.json")"
|
||||
confidence="$(jq -r '.confidence' "$RUNNER_TEMP/triage.json")"
|
||||
risk="$(jq -r '.risk' "$RUNNER_TEMP/triage.json")"
|
||||
|
||||
case "$category" in
|
||||
question | missing_information | bug | improvement | new_addon_request | unsupported | spam) ;;
|
||||
*) echo "Invalid triage category: $category" >&2; exit 1 ;;
|
||||
esac
|
||||
case "$risk" in
|
||||
low | medium | high) ;;
|
||||
*) echo "Invalid triage risk: $risk" >&2; exit 1 ;;
|
||||
esac
|
||||
|
||||
existing_addon=false
|
||||
if [[ -n "$addon" ]] &&
|
||||
jq -e --arg addon "$addon" 'index($addon) != null' <<< "$addon_catalog" > /dev/null; then
|
||||
existing_addon=true
|
||||
else
|
||||
addon=""
|
||||
fi
|
||||
|
||||
write_output() {
|
||||
local name="$1"
|
||||
local value="$2"
|
||||
if [[ "$value" == *$'\\n'* || "$value" == *$'\\r'* ]]; then
|
||||
echo "Refusing multiline GitHub output '$name'." >&2
|
||||
exit 1
|
||||
fi
|
||||
printf '%s=%s\\n' "$name" "$value" >> "$GITHUB_OUTPUT"
|
||||
}
|
||||
|
||||
write_output addon "$addon"
|
||||
write_output category "$category"
|
||||
write_output confidence "$confidence"
|
||||
write_output existing_addon "$existing_addon"
|
||||
write_output risk "$risk"
|
||||
''')
|
||||
workflow = replace_exact(workflow, ' allow-users: "*"\n', '')
|
||||
workflow_path.write_text(workflow)
|
||||
|
||||
readme_path = Path('.github/ai/README.md')
|
||||
readme = readme_path.read_text()
|
||||
readme = replace_exact(
|
||||
readme,
|
||||
'''The validator independently rejects new top-level add-on directories and Codex
|
||||
never merges pull requests.
|
||||
''',
|
||||
'''The validator independently rejects new top-level add-on directories and Codex
|
||||
never merges pull requests. The Codex Action keeps its default authorization, so only
|
||||
users with repository write access can trigger its execution; external issue authors
|
||||
cannot run it merely by opening an issue.
|
||||
''')
|
||||
readme_path.write_text(readme)
|
||||
PY
|
||||
|
||||
- name: Validate scripts and workflow
|
||||
run: |
|
||||
set -euo pipefail
|
||||
bash -n .github/scripts/validate_ai_patch.sh
|
||||
jq empty .github/ai/triage-schema.json
|
||||
ruby -e 'require "yaml"; YAML.safe_load(File.read(ARGV.fetch(0)), aliases: true)' .github/workflows/on_issues_ai.yml
|
||||
ruby <<'RUBY'
|
||||
require "yaml"
|
||||
workflow = YAML.safe_load(File.read('.github/workflows/on_issues_ai.yml'), aliases: true)
|
||||
workflow.fetch('jobs').each do |job_name, job|
|
||||
job.fetch('steps', []).each_with_index do |step, index|
|
||||
next unless step['run']
|
||||
path = "/tmp/#{job_name}-#{index}.sh"
|
||||
File.write(path, step['run'])
|
||||
abort "bash syntax failed for #{job_name} step #{index}" unless system('bash', '-n', path)
|
||||
end
|
||||
end
|
||||
RUBY
|
||||
|
||||
- name: Test validator security cases
|
||||
run: |
|
||||
set -euo pipefail
|
||||
work="$RUNNER_TEMP/validator-tests"
|
||||
mkdir -p "$work"
|
||||
cp .github/scripts/validate_ai_patch.sh "$work/validator.sh"
|
||||
cd "$work"
|
||||
git init -q
|
||||
git config user.name test
|
||||
git config user.email test@example.com
|
||||
mkdir -p .github/ai addon
|
||||
printf 'protected\n' > .github/ai/README.md
|
||||
printf 'version: 1.2.0\n' > addon/config.yaml
|
||||
printf '# Changelog\n' > addon/CHANGELOG.md
|
||||
printf '#!/bin/sh\necho old\n' > addon/file.sh
|
||||
git add -A
|
||||
git commit -qm base
|
||||
base=HEAD
|
||||
|
||||
printf '#!/bin/sh\necho new\n' > addon/file.sh
|
||||
printf '# Changelog\n- change\n' > addon/CHANGELOG.md
|
||||
printf 'version: 1.2.1\n' > addon/config.yaml
|
||||
git add -A
|
||||
AI_REQUEST_CATEGORY=bug bash ./validator.sh "$base" > /dev/null
|
||||
git reset --hard -q HEAD
|
||||
|
||||
printf '#!/bin/sh\necho new\n' > addon/file.sh
|
||||
printf '# Changelog\n- change\n' > addon/CHANGELOG.md
|
||||
printf 'version: 1.1.9\n' > addon/config.yaml
|
||||
git add -A
|
||||
! AI_REQUEST_CATEGORY=bug bash ./validator.sh "$base" > downgrade.log 2>&1
|
||||
grep -q 'must increase' downgrade.log
|
||||
git reset --hard -q HEAD
|
||||
|
||||
git mv .github/ai/README.md addon/AI_README.md
|
||||
printf '# Changelog\n- change\n' > addon/CHANGELOG.md
|
||||
printf 'version: 1.2.1\n' > addon/config.yaml
|
||||
git add -A
|
||||
! AI_REQUEST_CATEGORY=bug bash ./validator.sh "$base" > rename.log 2>&1
|
||||
grep -q 'Disallowed path changed by AI: .github/ai/README.md' rename.log
|
||||
git reset --hard -q HEAD
|
||||
|
||||
bad=$'.github/bad\nname'
|
||||
printf 'x\n' > "$bad"
|
||||
git add -A
|
||||
! AI_REQUEST_CATEGORY=bug bash ./validator.sh "$base" > newline.log 2>&1
|
||||
grep -q 'Disallowed path changed by AI: .github/bad' newline.log
|
||||
|
||||
- name: Commit fixes and remove helper
|
||||
run: |
|
||||
set -euo pipefail
|
||||
rm -f .github/workflows/pr2897_fix_review_comments.yml
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||
git add .github/ai/README.md \
|
||||
.github/scripts/validate_ai_patch.sh \
|
||||
.github/workflows/on_issues_ai.yml \
|
||||
.github/workflows/pr2897_fix_review_comments.yml
|
||||
git commit -m "fix: address AI workflow review findings"
|
||||
git push origin HEAD:agent/ai-issue-triage-fixes
|
||||
Reference in New Issue
Block a user