I largely optimized the main building process. It is now easier to use.
This project is inspired by P3TERX's Actions-Openwrt.
With Github Actions and Actions-Openwrt, it is easy to build an OpenWrt firmware without running locally. However, Github Actions do not store cache and building files. This means it has to completely rebuild from source each time, even if it is a small change.
This project uses Docker Hub or any Docker registriy for storing previous building process, allowing incremental building.
Github Actions和Actions-Openwrt让我们可以很方便地自动化编译OpenWrt固件,而不必在本地编译。然而Github Actions不存储缓存,已编译过的文件也不会在下次编译重新被使用。这就意味着,即便只是很小的改动,每次编译我们要等上很久来重新编译整个固件。
本项目使用Docker Hub或任何Docker Registry存储编译状态,使得后续的编译可以增量进行。
- Building OpenWrt with GitHub Actions and Docker
- Load and save building state to Docker Hub or other registries
- Support building options
- Various trigger methods
- Push with commands in commit messages
- Deployment events (you can use tete1030/github-repo-dispatcher)
- Repository dispatch events (you can use tete1030/github-repo-dispatcher)
- Your repo been starred by yourself
- Scheduled cron jobs
- Two building modes (before colons are job names of Github Actions)
build-inc
: Incrementally building firmware and packages (every push, about 40 minutes for standard config, about 3 hours for first-time building)build-package
: Incrementally building only packages (every push, about 25 minutes for standard config, useful when only enabling a package module)
- 在Docker Hub或其他Registry加载和存储OpenWrt编译状态
- 支持编译选项
- 多种触发模式
- Push触发,支持在commit message中包含指令
- Deployment事件触发(可使用tete1030/github-repo-dispatcher)
- Repository dispatch事件触发(可使用tete1030/github-repo-dispatcher)
- 自己给自己Star触发(可指定Star的触发者)
- 定时触发
- 两个编译模式(冒号前是Github Actions中的job名称)
build-inc
:增量编译固件和软件包(每次push自动进行,标准配置下大约每次40分钟,第一次编译时耗时大约3小时)build-package
:增量编译软件包(每次push自动进行,标准配置下大约每次25分钟,当仅需要编译软件安装包时比较有用)
The default configuration uses coolsnowwolf/lede as the OpenWrt Repo (popular in China). If you want official OpenWrt 19.07, check out "openwrt_official" branch. (It's just changes of REPO_URL
and REPO_BRANCH
envs in .github/workflows/build-openwrt.yml
.)
Check out my own configuration in "sample" branch.
The building process generally takes 1.5~3 hours depending on your config.
- Sign up for GitHub Actions
- Fork this repo
- Register a Docker Hub account. This is necessary.
- Get your Docker Hub personal access token. Fill your username and the generated token into the forked repo's Settings->Secrets page. Use
docker_username
for your username, anddocker_password
for your token. See Secrets page for correct settings. - (Optional, not very useful) If you want the debug SSH command to be sent to Slack, you can generate a Slack Webhook URL and set the url as
SLACK_WEBHOOK_URL
in the Secrets page. Search in Google if you don't know how to do it. - (Optional) Customize
.github/workflows/build-openwrt.yml
to change builder's name and other options. - Generate your
.config
and rename it toconfig.diff
. Put the file in the root dir of your forked repo. - (Optional) Customize
scripts/update_feeds.sh
for additional packages you want to download. - (Optional) Put any patch you want to
patches
dir. The patches are applied afterupdate_feeds.sh
and beforedownload.sh
. - Commit and push your changes. This will automatically trigger an incremental building.
- Wait for
build-inc
job to finish. - Collect your files in the
build-inc
job'sArtifacts
menu
- 注册GitHub Actions
- Fork
- 注册Docker Hub. 这步很重要
- 取得Docker Hub的personal access token。在你自己Fork的Repo中的Settings->Secrets页面填写你的Docker Hub用户名和token。使用“docker_username”填写用户名,使用“docker_password”填写token。详见Secrets page。
- (可选,没什么用) 如果你想自动把SSH命令发送到Slack,你可以在Secrets页面设置
SLACK_WEBHOOK_URL
。详细方法请自行Google。 - (可选) 定制
.github/workflows/build-openwrt.yml
以修改你想在Docker Hub保存的builder名和其他选项。 - 生成你的
.config
文件,并把它重命名为config.diff
。把它放在根目录。 - (可选) 如果你想放置额外安装包,定制
scripts/update_feeds.sh
。 - (可选) 在patches目录放置补丁文件。补丁会自动在
update_feeds.sh
之后,download.sh
之前执行。 - Commit并Push。这一步骤会自动触发编译。
- 等待
build-inc
任务完成。 - 在
build-inc
任务的Artifacts
目录下载编译好的文件。
After the first-time building, you will only need the following steps to build your firmwares and packages when you change your config. The building process generally only takes 20 minutes ~ 1 hour depending on how much your config has changed.
- (Optional) Modify your
config.diff
if you want. - (Optional) Customize
scripts/update_feeds.sh
for additional packages you want to download. - (Optional) Put any patch you want to
patches
dir. - Commit and push your changes. If you want to do
build-inc
, you don't need any special step. If you needbuild-package
, you can include this string in your last commit message before push:#build-package#
. - Wait for
build-inc
orbuild-package
to finish - Collect your files in the
build-inc
orbuild-package
job's "Artifacts" menu
- (可选) 根据需要修改你的
config.diff
- (可选) 根据需要修改你的
scripts/update_feeds.sh
- (可选) 根据需要添加新的补丁至patches目录
- Commit并Push。如果你想执行
build-inc
任务,你不需要进行任何特殊操作。如果你需要执行build-package
,你可以在Push前的最后一个commit message中包含这一字符串:#build-package#
- 等待
build-inc
或build-package
完成 - 在“Artifacts”目录收集文件
The following contents require your understanding of the mechanism. See Mechanism.
If you have largely modified your configurations, incremental building may fail as there could be old configurations remained. It's better to completely re-create your builder. You can specify the rebuild
building option to achieve this. For usage of building options, refer to Manually trigger building and its options.
Technically, this is to "re-create your base builder". For definition of "base builder", refer to Mechanism.
Sometimes, you don't need to re-create the base builder. You just need to link previous base builder to current "incremental builder".
Because the incremental builders used in build-inc
and build-package
jobs are reusing previous building state, the builder image may grow larger and larger. The builder itself could also fall into some error state. If so, you can re-link them from the base builder.
For rebase build-inc
, you can use the use_base
option to base it on the base builder.
For rebase build-package
, you can use the use_base
option to base it on the base builder, or you can use the use_inc
option to base it on previous incremental builder used in build-inc
.
There are two methods for manually triggering and specifying building options:
- Use tete1030/github-repo-dispatcher.
- Repository dispatch event ("Repo Dispatch" button, only support "master" branch)
- Specify your job name in the "Type" prompt
- Fill your options in the "Payload" prompt (in JSON), or leave "Payload" empty when no option is needed
- Deployment event ("Deploy" button, support any commit/branch/tag)
- Specify your job name in the "Task" prompt
- Specify your branch in the "Ref" prompt
- Fill your options in the "Payload" prompt (in JSON), or leave "Payload" empty when no option is needed
- Repository dispatch event ("Repo Dispatch" button, only support "master" branch)
- Including your command and options in your commit message (it must be the commit right before the push)
- You can specify your job name by including a string "#JOB_NAME#" in your latest commit message, e.g.
#build-package#
- You can enable boolean options by including a string "#BOOL_OPTION_NAME#" in your latest commit message, e.g.
#debug#
- You can combine job name and options. e.g.
#build-package##debug#
or#build-package#debug#
are both acceptable (becauseindexOf(commit_message, '#JOB_OR_OPT#')
is used for searching them).
- You can specify your job name by including a string "#JOB_NAME#" in your latest commit message, e.g.
All boolean options are by default false
. The following are options available.
debug
(bool): entering tmate during and after building, allowing you to SSH into the Actionspush_when_fail
(bool): always save the builder to Docker Hub even if the building process fails. Not recommended to use
rebuild
(bool): re-create the building environment completelyupdate_repo
(bool): dogit pull
on main repo. It could fail if any tracked file of the repo has changed.update_feeds
(bool): dogit pull
on feeds and your manually added packages. It could fail if any tracked file changed.use_base
(bool): instead of using the job's own previous builder, use latest base builder
update_feeds
(bool): same to previous sectionuse_base
(bool): same to previous sectionuse_inc
(bool): instead of using the job's own previous builder, use latest incremental builder generated bybuild-inc
To trigger rebase the incremental builder with SSH debugger enabled:
- Open your forked repo
- Click "Repo Dispatch" or "Deploy" at the top right corner (install at tete1030/github-repo-dispatcher)
- Fill
build-inc
in "Type/Task" prompt - If using "Deploy" trigger, fill your branch/tag/commit in "Ref" prompt (e.g.
master
) - Fill
{"use_base": true, "debug": true}
in "Payload" prompt - Open the job's log page, wait for the SSH command showing up (when debugging, you are allowed to SSH into the job's runner, with the help of tmate.io)
- Save all the files you changed
- At the last commit before push, commit with message "some message #build-inc#rebuild# some message"
- Push
- Wait for jobs to finish
[TODO] Probably a figure is better
For convenience, assume docker image for storing builder
IMAGE_NAME=tete1030/openwrt_x86_64
(abbreviated tot/o
)IMAGE_TAG=latest
There are three builders:
- When doing first-time building or rebuilding, the
build-inc
mode setups "base builder" and builds OpenWrt freshly. It produces a firmware and a "base builder". The builder is named ast/o:latest
and stored in Docker Hub. It is further linked tot/o:latest-inc
, which is an incremental build used for future use. - For every push, the
build-inc
mode setups "incremental buildert/o:latest-inc
" based on its own previous "incremental buildert/o:latest-inc
" (same name). It also builds a new firmware. Finally it saves back the new builder to Docker Hub, overwriting the old one. - For every push, the
build-package
mode setups "incremental buildert/o:latest-package
" based on its own previous "incremental buildert/o:latest-package
" (same name). If the previous one does not exist, it uses the base builder. This mode also builds packages (*.ipkg). Finally it saves back the new builder to Docker Hub, overwriting the old one.
openwrt/openwrt;openwrt-19.07:
I'll now explain here the detailed building process of each mode.
- Pull
${BUILDER_NAME}:${BUILDER_TAG}-inc
from Docker Hub. If the tag does not exist oruse_base
building option is set, link${BUILDER_NAME}:${BUILDER_TAG}
to${BUILDER_NAME}:${BUILDER_TAG}-inc
. If${BUILDER_NAME}:${BUILDER_TAG}
also does not exist, set building optionrebuild
totrue
. initenv.sh
, set up building environment only whenrebuild
.update_repo.sh
. It will dogit clone
orgit pull
for main repo only whenupdate_repo
orrebuild
option is setupdate_feeds.sh
. It will download you manually added packages, and dogit pull
for existing packages only whenupdate_feeds
option is set.customize.sh
. Apply patches only when a patch has not been already applied. Loadconfig.diff
to.config
, executemake defconfig
download.sh
, download/update package source code that are not already downloadedcompile.sh
, Multi/single-thread compile- Save this new builder to Docker Hub's
${BUILDER_NAME}:${BUILDER_TAG}-inc
. Ifrebuild
, link it back to${BUILDER_NAME}:${BUILDER_TAG}
- Copy out from docker and upload files to Artifacts
OpenWrt_bin
: all binaries files, including packages and firmwaresOpenWrt_firmware
: firmware only
- Pull
${BUILDER_NAME}:${BUILDER_TAG}-package
from Docker Hub. If the tag does not exist or whenuse_base
option is set, link current${BUILDER_NAME}:${BUILDER_TAG}
to${BUILDER_NAME}:${BUILDER_TAG}-package
(Or link${BUILDER_NAME}:${BUILDER_TAG}-inc
to${BUILDER_NAME}:${BUILDER_TAG}-package
when theuse_inc
option is set) - Unlike other building processes,
update_repo.sh
is not executed update_feeds.sh
. It will always download you manually added packages, and dogit pull
for existing packages only whenupdate_feeds
option is set.customize.sh
, apply patches only when a patch has not been already applieddownload.sh
, download/update package source code that are not already downloadedcompile.sh
, Multi/single-thread compile- Save this new builder to Docker Hub's
${BUILDER_NAME}:${BUILDER_TAG}-package
- Upload files to Artifacts
OpenWrt_packages
: all packagesOpenWrt_new_packages
: only newly produced packages of this building
All tags actually exist but could be invisible. Caused by known problem of buildx:
- Merge three building modes into one to simplify the process
- SSH into docker container instead of just the runner (for
make menuconfig
) - Allow customizing trigger event
- Allow specify building job in commit message
- Automatically linking from base builder to builders for
build-inc
andbuild-package
when not existing - Optimize README
- Simplfy documentation
- Add Chinese version of "Usage"
- Add a figure to "Mechanism"
- Describe mechanism
- Describe building process
- Describe using tete1030/github-repo-dispatcher to trigger building with extra options
- Optimize comments in
build-openwrt.yml
anddocker.sh
- Optimize
build-openwrt.yml
, making options cleaner - Allow deterministic building (by fixing commit of main repo and feeds)
- P3TERX's Actions-Openwrt
- crazy-max/ghaction-docker-buildx
- Docker Hub
- Microsoft Azure
- GitHub Actions
- tmate
- mxschmitt/action-tmate
- csexton/debugger-action
- OpenWrt
- Lean's OpenWrt
Most files under
MIT © Texot
Original idea and some files under
MIT © P3TERX