Files
Dwrt-build/.github/workflows/build.yml
2026-01-18 15:41:16 +08:00

380 lines
13 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
name: Build WRT
on:
workflow_dispatch:
inputs:
project:
description: "选择 WRT 项目"
required: true
default: "immortalwrt"
type: choice
options:
- lede
- openwrt
- immortalwrt
- immortalwrt-mt798x
- immortalwrt-mt798x-6.6
tag:
description: "版本号"
required: false
default: "v24.10.3"
type: string
version_type:
description: "版本类型"
required: true
default: "stable"
type: choice
options:
- "snapshot"
- "stable"
config_path:
description: "配置文件路径"
required: true
default: "config/x86_64_config"
type: string
proxy_passwall2:
description: "启用Passwall2"
required: false
default: false
type: boolean
proxy_luci_app_zzz:
description: "启用luci-app-zzz"
required: false
default: false
type: boolean
proxy_luci_app_momo:
description: "启用luci-app-momo"
required: false
default: false
type: boolean
threads:
description: "编译线程数(填写 0 则使用 nproc"
required: false
default: "0"
type: string
cache_enabled:
description: "启用缓存加速编译"
required: false
default: true
type: boolean
env:
CCACHE_DIR: ${{ github.workspace }}/wrt/.ccache
DL_DIR: ${{ github.workspace }}/wrt/dl
jobs:
validate:
name: 验证输入参数
runs-on: ubuntu-latest
outputs:
is_valid: ${{ steps.validate.outputs.is_valid }}
config_exists: ${{ steps.validate.outputs.config_exists }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Validate inputs
id: validate
run: |
echo "🔍 验证输入参数..."
# 验证 threads 参数
if [ -n "${{ inputs.threads }}" ]; then
if ! [[ "${{ inputs.threads }}" =~ ^[0-9]+$ ]]; then
echo "❌ threads 参数必须是数字"
echo "is_valid=false" >> "$GITHUB_OUTPUT"
exit 1
fi
fi
# 验证配置文件是否存在
if [ -f "${{ inputs.config_path }}" ]; then
echo "config_exists=true" >> "$GITHUB_OUTPUT"
echo "✅ 配置文件存在:${{ inputs.config_path }}"
else
echo "config_exists=false" >> "$GITHUB_OUTPUT"
echo "❌ 配置文件不存在:${{ inputs.config_path }}"
echo "is_valid=false" >> "$GITHUB_OUTPUT"
exit 1
fi
echo "is_valid=true" >> "$GITHUB_OUTPUT"
echo "✅ 所有输入参数验证通过"
build:
name: 编译固件
runs-on: ubuntu-latest
needs: validate
timeout-minutes: 360
steps:
- name: Checkout current repository
uses: actions/checkout@v4
- name: Free up disk space
run: |
echo "🧹 开始清理无用文件,释放磁盘空间"
sudo rm -rf /usr/share/dotnet \
/usr/local/lib/android \
/opt/ghc \
/opt/az \
/opt/microsoft \
/usr/local/share/boost \
/usr/share/swift \
/usr/local/lib/nodejs
sudo apt-get clean
sudo rm -rf /var/lib/apt/lists/*
echo "📊 磁盘使用情况:"
df -h || true
- name: Setup ccache
uses: hendrikmuhs/ccache-action@v1.2
if: inputs.cache_enabled == true
with:
key: ${{ runner.os }}-wrt-ccache-${{ inputs.project }}-${{ inputs.version_type }}
max-size: 2G
- name: Cache downloads
uses: actions/cache@v4
if: inputs.cache_enabled == true
with:
path: ${{ env.DL_DIR }}
key: ${{ runner.os }}-wrt-dl-${{ inputs.project }}-${{ inputs.version_type }}-${{ hashFiles('**/*.config') }}
restore-keys: |
${{ runner.os }}-wrt-dl-${{ inputs.project }}-${{ inputs.version_type }}-
${{ runner.os }}-wrt-dl-${{ inputs.project }}-
${{ runner.os }}-wrt-dl-
- name: Cache build directory
uses: actions/cache@v4
if: inputs.cache_enabled == true
with:
path: wrt/build_dir
key: ${{ runner.os }}-wrt-build-${{ inputs.project }}-${{ inputs.version_type }}-${{ hashFiles('**/*.config') }}
restore-keys: |
${{ runner.os }}-wrt-build-${{ inputs.project }}-${{ inputs.version_type }}-
${{ runner.os }}-wrt-build-${{ inputs.project }}-
${{ runner.os }}-wrt-build-
- name: Choose Wrt Version
id: refinfo
run: |
if [ "${{ inputs.version_type }}" = "snapshot" ]; then
echo "ref=master" >> "$GITHUB_OUTPUT"
else
echo "ref=${{ inputs.tag }}" >> "$GITHUB_OUTPUT"
fi
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
build-essential clang flex bison g++ gawk gettext git \
libncurses-dev libssl-dev python3 python3-dev python3-setuptools \
rsync unzip zlib1g-dev file wget curl \
gzip tar zip xz-utils bzip2 zstd \
make cmake autoconf automake libtool patch diffutils \
findutils grep sed help2man texinfo \
libelf-dev libfuse-dev liblzma-dev libxml2-dev libyaml-dev \
uuid-dev device-tree-compiler antlr3 gperf \
time bc jq xxd swig upx-ucl ccache ecj fastjar imagemagick \
llvm linux-tools-common libbpf-dev linux-tools-$(uname -r) \
u-boot-tools device-tree-compiler
- name: Determine Git URL
id: projectinfo
run: |
case "${{ inputs.project }}" in
immortalwrt)
echo "url=https://github.com/immortalwrt/immortalwrt.git" >> $GITHUB_OUTPUT
;;
immortalwrt-mt798x)
echo "url=https://github.com/hanwckf/immortalwrt-mt798x.git" >> $GITHUB_OUTPUT
;;
immortalwrt-mt798x-6.6)
echo "url=https://github.com/padavanonly/immortalwrt-mt798x-6.6.git" >> $GITHUB_OUTPUT
;;
openwrt)
echo "url=https://git.openwrt.org/openwrt/openwrt.git" >> $GITHUB_OUTPUT
;;
lede)
echo "url=https://github.com/coolsnowwolf/lede.git" >> $GITHUB_OUTPUT
;;
*)
echo "❌ 未知项目: ${{ inputs.project }}" >&2
exit 1
;;
esac
- name: Clone Wrt source
run: |
echo "📥 克隆 ${{ inputs.project }} 仓库"
git clone --depth 1 "${{ steps.projectinfo.outputs.url }}" -b "${{ steps.refinfo.outputs.ref }}" wrt || \
(git clone "${{ steps.projectinfo.outputs.url }}" wrt && cd wrt && git checkout "${{ steps.refinfo.outputs.ref }}")
echo "🔖 当前版本:$(cd wrt && git describe --tags --always || git rev-parse --short HEAD)"
- name: Copy and Run diy.sh
run: |
echo "📂 复制 diy.sh 到 wrt 目录并执行"
cp diy.sh wrt/diy.sh
cd wrt
chmod +x diy.sh
./diy.sh
- name: Update and install feeds
working-directory: wrt
run: |
if [ "${{ inputs.proxy_luci_app_zzz }}" = "true" ]; then
echo "📦 添加 luci-app-zzz feed"
echo "src-git luci-app-zzz https://github.com/Dichgrem/luci-app-zzz.git" >> "feeds.conf.default"
fi
if [ "${{ inputs.proxy_passwall2 }}" = "true" ]; then
echo "📦 添加 passwall2 feed"
echo "src-git passwall https://github.com/xiaorouji/openwrt-passwall2.git" >> "feeds.conf.default"
fi
if [ "${{ inputs.proxy_luci_app_momo }}" = "true" ]; then
echo "📦 添加 luci-app-momo feed"
echo "src-git momo https://github.com/nikkinikki-org/OpenWrt-momo.git" >> "feeds.conf.default"
fi
echo "📦 更新 feeds"
./scripts/feeds update -a
echo "📦 安装 feeds"
./scripts/feeds install -a
- name: Setup configuration
run: |
echo "📋 复制配置:${{ inputs.config_path }} → wrt/.config"
cp "${{ inputs.config_path }}" wrt/.config
cd wrt
echo "📑 备份配置文件以供对比"
cp .config .config.before_oldconfig
echo "🔄 运行 make oldconfig"
make oldconfig
echo "🔍 对比 make oldconfig 前后的 .config 差异"
if cmp -s .config.before_oldconfig .config; then
echo "✅ .config 在 make oldconfig 后未发生变化"
else
echo "⚠️ .config 在 make oldconfig 后发生变化,差异如下:"
diff -u .config.before_oldconfig .config || true
fi
- name: Download packages
working-directory: wrt
run: |
echo "⬇️ 下载所有源码包(使用单线程 -j1 避免卡住)"
set -o pipefail
START=$(date +%s)
time make download -j1
END=$(date +%s)
DURATION=$((END - START))
echo "✅ 下载完成,耗时:${DURATION}秒"
- name: Build Firmware
id: build
working-directory: wrt
run: |
if [ "${{ inputs.threads }}" = "0" ] || [ -z "${{ inputs.threads }}" ]; then
JOBS=$(nproc)
else
JOBS=${{ inputs.threads }}
fi
echo "🚀 全量编译(并行 ${JOBS})开始"
START=$(date "+%Y-%m-%d %H:%M:%S")
START_TS=$(date +%s)
echo "⏱️ 编译开始:${START}"
echo "jobs_count=${JOBS}" >> "$GITHUB_OUTPUT"
set -o pipefail
# 第一次尝试多线程编译,并保存日志
if ! (time make world -j${JOBS} 2>&1 | tee world_debug.log); then
echo "⚠️ 多线程编译失败,尝试使用单线程并输出详细信息..."
# 单线程模式输出详细信息,并追加到同一日志
time make world -j1 V=s 2>&1 | tee -a world_debug.log
echo "❌ 单线程编译后依然失败,以下是匹配关键字的错误行:"
grep -E -i "(error:|failed|fatal|cannot install package)" -n world_debug.log || true
exit 1
fi
END=$(date "+%Y-%m-%d %H:%M:%S")
END_TS=$(date +%s)
DURATION=$((END_TS - START_TS))
DURATION_H=$((DURATION / 3600))
DURATION_M=$(((DURATION % 3600) / 60))
DURATION_S=$((DURATION % 60))
echo "✅ 编译成功"
echo "⏱️ 编译结束:${END}"
echo "⏱️ 总耗时:${DURATION_H}小时 ${DURATION_M}分钟 ${DURATION_S}秒"
echo "build_success=true" >> "$GITHUB_OUTPUT"
- name: Build statistics
if: steps.build.outputs.build_success == 'true'
run: |
echo "📊 编译统计信息:"
echo "项目:${{ inputs.project }}"
echo "版本:${{ steps.refinfo.outputs.ref }}"
echo "编译线程:${{ steps.build.outputs.jobs_count }}"
echo "缓存状态:${{ inputs.cache_enabled }}"
echo ""
echo "固件文件列表:"
if [ -d wrt/bin/targets ]; then
find wrt/bin/targets -type f -exec ls -lh {} \; | awk '{print $9, $5}'
echo ""
echo "总固件大小:"
du -sh wrt/bin/targets
fi
- name: Upload build log on failure
uses: actions/upload-artifact@v4
if: failure()
with:
name: ${{ inputs.project }}-build-log-error
path: wrt/world_debug.log
retention-days: 7
if-no-files-found: ignore
- name: Upload build artifacts
uses: actions/upload-artifact@v4
if: steps.build.outputs.build_success == 'true'
with:
name: ${{ inputs.project }}-output-${{ inputs.version_type }}-${{ github.run_number }}
path: |
wrt/bin/targets/**
!wrt/bin/targets/x86/64/packages/**
!wrt/bin/targets/**/packages/**
if-no-files-found: warn
compression-level: 6
overwrite: false
retention-days: 30
- name: Upload config diff
uses: actions/upload-artifact@v4
if: steps.build.outputs.build_success == 'true'
with:
name: ${{ inputs.project }}-config-diff
path: |
wrt/.config
wrt/.config.before_oldconfig
if-no-files-found: ignore
retention-days: 7
- name: Cleanup
if: always()
run: |
echo "🧹 清理工作空间..."
cd wrt
make clean || true
echo "✅ 清理完成"