mirror of
https://github.com/Dichgrem/Dwrt-build.git
synced 2026-02-05 02:11:56 -05:00
380 lines
13 KiB
YAML
380 lines
13 KiB
YAML
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 "✅ 清理完成"
|