Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 3 additions & 7 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,15 @@ updates:
directory: /
target-branch: main
schedule:
interval: monthly
open-pull-requests-limit: 1
interval: weekly
open-pull-requests-limit: 5
groups:
github-actions:
github-actions-minor-patch:
patterns:
- '*'
update-types:
- minor
- patch
ignore:
- dependency-name: '*'
update-types:
- version-update:semver-major
commit-message:
prefix: deps(actions)
rebase-strategy: auto
36 changes: 36 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,44 @@ jobs:
cat .output/upstream-summary.json
fi
fi
if [ -d .artifacts/diagnostics ]; then
python3 - <<'PY'
import json
from pathlib import Path

diagnostics = Path(".artifacts/diagnostics")
allowed_names = {
"build-summary.json",
"transaction-health.json",
"upstream-summary.json",
}
max_bytes = 256 * 1024

for path in sorted(diagnostics.rglob("*.json")):
if path.name not in allowed_names or path.stat().st_size > max_bytes:
continue
try:
payload = json.loads(path.read_text(encoding="utf-8"))
except (OSError, json.JSONDecodeError) as exc:
print(f"diagnostic summary unreadable: {path}: {exc}")
continue
print(f"Failure diagnostic summary: {path}")
print(json.dumps(payload, ensure_ascii=False, indent=2, sort_keys=True))
PY
fi
echo "Changed files summary:"
git status --short

- name: Upload failure diagnostics
if: failure()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: build-diagnostics-${{ github.run_id }}-${{ github.run_attempt }}
path: .artifacts/diagnostics/
include-hidden-files: true
if-no-files-found: warn
retention-days: 7

- name: Upload publish artifacts
if: success()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
Expand All @@ -114,6 +149,7 @@ jobs:

publish:
needs: build
if: github.ref == format('refs/heads/{0}', github.event.repository.default_branch)
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
Expand Down
34 changes: 32 additions & 2 deletions .github/workflows/pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,33 +42,63 @@ jobs:
fetch-depth: 0
persist-credentials: false

- name: Select release candidate scope
id: scope
env:
EVENT_NAME: pull_request
BEFORE_SHA: ${{ github.event.pull_request.base.sha }}
CURRENT_SHA: ${{ github.sha }}
run: ./scripts/commands/select-build-scope.sh

- name: Show selected release candidate scope
run: echo "${{ steps.scope.outputs.scope }} - ${{ steps.scope.outputs.reason }}"

- name: Set up Python
if: steps.scope.outputs.scope != 'none'
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
with:
python-version: '3.11'

- name: Prepare scripts
if: steps.scope.outputs.scope != 'none'
run: find scripts -type f \( -name '*.sh' -o -name '*.py' \) -exec chmod +x {} +

- name: Resolve tool versions
if: steps.scope.outputs.scope != 'none'
id: core_versions
run: bash ./scripts/commands/resolve-tool-versions.sh

- name: Restore verified tool cache
if: steps.scope.outputs.scope != 'none'
uses: actions/cache@caa296126883cff596d87d8935842f9db880ef25 # v5
with:
path: .bin
key: rules-tools-v3-${{ steps.core_versions.outputs.sing_box_version }}-${{ steps.core_versions.outputs.mihomo_version }}-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('config/tools-lock.json') }}

- name: Build and verify release candidate
if: steps.scope.outputs.scope != 'none'
env:
RULES_BUILD_SCOPE: full
RULES_BUILD_SCOPE: ${{ steps.scope.outputs.scope }}
RULES_CONFLICT_BASE_SHA: ${{ steps.scope.outputs.base_sha }}
ARTIFACT_GENERATION_ID: pr-${{ github.event.pull_request.number }}-${{ github.run_attempt }}
ARTIFACT_BUILD_ID: ${{ github.run_id }}
ARTIFACT_SOURCE_SHA: ${{ github.sha }}
run: ./scripts/commands/build-artifacts-transaction.sh

- name: Show release candidate summary
if: steps.scope.outputs.scope != 'none'
run: |
cat .output/build-summary.json
cat .output/upstream-summary.json
if [ -f .output/upstream-summary.json ]; then
cat .output/upstream-summary.json
fi

- name: Upload failure diagnostics
if: failure() && steps.scope.outputs.scope != 'none'
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: release-candidate-diagnostics-${{ github.run_id }}-${{ github.run_attempt }}
path: .artifacts/diagnostics/
include-hidden-files: true
if-no-files-found: warn
retention-days: 7
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
.output/
.tmp/
.bin/
.artifacts/

# Python
__pycache__/
Expand Down
4 changes: 2 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ IP 目录可不存在或为空。文件名只使用小写字母、数字和连

## 审计信息的使用

完整主上游同步生成 `.output/upstream-summary.json` 和域名 `rule-manifest.json`。前者是部分采集摘要,不覆盖本仓库维护的自定义源(包括 `sources/custom/domain/fakeip-filter.list`)、完整转换链、提交身份或内容校验和,不能称为完整来源追溯记录。`fakeip-filter` 与其他自定义规则一起生成各平台产物,不得重新引入第三方预编译文件或下载步骤;过去采用的 `wwqgtxx/clash-rules` 二进制仅属历史
完整主上游同步生成 `.output/upstream-summary.json` 和域名 `rule-manifest.json`。前者记录健康结果与输入摘要,但不覆盖本仓库维护的自定义源(包括 `sources/custom/domain/fakeip-filter.list`)、完整转换链或 HTTP 响应身份,不能称为完整来源追溯记录。`fakeip-filter` 与其他自定义规则一起生成各平台产物,不得引入独立预编译文件或下载步骤

成功的 `build-artifacts-transaction.sh` 在产物守卫之后、manifest 之前生成 `.output/build-summary.json`;manifest 绑定其文件摘要与嵌入内容。独立运行 `make build-custom*` 不生成该文件。所有摘要都不是许可证明。

Expand All @@ -61,7 +61,7 @@ make build-custom

`make preflight` 只组合 `make validate` 与文本自定义构建,不执行完整同步、产物守卫(artifact guard)或发布。本地缺少 ShellCheck 时可能跳过,CI 则设置 `REQUIRE_SHELLCHECK=1`。

完整支持环境与工具下载边界见 [开发指南](docs/DEVELOPMENT.md)。不要提交 `.output/`、`.tmp/`、`.bin/`、凭据或本机缓存。
完整支持环境与工具下载边界见 [开发指南](docs/DEVELOPMENT.md)。不要提交 `.output/`、`.tmp/`、`.artifacts/`、`.bin/`、凭据或本机缓存。

## 修改实现

Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,9 @@ make clean
## 仓库边界

- 长期分支只保留 `main` 与 `surge`、`quanx`、`egern`、`sing-box`、`mihomo` 五个产物分支。
- 变更通过临时分支向 `main` 提交 Pull Request;PR 运行静态检查和不发布的完整候选构建,临时分支在合并后删除。
- 变更通过临时分支向 `main` 提交 Pull Request;PR 始终运行静态检查,并按改动路径选择跳过、custom 或 full 候选构建,临时分支在合并后删除。
- `main` 在构建相关路径变化、定时任务运行或人工触发时执行发布工作流;产物内容没有变化时不会创建新的产物分支提交。
- Dependabot 每月向 `main` 集中提交一个 GitHub Actions minor/patch 更新 PR;major 与安全告警单独人工评估
- Dependabot 每周向 `main` 集中提交一个 GitHub Actions minor/patch 更新 PR;major 与安全更新保持独立,逐项评估
- `fakeip-filter` 是本仓库维护的文本源,不下载第三方预编译文件。
- 构建摘要、manifest 和 CI 通过都不是第三方许可证明。
- 规则按现状提供。使用者需自行判断策略、顺序和更新带来的影响,并保留可回退版本。
Expand Down
10 changes: 4 additions & 6 deletions THIRD_PARTY_NOTICES.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# 第三方声明

本文件记录当前已知第三方输入及截至 **2026-07-14** 的人工核对状态。它不是自动生成清单,也不是法律意见。`trust` 只表示采集来源分类;公开可访问、官方托管、注册机构提供或 CI 成功都不等于获得复制、修改或再分发授权。
本文件记录当前已知第三方输入及截至 **2026-07-15** 的人工核对状态。它不是自动生成清单,也不是法律意见。`trust` 只表示采集来源分类;公开可访问、官方托管、注册机构提供或 CI 成功都不等于获得复制、修改或再分发授权。

标准 MIT License 位于 [`LICENSE`](LICENSE),适用范围见 [`NOTICE`](NOTICE)。第三方材料不会因下载、规范化、合并、转换或编译而变为本仓库的 MIT 内容。

Expand All @@ -24,24 +24,22 @@
| `ip.google` | <https://www.gstatic.com/ipranges/goog.json> | `official` | 未知;响应中未见独立数据许可证。 |
| `ip.telegram` | <https://core.telegram.org/resources/cidr.txt> | `official` | 未知;响应中未见独立数据许可证。 |
| `ip.cloudflare-ipv4`、`ip.cloudflare-ipv6` | <https://www.cloudflare.com/ips-v4>、<https://www.cloudflare.com/ips-v6> | `official` | 未知;未确认独立数据许可证。 |
| `ip.aws`(也生成 `cloudfront` | <https://ip-ranges.amazonaws.com/ip-ranges.json> | `official` | 未知;响应中未见独立数据许可证。 |
| `ip.aws`、`ip.cloudfront` | <https://ip-ranges.amazonaws.com/ip-ranges.json> | `official` | 未知;两个解析器复用同一官方响应,未见独立数据许可证。 |
| `ip.fastly` | <https://api.fastly.com/public-ip-list> | `official` | 未知;响应中未见独立数据许可证。 |
| `ip.github` | <https://api.github.com/meta> | `official` | 未知;未确认 Meta API 数据的独立再分发许可证。 |
| `ip.apple` | <https://support.apple.com/en-us/101555>(回退:<https://support.apple.com/zh-cn/101555>) | `official` | 未知;未确认页面中网络范围数据的独立再分发许可证。 |
| `ip.ripe-stat` | <https://stat.ripe.net/data/announced-prefixes/data.json?resource=AS> | `registry` | 未知;未确认 API 响应和 ASN 查询所得前缀集合的再分发许可。 |

`asn_groups.telegram`、`asn_groups.netflix`、`asn_groups.spotify` 和 `asn_groups.disney` 只是 RIPEstat 查询参数分组,不是独立许可声明;所得结果沿用 `ip.ripe-stat` 的“未知”状态。组织名称和商标归各自权利人所有。

## Fake-IP 迁移说明
## Fake-IP

当前 `fakeip-filter` 是 KuGouGo 在 `sources/custom/domain/fakeip-filter.list` 维护的仓库源码,由自定义构建生成各平台文本产物以及 sing-box、mihomo 二进制产物;它不属于第三方输入,也不下载第三方预编译文件。

本仓库过去曾直接采用 `wwqgtxx/clash-rules` 的预编译 `release/fakeip-filter.mrs`。该来源仅记录历史迁移背景,不是当前网络输入、构建步骤或发布材料;当前产物不得据此归因于该项目。

## 审计与评审边界

- `config/upstreams.json` 覆盖主上游规则网络输入;工具资产下载另由工具 lock 控制。当前没有 Fake-IP 网络输入或独立同步步骤。
- `.output/upstream-summary.json` 只覆盖主同步记录,不覆盖本仓库自定义源(包括 `fakeip-filter`)、完整转换链、提交身份或内容校验和,因此不是完整来源追溯记录。
- `.output/upstream-summary.json` 只覆盖主同步记录,不覆盖本仓库自定义源(包括 `fakeip-filter`)、完整转换链或 HTTP 响应身份,因此不是完整来源追溯记录。
- `.output/build-summary.json` 由成功构建事务在产物守卫后生成并受 manifest 摘要绑定;它只说明事务产物统计,不证明来源或授权。
- 当前自动化不解析 `NOTICE` 或本文件,不验证第三方许可,也不会因“未知”状态自动失败。
- 新增、更换或改变第三方输入时,应同步更新本文件并提供可核验依据;无法确认时保持“未知”,由维护者人工决定停止、替换、取得授权或满足适用义务后再发布。
Expand Down
4 changes: 4 additions & 0 deletions config/upstreams.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@
"kind": "json", "trust": "official", "parser": "aws-json", "url": "https://ip-ranges.amazonaws.com/ip-ranges.json",
"health": { "requirement": "required", "min_raw_bytes": 1000, "min_entries": 100, "family": "dual", "fallback_policy": "none" }
},
"cloudfront": {
"kind": "json", "trust": "official", "parser": "aws-cloudfront-json", "url": "https://ip-ranges.amazonaws.com/ip-ranges.json",
"health": { "requirement": "required", "min_raw_bytes": 1000, "min_entries": 150, "family": "dual", "fallback_policy": "none" }
},
"fastly": {
"kind": "json", "trust": "official", "parser": "fastly-json", "url": "https://api.fastly.com/public-ip-list",
"health": { "requirement": "required", "min_raw_bytes": 50, "min_entries": 12, "family": "any", "fallback_policy": "none" }
Expand Down
Loading