Skip to content

feat(rules): add direct domain panjue.com by Rule-Bot (from Rule-Bot … #476

feat(rules): add direct domain panjue.com by Rule-Bot (from Rule-Bot …

feat(rules): add direct domain panjue.com by Rule-Bot (from Rule-Bot … #476

name: Auto generate rules
on:
workflow_call:
inputs:
source_before_sha:
description: Source-list parent revision supplied by an updater workflow
required: false
type: string
push:
branches:
- main
paths:
- 'rule/Custom_Direct.list'
- 'rule/Custom_Proxy.list'
- 'rule/Steam_CDN.list'
- 'rule/Encrypted_DNS.list'
- 'rule/Game_Download_CDN.list'
- 'rule/game_rule/**/*.list'
- 'py/generate_rules.py'
- 'py/generate_stash_configs.py'
- 'cfg/Custom_Clash.ini'
- 'cfg/Custom_Clash_Fallback.ini'
- 'cfg/Custom_Clash_Lite.ini'
- 'cfg/Custom_Clash_Lite_Fallback.ini'
- 'cfg/Custom_Clash_GFW.ini'
- 'cfg/Custom_Clash_GFW_Fallback.ini'
- 'cfg/Custom_Clash_Full.ini'
- 'cfg/Custom_Clash_Full_Fallback.ini'
workflow_dispatch:
inputs:
source_before_sha:
description: Source-list parent revision supplied by an updater workflow
required: false
type: string
permissions:
contents: write
# All workflows that commit to main share this queue to avoid push races.
concurrency:
group: main-writers
jobs:
generate-rules:
runs-on: ubuntu-latest
timeout-minutes: 15
outputs:
purge_base_sha: ${{ steps.publication-range.outputs.purge_base_sha }}
publication_sha: ${{ steps.publish.outputs.publication_sha }}
steps:
- name: Checkout latest main branch
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
ref: main
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: '3.13'
- name: Record source publication range
id: publication-range
env:
EVENT_NAME: ${{ github.event_name }}
EVENT_BEFORE: ${{ github.event.before }}
REQUEST_BEFORE: ${{ inputs.source_before_sha }}
run: |
if [ "$EVENT_NAME" = "push" ]; then
purge_base_sha="$EVENT_BEFORE"
else
purge_base_sha="$REQUEST_BEFORE"
fi
if [ -z "$purge_base_sha" ]; then
purge_base_sha="$(git rev-parse HEAD^)"
elif [ "${purge_base_sha//0/}" != "" ]; then
purge_base_sha="$(git rev-parse "${purge_base_sha}^{commit}")"
fi
echo "Source publication base: $purge_base_sha"
echo "purge_base_sha=$purge_base_sha" >> "$GITHUB_OUTPUT"
- name: Set up pinned Mihomo
uses: ./.github/actions/setup-mihomo
- name: Generate derived rules and Stash templates
run: |
python py/generate_rules.py --mihomo mihomo
python py/generate_stash_configs.py
- name: Test generation and conversion logic
run: |
python py/generate_rules.py --check --mihomo mihomo
python py/generate_stash_configs.py --check
- name: Commit and push changes
id: publish
shell: bash
run: |
set -euo pipefail
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
generated_pathspecs=(
':(glob)rule/*.yaml'
':(glob)rule/*.mrs'
':(glob)rule/game_rule/**/*.yaml'
':(glob)rule/game_rule/**/*.mrs'
'cfg/Custom_Clash_Mainland.ini'
':(glob)cfg/Custom_Stash*.ini'
)
generated_excludes=(
':(exclude,glob)rule/*.yaml'
':(exclude,glob)rule/*.mrs'
':(exclude,glob)rule/game_rule/**/*.yaml'
':(exclude,glob)rule/game_rule/**/*.mrs'
':(exclude)cfg/Custom_Clash_Mainland.ini'
':(exclude,glob)cfg/Custom_Stash*.ini'
)
remote_main_sha() {
git ls-remote --exit-code origin refs/heads/main |
awk 'NR == 1 { print $1 }'
}
publication_sha=""
for attempt in 1 2 3; do
echo "Generation and publication attempt ${attempt}/3"
git fetch --no-tags origin main
git reset --hard origin/main
python py/generate_rules.py --mihomo mihomo
python py/generate_rules.py --check --mihomo mihomo
python py/generate_stash_configs.py
python py/generate_stash_configs.py --check
unexpected_changes="$(
git status --short --untracked-files=all -- . \
"${generated_excludes[@]}"
)"
if [ -n "$unexpected_changes" ]; then
echo "Generator modified files outside the derived-rule allowlist:" >&2
printf '%s\n' "$unexpected_changes" >&2
exit 1
fi
base_sha="$(git rev-parse HEAD)"
git add -A -- "${generated_pathspecs[@]}"
if git diff --cached --quiet; then
remote_sha="$(remote_main_sha)"
if [ "$remote_sha" = "$base_sha" ]; then
echo "No generated rule changes, skip commit and push."
publication_sha="$base_sha"
break
fi
echo "main advanced before the no-op result was confirmed; retrying."
continue
fi
git commit -m "chore(rules): auto generate derived rule files"
candidate_sha="$(git rev-parse HEAD)"
if git push origin HEAD:main; then
remote_sha="$(remote_main_sha)"
if [ "$remote_sha" = "$candidate_sha" ]; then
publication_sha="$candidate_sha"
break
fi
echo "main advanced after publication; regenerating from its new head."
continue
fi
remote_sha="$(remote_main_sha)"
if [ "$remote_sha" = "$base_sha" ]; then
echo "Push failed without a competing main update; refusing to hide the error." >&2
exit 1
fi
echo "Push raced with a newer main revision; regenerating and retrying."
done
if [ -z "$publication_sha" ]; then
echo "Could not publish derived rules after 3 attempts." >&2
exit 1
fi
echo "Final revision to publish: $publication_sha"
echo "publication_sha=$publication_sha" >> "$GITHUB_OUTPUT"
# Generation and format validation already ran against the exact worktree that
# was published. Purge its changed cache keys without re-running unrelated tests.
purge-generated:
needs: generate-rules
permissions:
contents: read
uses: ./.github/workflows/purge-jsdelivr.yml
secrets: inherit
with:
before_sha: ${{ needs.generate-rules.outputs.purge_base_sha }}
after_sha: ${{ needs.generate-rules.outputs.publication_sha }}
generation_complete: true