Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
903bfbd
fix: stabilize local dev login flow
Ryson-32 Jun 20, 2026
0832d47
fix: tolerate fake-ip DNS for source import
Ryson-32 Jun 20, 2026
4a0d317
refactor: centralize fake-ip DNS recheck policy
Ryson-32 Jun 20, 2026
eafe684
refactor: decouple rule ordering from routing targets
Ryson-32 Jun 21, 2026
228875a
feat: add dev release channel
Ryson-32 Jun 21, 2026
f2aa108
fix: restore rule order confirmation gate
Ryson-32 Jun 21, 2026
a25ac66
test: update local URL resolver fixture
Ryson-32 Jun 21, 2026
fcdcd55
Remove legacy selfhost rule compatibility
Ryson-32 Jun 21, 2026
484a076
Add shared RFC8484 DoH resolver
Ryson-32 Jun 21, 2026
fccc80f
Add generated YAML semantic diff helpers
Ryson-32 Jun 21, 2026
29c43fb
Fix TypeScript source package exports
Ryson-32 Jun 22, 2026
d01db2f
fix(core): remove deprecated global fingerprint handling
Ryson-32 Jun 22, 2026
8359e48
fix: restore duplicate-origin source nodes
Ryson-32 Jun 22, 2026
0517ec5
feat: unify proxy group advanced editing
Ryson-32 Jun 22, 2026
3be7f45
fix: default custom proxy groups expanded
Ryson-32 Jun 22, 2026
0f67ea9
Remove legacy filtered group runtime support
Ryson-32 Jun 22, 2026
fd55a8a
fix: preserve migrated filtered group semantics
Ryson-32 Jun 23, 2026
17dc6b1
test: cover filtered group edge cases
Ryson-32 Jun 23, 2026
bfa9c39
test: cover proxy group member resolution edges
Ryson-32 Jun 23, 2026
3d70b1d
fix: export proxy group target helpers
Ryson-32 Jun 23, 2026
fafaa22
fix: export proxy group advanced helpers
Ryson-32 Jun 23, 2026
ee28cac
test(core): raise generator and parser coverage
Ryson-32 Jun 23, 2026
44521b9
test(local): cover cleanup and server-core paths
Ryson-32 Jun 23, 2026
450bed3
test(ui): cover advanced proxy group controls
Ryson-32 Jun 23, 2026
1784677
test(store): cover proxy group state actions
Ryson-32 Jun 23, 2026
ece904a
fix: tighten custom proxy group editor layout
Ryson-32 Jun 24, 2026
03ac471
test: update custom group card mock
Ryson-32 Jun 24, 2026
4d997b1
chore: prepare SubBoost v2.5.0 release
Ryson-32 Jun 24, 2026
be5c985
fix: avoid regex backtracking in rule paths
Ryson-32 Jun 24, 2026
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
275 changes: 275 additions & 0 deletions .github/workflows/dev-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,275 @@
name: Dev Release

on:
workflow_dispatch:
push:
branches:
- ryan/dev
paths:
- ".github/workflows/ci.yml"
- ".github/workflows/dev-release.yml"
- ".github/workflows/release.yml"
- "eslint.config.mjs"
- "local/**"
- "package-lock.json"
- "package.json"
- "packages/**"
- "scripts/**"
- "tsconfig.json"
- "vitest.config.ts"
- "vitest.core.config.ts"

permissions:
contents: write
packages: write

concurrency:
group: dev-release-${{ github.ref }}
cancel-in-progress: false

env:
IMAGE_NAME: ghcr.io/subboost/subboost

jobs:
meta:
runs-on: ubuntu-latest
outputs:
build_version: ${{ steps.meta.outputs.build_version }}
image_name: ${{ steps.meta.outputs.image_name }}
release_version: ${{ steps.meta.outputs.release_version }}
short_sha: ${{ steps.meta.outputs.short_sha }}
steps:
- uses: actions/checkout@v6

- uses: actions/setup-node@v6
with:
node-version: "22.19.0"

- name: Validate dev source
id: meta
shell: bash
run: |
set -euo pipefail
if [ "${GITHUB_REF_NAME}" != "ryan/dev" ]; then
echo "Dev release must run from ryan/dev, got ${GITHUB_REF_NAME}." >&2
exit 1
fi
release_version="$(node -p "require('./package.json').version")"
short_sha="${GITHUB_SHA::12}"
echo "release_version=${release_version}" >> "$GITHUB_OUTPUT"
echo "short_sha=${short_sha}" >> "$GITHUB_OUTPUT"
echo "build_version=${release_version}+sha.${short_sha}" >> "$GITHUB_OUTPUT"
echo "image_name=${IMAGE_NAME}" >> "$GITHUB_OUTPUT"

checks:
runs-on: ubuntu-latest
needs: meta
steps:
- uses: actions/checkout@v6

- uses: actions/setup-node@v6
with:
node-version: "22.19.0"

- run: npm ci
- run: npm run lint
- run: npm run test:unit
- run: npm run check:local-app

build-image:
runs-on: ubuntu-latest
needs: meta
strategy:
fail-fast: false
matrix:
include:
- arch: amd64
platform: linux/amd64
- arch: arm64
platform: linux/arm64
steps:
- uses: actions/checkout@v6

- uses: docker/setup-qemu-action@v3

- uses: docker/setup-buildx-action@v3

- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ secrets.GHCR_USERNAME || github.actor }}
password: ${{ secrets.GHCR_PAT || github.token }}

- name: Build and push ${{ matrix.platform }} image by digest
id: build_image
uses: docker/build-push-action@v6
with:
context: .
file: local/Dockerfile
platforms: ${{ matrix.platform }}
outputs: type=image,push-by-digest=true,name-canonical=true,push=true
build-args: |
APP_RELEASE_VERSION=${{ needs.meta.outputs.release_version }}
APP_BUILD_SHA=${{ github.sha }}
APP_VERSION=${{ needs.meta.outputs.build_version }}
APP_VERSION_TOKEN=${{ needs.meta.outputs.build_version }}
cache-from: type=gha,scope=selfhost-dev-${{ matrix.arch }}
cache-to: type=gha,mode=max,scope=selfhost-dev-${{ matrix.arch }}
provenance: false
tags: ${{ needs.meta.outputs.image_name }}

- name: Export digest
shell: bash
run: |
set -euo pipefail
mkdir -p "${RUNNER_TEMP}/digests"
digest="${{ steps.build_image.outputs.digest }}"
touch "${RUNNER_TEMP}/digests/${digest#sha256:}"

- name: Upload digest
uses: actions/upload-artifact@v4
with:
name: digest-${{ matrix.arch }}
path: ${{ runner.temp }}/digests/*
if-no-files-found: error
retention-days: 1

publish-dev-release:
runs-on: ubuntu-latest
needs:
- meta
- checks
- build-image
steps:
- uses: actions/checkout@v6

- uses: actions/setup-node@v6
with:
node-version: "22.19.0"

- uses: docker/setup-buildx-action@v3

- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ secrets.GHCR_USERNAME || github.actor }}
password: ${{ secrets.GHCR_PAT || github.token }}

- name: Download image digests
uses: actions/download-artifact@v4
with:
pattern: digest-*
path: ${{ runner.temp }}/digests
merge-multiple: true

- name: Create dev image tags
id: image_manifest
shell: bash
env:
IMAGE_NAME: ${{ needs.meta.outputs.image_name }}
SHORT_SHA: ${{ needs.meta.outputs.short_sha }}
run: |
set -euo pipefail
mapfile -t digest_files < <(find "${RUNNER_TEMP}/digests" -type f | sort)
if [ "${#digest_files[@]}" -lt 2 ]; then
echo "Expected at least two architecture digests, found ${#digest_files[@]}" >&2
exit 1
fi

sources=()
for file in "${digest_files[@]}"; do
sources+=("${IMAGE_NAME}@sha256:$(basename "$file")")
done

docker buildx imagetools create \
--metadata-file "${RUNNER_TEMP}/image-metadata.json" \
--tag "${IMAGE_NAME}:dev" \
--tag "${IMAGE_NAME}:sha-${SHORT_SHA}" \
"${sources[@]}"

digest="$(node -e 'const metadata = require(process.argv[1]); const digest = metadata["containerimage.digest"] || metadata["containerimage.descriptor"]?.digest; if (!digest) { console.error(JSON.stringify(metadata, null, 2)); process.exit(1); } process.stdout.write(digest);' "${RUNNER_TEMP}/image-metadata.json")"
if [ -z "$digest" ] || [ "$digest" = "null" ]; then
echo "Failed to resolve multi-platform image digest for ${IMAGE_NAME}:dev" >&2
exit 1
fi
echo "digest=${digest}" >> "$GITHUB_OUTPUT"

- name: Prepare dev release assets
shell: bash
env:
IMAGE_DIGEST: ${{ steps.image_manifest.outputs.digest }}
IMAGE_NAME: ${{ needs.meta.outputs.image_name }}
run: |
set -euo pipefail
dev_base_url="https://github.com/${GITHUB_REPOSITORY}/releases/download/dev"
node scripts/selfhost-release-assets.cjs \
--output dist/release-assets \
--tag dev \
--build-sha "${GITHUB_SHA}" \
--image "${IMAGE_NAME}@${IMAGE_DIGEST}" \
--image-tag "${IMAGE_NAME}:dev" \
--base-url "${dev_base_url}" \
--installer-release-url "${dev_base_url}/release.json" \
--installer-compose-url "${dev_base_url}/docker-compose.image.yml" \
--installer-manager-url "${dev_base_url}/subboost-manager" \
--installer-image "${IMAGE_NAME}:dev"

- name: Move dev tag
shell: bash
run: |
set -euo pipefail
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git tag -f dev "${GITHUB_SHA}"
git push origin "refs/tags/dev" --force

- name: Create or update dev prerelease
shell: bash
env:
GH_TOKEN: ${{ github.token }}
IMAGE_DIGEST: ${{ steps.image_manifest.outputs.digest }}
IMAGE_NAME: ${{ needs.meta.outputs.image_name }}
run: |
set -euo pipefail
notes_file="${RUNNER_TEMP}/dev-release-notes.md"
cat > "$notes_file" <<EOF
Automated dev prerelease for ryan/dev.

- Commit: ${GITHUB_SHA}
- Image tag: ${IMAGE_NAME}:dev
- Image digest: ${IMAGE_NAME}@${IMAGE_DIGEST}

This mutable prerelease follows ryan/dev and is not a stable release announcement.
EOF

if gh release view dev >/dev/null 2>&1; then
gh release edit dev \
--title "SubBoost dev" \
--notes-file "$notes_file" \
--prerelease \
--draft=false
gh release upload dev \
dist/release-assets/release.json \
dist/release-assets/install.sh \
dist/release-assets/docker-compose.image.yml \
dist/release-assets/subboost-manager \
--clobber
else
gh release create dev \
--title "SubBoost dev" \
--notes-file "$notes_file" \
--prerelease \
--latest=false \
--verify-tag \
dist/release-assets/release.json \
dist/release-assets/install.sh \
dist/release-assets/docker-compose.image.yml \
dist/release-assets/subboost-manager
fi

release_id="$(gh api "repos/${GITHUB_REPOSITORY}/releases/tags/dev" --jq ".id")"
gh api --method PATCH "repos/${GITHUB_REPOSITORY}/releases/${release_id}" \
-F draft=false \
-F prerelease=true \
-f make_latest=false \
>/dev/null
4 changes: 2 additions & 2 deletions README-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<h1>SubBoost</h1>
<p>
<img src="https://img.shields.io/badge/platform-Linux%20%2B%20Docker-lightgrey.svg" alt="平台:Linux + Docker">
<img src="https://img.shields.io/badge/version-2.4.0-green.svg" alt="版本 2.4.0">
<img src="https://img.shields.io/badge/version-2.5.0-green.svg" alt="版本 2.5.0">
<a href="https://subboost.org"><img src="https://img.shields.io/badge/app-subboost.org-brightgreen.svg" alt="在线入口"></a>
<a href="https://docs.subboost.org"><img src="https://img.shields.io/badge/docs-subboost.org-blue.svg" alt="文档"></a>
<img src="https://img.shields.io/badge/image-GHCR-blue.svg" alt="GHCR 镜像">
Expand All @@ -19,7 +19,7 @@

- **订阅转换**:支持订阅链接、YAML 文件和节点链接等多种格式导入。
- **节点管理**:支持批量对节点重命名、删除或配置监听端口。
- **节点筛选**:可按导入源、地区和自定义规则,构建只有部分节点的 `筛选代理组`
- **节点筛选**:可在分流组高级模式中按导入源、地区和自定义规则筛选节点
- **链式代理**:一键可视化配置链式代理和 `中转代理组`。
- **精确分流**:内置 30 多个常用代理组和 2000 多条远程规则集供启用。
- **规则管理**:可修改规则顺序,供高级用户深度自定义。
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<h1>SubBoost</h1>
<p>
<img src="https://img.shields.io/badge/platform-Linux%20%2B%20Docker-lightgrey.svg" alt="Platform: Linux + Docker">
<img src="https://img.shields.io/badge/version-2.4.0-green.svg" alt="Version 2.4.0">
<img src="https://img.shields.io/badge/version-2.5.0-green.svg" alt="Version 2.5.0">
<a href="https://subboost.org"><img src="https://img.shields.io/badge/app-subboost.org-brightgreen.svg" alt="Online app"></a>
<a href="https://docs.subboost.org"><img src="https://img.shields.io/badge/docs-subboost.org-blue.svg" alt="Documentation"></a>
<img src="https://img.shields.io/badge/image-GHCR-blue.svg" alt="GHCR image">
Expand Down
58 changes: 33 additions & 25 deletions docs/release-notes.md
Original file line number Diff line number Diff line change
@@ -1,41 +1,49 @@
# SubBoost v2.4.0
# SubBoost v2.5.0

## 中文

### 初始发布
### 更新重点

这是 SubBoost 的首次公开发布。这个版本提供一个可以自行部署的 SubBoost 包,适合希望在自己的服务器上运行 SubBoost,并管理订阅转换、模板和规则配置的用户
SubBoost v2.5.0 主要改善代理组编辑、自部署更新和订阅生成稳定性。建议 v2.4.0 用户升级

### 包含内容
### 主要变化

- 一键部署脚本和 Docker Compose 配置,用于在 Linux 服务器上安装 SubBoost。
- 本地 Web 管理界面,用于创建管理员账号,并管理订阅、模板和规则。
- 共享的订阅解析、订阅生成、模板处理和规则处理能力。
- GitHub Release 资产:`install.sh`、`release.json`、`docker-compose.image.yml` 和 `subboost-manager`。
- 基于 AGPL-3.0-only 许可证发布的公开源码。
- 新增高级代理组模式,自定义分组、规则集和手动规则的编辑状态会更稳定地保存。
- 自定义代理组入口更统一,可以更方便地按来源、地区、关键词和排除条件整理节点。
- 订阅生成更稳,规则顺序、代理组输出和常见 Mihomo 字段处理减少了意外变化。
- 节点导入兼容性更好,覆盖更多常见节点链接和 Clash/Mihomo YAML 配置。
- 自部署安装和更新流程更可靠,`subboost update`、状态检查和失败提示都有改进。
- Dashboard 下载订阅 YAML 的行为更接近直接访问订阅链接,文件名和响应头更稳定。
- 首次安装后的管理员初始化、登录和数据库连接更稳,减少安装完成后进不去后台的情况。
- 安全和发布检查加强,降低公开包、安装资产和更新流程出错的风险。

### 安装和更新
### 升级说明

- 这是首次发布,新安装不需要人工迁移。
- 安装后,后续版本可以继续使用 `subboost update` 更新。
- 建议妥善保存 `/opt/subboost/.env` 和数据库备份,方便以后迁移或恢复。
- 建议升级前备份 `/opt/subboost/.env` 和数据库,方便需要时回滚。
- 已安装 v2.4.0 的自部署实例可以继续使用 `subboost update` 更新。
- 普通订阅转换、模板和规则功能不需要手动改环境变量。
- 如果你在 v2.4.0 使用过筛选代理组,请升级后打开自定义代理组检查输出结果;必要时用新的高级代理组重新配置。

## English

### Initial Release
### Highlights

This is the first public release of SubBoost. This version provides a self-hostable SubBoost package for users who want to run SubBoost on their own server and manage subscription conversion, templates, and rule configuration.
SubBoost v2.5.0 mainly improves proxy group editing, self-hosted updates, and subscription generation stability. v2.4.0 users are encouraged to upgrade.

### What's Included
### Main Changes

- A one-click deployment script and Docker Compose configuration for installing SubBoost on a Linux server.
- A local web management interface for creating an administrator account and managing subscriptions, templates, and rules.
- Shared subscription parsing, subscription generation, template processing, and rule processing capabilities.
- GitHub Release assets: `install.sh`, `release.json`, `docker-compose.image.yml`, and `subboost-manager`.
- Public source code released under the AGPL-3.0-only license.
- Added advanced proxy group mode, with more reliable persistence for custom groups, rule sets, and manual rules.
- Unified the custom proxy group entry point, making it easier to organize nodes by source, region, keyword, and exclusion rules.
- Made subscription generation more stable, reducing unexpected changes in rule order, proxy group output, and common Mihomo fields.
- Improved node import compatibility for more common node links and Clash/Mihomo YAML configurations.
- Made self-hosted install and update flows more reliable, including `subboost update`, status checks, and failure messages.
- Dashboard YAML downloads now behave more like direct subscription links, with steadier filenames and response headers.
- Improved first-install admin setup, login, and database connection reliability to reduce post-install access issues.
- Strengthened safety and release checks to reduce the risk of problems in public packages, install assets, and updates.

### Installation and Updates
### Upgrade Notes

- This is the first release, so new installations do not require manual migration.
- After installation, future versions can continue to be updated with `subboost update`.
- Keep `/opt/subboost/.env` and database backups safe so future migration or recovery is easier.
- Back up `/opt/subboost/.env` and the database before upgrading so rollback is easier if needed.
- Existing v2.4.0 self-hosted installations can continue to update with `subboost update`.
- Normal subscription conversion, templates, and rules do not require manual environment-variable changes.
- If you used filtered proxy groups in v2.4.0, open the custom proxy group editor after upgrading and check the generated output. Recreate those groups with the new advanced proxy group controls if needed.
Loading
Loading