I have largely optimized the main building process. It is now easier to use.
This project is most useful for people who modify the compiling settings frequently, and may need to compile new packages from time to time. It by default does not update OpenWrt's and packages' source code every time it builds (unless you specified), because doing so harms incremental building‘s utility and stability.
If you don't like this, do not care about long compiling duration, or feel that the following instructions are complex, check out P3TERX's Actions-Openwrt or KFERMercer's OpenWrt-CI. They are very easy to use except for the compiling duration.
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.
- 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)
- Handy debugging and manual configuration through SSH (e.g.
make menuconfig
)
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, for debug) Set
SLACK_WEBHOOK_URL
orTMATE_ENCRYPT_PASSWORD
in the Secrets page. Refer to Debug and manually configure. - (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
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
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 docker container and Actions. See Debug and manually configure for detailed usage.push_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 rebasing 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). This mode builds a new firmware and packages. 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 only builds packages (*.ipkg), no firmware is built. 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
Thanks to tmate, you can enter into both the docker containers and GitHub Actions runners through SSH to debug and manually change your configuration, e.g. make menuconfig
. To enter the mode, you have to enable the building option: debug
. See Manually trigger building and its options for methods of using options.
For safety of your sensitive information, you must either set SLACK_WEBHOOK_URL
or TMATE_ENCRYPT_PASSWORD
in the Secrets page to protect the tmate connection info. Refer to tete1030/debugger-action/README.md for details.
Note that the configuration changes you made should only be for temporary use. Though your changes in the docker container will be saved to Docker Hub, there are situations where you manual configuration may lost:
- The
rebuild
option is set to completely rebuild your base builder and rebase the incremental builder - The
use_base
oruse_inc
option is set to rebase the incremental builder - Some files will be overwriten during every building. For example, if you have executed
make menuconfig
in the container, the changes of the.config
file will be saved. But during next building, theconfig.diff
file in this repo will be copied to.config
. This will overwrite your previous changes.
To make permanent changes, it is still recommended to use the config.diff
file and other customization methods provided in this repo.
All tags actually exist but could be invisible. Caused by known problem of buildx:
- Merge building modes 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