├── .ruff.toml ├── requirements-dev.txt ├── .dockerignore ├── docker ├── buildworker │ ├── files │ │ ├── entry.sh │ │ └── start.sh │ └── Dockerfile ├── rsync │ ├── Dockerfile │ └── files │ │ └── entry.sh ├── buildmaster │ ├── files │ │ ├── entry.sh │ │ └── start.sh │ └── Dockerfile ├── certs │ ├── buildmaster-phase1.crt │ ├── buildmaster-phase2.crt │ ├── ca.crt │ ├── ca.key │ ├── buildmaster-phase1.key │ └── buildmaster-phase2.key ├── docker-compose.yml └── config.ini ├── README.md ├── .gitlab ├── docker │ ├── README.md │ ├── buildmaster │ │ └── gitlab.yml │ └── buildworker │ │ └── gitlab.yml └── docker.yml ├── .flake8 ├── tests └── cram │ ├── master │ ├── 02-apk.t │ └── 01-logs.t │ └── worker │ └── 01-logs.t ├── scripts ├── rsync.sh ├── sec2pubkey.pl ├── ccache.sh ├── findbin.pl ├── cleanup.sh ├── sha2rsync.pl ├── makebranch.sh └── signall.sh ├── .gitlab-ci.yml ├── .github ├── dependabot.yml └── workflows │ └── build-push.yml ├── .gitignore ├── phase1 ├── buildbot.tac ├── config.ini.example └── master.cfg └── phase2 ├── buildbot.tac ├── config.ini.example └── master.cfg /.ruff.toml: -------------------------------------------------------------------------------- 1 | ignore = ["E501"] 2 | -------------------------------------------------------------------------------- /requirements-dev.txt: -------------------------------------------------------------------------------- 1 | cram==0.7 2 | black==23.12.1 3 | ruff==0.1.9 4 | flake8==6.1.0 5 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | docker/rsync 2 | !docker/rsync/files 3 | docker/build 4 | docker/docker-compose.yml 5 | -------------------------------------------------------------------------------- /docker/buildworker/files/entry.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | chown buildbot:buildbot /builder 4 | 5 | /usr/sbin/gosu buildbot "$@" 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OpenWrt buildbot configuration 2 | 3 | This repository provides containers used for building OpenWrt at https://buildbot.openwrt.org 4 | -------------------------------------------------------------------------------- /.gitlab/docker/README.md: -------------------------------------------------------------------------------- 1 | # Content 2 | 3 | This directory contains bits for Docker images used on the GitLab CI. 4 | 5 | ## buildmaster 6 | ## buildworker 7 | -------------------------------------------------------------------------------- /.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | max-line-length = 140 3 | per-file-ignores = 4 | phase2/master.cfg: E101,E117,E128,E201,E202,E203,E221,E225,E251,E266,E302,E305,E501,W191 5 | -------------------------------------------------------------------------------- /tests/cram/master/02-apk.t: -------------------------------------------------------------------------------- 1 | Check that apk is available and usable in master container: 2 | 3 | $ docker run --entrypoint apk local/master | grep usage 4 | usage: apk [...] COMMAND [...] 5 | -------------------------------------------------------------------------------- /scripts/rsync.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -x 2 | 3 | export LC_ALL=C 4 | 5 | set -o pipefail 6 | 7 | PV=`which pv` 8 | RSYNC=rsync 9 | 10 | if [[ -x $PV ]]; then 11 | $RSYNC "$@" | $PV -t -i 60 -f 12 | else 13 | $RSYNC "$@" 14 | fi 15 | -------------------------------------------------------------------------------- /tests/cram/master/01-logs.t: -------------------------------------------------------------------------------- 1 | Check that logs have expected content after container startup: 2 | 3 | $ docker logs test-master 4 | updating existing installation 5 | creating /master/master.cfg.sample 6 | creating database (sqlite:///state.sqlite) 7 | buildmaster configured in /master 8 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | variables: 2 | BUILDBOT_VERSION: 3.5.0 3 | OPENWRT_VERSION: $CI_COMMIT_SHORT_SHA 4 | 5 | include: 6 | - local: .gitlab/docker.yml 7 | - local: .gitlab/docker/buildmaster/gitlab.yml 8 | - local: .gitlab/docker/buildworker/gitlab.yml 9 | 10 | stages: 11 | - docker 12 | - docker test 13 | - docker deploy 14 | -------------------------------------------------------------------------------- /docker/rsync/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM debian:12 2 | 3 | COPY docker/rsync/files/entry.sh /entry.sh 4 | 5 | RUN apt-get update && \ 6 | apt-get -y install rsync && \ 7 | apt-get clean && \ 8 | mkdir -p /data && \ 9 | chmod 0755 /entry.sh 10 | 11 | EXPOSE 873 12 | VOLUME [ "/data" ] 13 | ENTRYPOINT [ "/entry.sh" ] 14 | HEALTHCHECK CMD xargs kill -0 < /tmp/rsyncd.pid 15 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # Set update schedule for GitHub Actions 2 | 3 | version: 2 4 | updates: 5 | 6 | - package-ecosystem: "github-actions" 7 | directory: "/" 8 | schedule: 9 | # Check for updates to GitHub Actions every week 10 | interval: "weekly" 11 | # Prefix all commit messages with "CI" plus its scope, that is, a 12 | # list of updated dependencies 13 | commit-message: 14 | prefix: "CI" 15 | include: "scope" 16 | -------------------------------------------------------------------------------- /tests/cram/worker/01-logs.t: -------------------------------------------------------------------------------- 1 | Check that logs have expected content after container startup: 2 | 3 | $ docker logs test-worker 4 | updating existing installation 5 | mkdir /builder/info 6 | Creating info/admin, you need to edit it appropriately. 7 | Creating info/host, you need to edit it appropriately. 8 | Not creating info/access_uri - add it if you wish 9 | Please edit the files in /builder/info appropriately. 10 | worker configured in /builder 11 | -------------------------------------------------------------------------------- /docker/buildmaster/files/entry.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | for dir in /master /config /certs /home/buildbot; do 4 | [ -d "$dir" ] || continue 5 | 6 | chown --recursive buildbot:buildbot "$dir" 7 | chmod 0700 "$dir" 8 | done 9 | 10 | if [ -S "/home/buildbot/.gnupg/S.gpg-agent" ]; then 11 | chown buildbot:buildbot /home/buildbot/.gnupg/S.gpg-agent 12 | chmod 0600 /home/buildbot/.gnupg/S.gpg-agent 13 | fi 14 | 15 | /usr/sbin/gosu buildbot /start.sh "$@" 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | !.dockerignore 4 | !build-docker-images.sh 5 | !docker 6 | !docker/* 7 | !docker/*/* 8 | !docker/*/*/* 9 | docker/build 10 | !scripts 11 | !scripts/* 12 | !phase[12] 13 | !phase[12]/* 14 | phase[12]/*/* 15 | phase[12]/config.ini 16 | phase[12]/http.log 17 | phase[12]/key-build* 18 | phase[12]/state.sqlite* 19 | phase[12]/twistd.* 20 | !.gitlab-ci.yml 21 | !.gitlab 22 | !.gitlab/* 23 | !.gitlab/**/* 24 | !.github 25 | !.github/**/* 26 | !requirements-dev.txt 27 | !.ruff.toml 28 | !tests 29 | !tests/**/* 30 | !.flake8 31 | -------------------------------------------------------------------------------- /scripts/sec2pubkey.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | 3 | use strict; 4 | use MIME::Base64; 5 | 6 | my @lines = (-t STDIN) ? () : <>; 7 | 8 | if (@lines == 0) { 9 | die "Usage: $0 < key.sec > key.pub\n"; 10 | } 11 | 12 | my $seckey = decode_base64(pop @lines); 13 | my $comment = shift(@lines) || "untrusted comment: secret key"; 14 | 15 | chomp($comment); 16 | 17 | $comment =~ s/\bsecret key$/public key/; 18 | 19 | if (length($seckey) != 104) { 20 | die "Unexpected secret key length\n"; 21 | } 22 | 23 | my $pubkey = encode_base64(substr($seckey, 0, 2) . substr($seckey, 32, 8) . substr($seckey, 72), ""); 24 | 25 | printf "%s\n%s\n", $comment, $pubkey; 26 | -------------------------------------------------------------------------------- /scripts/ccache.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | export LC_ALL=C 4 | 5 | mkdir -p "$HOME/.ccache" || exit 1 6 | 7 | grep -sq max_size "$HOME/.ccache/ccache.conf" || \ 8 | echo "max_size = 10.0G" >> "$HOME/.ccache/ccache.conf" || exit 1 9 | 10 | grep -sq compiler_check "$HOME/.ccache/ccache.conf" || \ 11 | echo "compiler_check = %compiler% -dumpmachine; %compiler% -dumpversion" >> "$HOME/.ccache/ccache.conf" || exit 1 12 | 13 | for dir in $(make --no-print-directory val.TOOLCHAIN_DIR val.STAGING_DIR val.STAGING_DIR_HOST V=s | grep staging_dir/); do 14 | if [ ! -L "$dir/ccache" ] || [ -L "$dir/ccache" -a ! -d "$dir/ccache" ]; then 15 | mkdir -vp "$dir" || exit 1 16 | rm -vrf "$dir/ccache" || exit 1 17 | ln -vs "$HOME/.ccache" "$dir/ccache" || exit 1 18 | fi 19 | done 20 | 21 | exit 0 22 | -------------------------------------------------------------------------------- /docker/buildmaster/files/start.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | case "${1:-start}" in 4 | reconfig) 5 | exec /opt/venv/bin/buildbot reconfig /master 6 | ;; 7 | start) 8 | case "${BUILDMASTER_PHASE:-1}" in 9 | 1|2) 10 | cp /phase${BUILDMASTER_PHASE:-1}/config.ini.example /master/ 11 | ;; 12 | *) 13 | echo "Invalid BUILDMASTER_PHASE given. Must be either '1' or '2'" >&2 14 | exit 1 15 | ;; 16 | esac 17 | 18 | /opt/venv/bin/buildbot create-master --config=/phase${BUILDMASTER_PHASE:-1}/master.cfg /master 19 | 20 | unset BUILDMASTER_PHASE 21 | 22 | rm -f /master/twistd.pid 23 | exec /opt/venv/bin/buildbot start --nodaemon /master 24 | ;; 25 | /*) 26 | exec "$@" 27 | ;; 28 | *) 29 | echo "Unknown command given. Must be either 'start' or 'reconfig'" >&2 30 | exit 1 31 | ;; 32 | esac 33 | -------------------------------------------------------------------------------- /.gitlab/docker/buildmaster/gitlab.yml: -------------------------------------------------------------------------------- 1 | build Docker image buildmaster: 2 | stage: docker 3 | extends: .build Docker image 4 | 5 | test Docker image buildmaster: 6 | stage: docker test 7 | extends: .docker in docker 8 | needs: ["build Docker image buildmaster"] 9 | script: 10 | - export IMAGE_NAME="$(echo $CI_JOB_NAME | sed 's/test Docker image \(.*\)/\1/')" 11 | - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY 12 | - docker pull "$CI_REGISTRY_IMAGE/$IMAGE_NAME-$BUILDBOT_VERSION:$CI_COMMIT_REF_SLUG" 13 | - > 14 | docker run --rm "$CI_REGISTRY_IMAGE/$IMAGE_NAME-$BUILDBOT_VERSION:$CI_COMMIT_REF_SLUG" | 15 | grep "buildmaster configured in /master" 16 | 17 | deploy Docker image buildmaster: 18 | stage: docker deploy 19 | extends: .deploy Docker image 20 | needs: ["test Docker image buildmaster"] 21 | -------------------------------------------------------------------------------- /docker/rsync/files/entry.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ( 4 | echo "use chroot = yes" 5 | echo "[${SHARE_NAME:-data}]" 6 | echo "log file = /dev/null" 7 | echo "uid = ${SHARE_UID:-1000}" 8 | echo "gid = ${SHARE_GID:-1000}" 9 | echo "path = /data" 10 | echo "read only = false" 11 | echo "write only = false" 12 | echo "comment = ${SHARE_COMMENT:-Rsync data share}" 13 | 14 | if [ -n "$SHARE_USER" -a -n "$SHARE_PASSWORD" ]; then 15 | echo "auth users = $SHARE_USER" 16 | echo "secrets file = /rsyncd.secrets" 17 | fi 18 | ) > /rsyncd.conf 19 | 20 | if [ -n "$SHARE_USER" -a -n "$SHARE_PASSWORD" ]; then 21 | echo "$SHARE_USER:$SHARE_PASSWORD" > /rsyncd.secrets 22 | chmod 0600 /rsyncd.secrets 23 | fi 24 | 25 | chown "${SHARE_UID:-1000}:${SHARE_GID:-1000}" /data 26 | 27 | rm -f /tmp/rsyncd.pid 28 | 29 | exec /usr/bin/rsync --daemon --no-detach --config=/rsyncd.conf --log-file=/dev/stdout --dparam=pidfile=/tmp/rsyncd.pid "$@" 30 | -------------------------------------------------------------------------------- /.gitlab/docker/buildworker/gitlab.yml: -------------------------------------------------------------------------------- 1 | build Docker image buildworker: 2 | stage: docker 3 | extends: .build Docker image 4 | 5 | .test Docker image buildworker: 6 | stage: docker test 7 | extends: .docker in docker 8 | needs: ["build Docker image buildworker"] 9 | script: 10 | - export IMAGE_NAME="$(echo $CI_JOB_NAME | sed 's/test Docker image \(.*\)/\1/')" 11 | - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY 12 | - docker pull "$CI_REGISTRY_IMAGE/$IMAGE_NAME-$BUILDBOT_VERSION:$CI_COMMIT_REF_SLUG" 13 | - > 14 | docker run --rm --env BUILDWORKER_NAME=foo --env BUILDWORKER_PASSWORD=XXX 15 | "$CI_REGISTRY_IMAGE/$IMAGE_NAME-$BUILDBOT_VERSION:$CI_COMMIT_REF_SLUG" | 16 | grep "worker configured in /builder" 17 | 18 | deploy Docker image buildworker: 19 | stage: docker deploy 20 | extends: .deploy Docker image 21 | #needs: ["test Docker image buildworker"] 22 | -------------------------------------------------------------------------------- /docker/buildworker/files/start.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | cleanup_buildworker_env_variables() { 4 | for var in "${!BUILDWORKER_@}"; do 5 | unset "$var" 6 | done 7 | } 8 | 9 | [ -n "$BUILDWORKER_NAME" ] || { 10 | echo "Please supply a name via --env BUILDWORKER_NAME=XXX" >&2 11 | exit 1 12 | } 13 | 14 | [ -n "$BUILDWORKER_PASSWORD" ] || { 15 | echo "Please supply a password via --env BUILDWORKER_PASSWORD=XXX" >&2 16 | exit 2 17 | } 18 | 19 | rm -f /builder/buildbot.tac 20 | 21 | /opt/venv/bin/buildbot-worker create-worker \ 22 | --force \ 23 | --umask="0o22" \ 24 | ${BUILDWORKER_TLS:+--connection-string="SSL:$BUILDWORKER_MASTER"} \ 25 | /builder \ 26 | "$BUILDWORKER_MASTER" \ 27 | "$BUILDWORKER_NAME" \ 28 | "$BUILDWORKER_PASSWORD" 29 | 30 | echo "$BUILDWORKER_ADMIN" > /builder/info/admin 31 | echo "$BUILDWORKER_DESCRIPTION" > /builder/info/host 32 | 33 | cleanup_buildworker_env_variables 34 | rm -f /builder/twistd.pid 35 | exec /opt/venv/bin/buildbot-worker start --nodaemon /builder 36 | -------------------------------------------------------------------------------- /phase1/buildbot.tac: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from twisted.application import service 4 | from buildbot.master import BuildMaster 5 | 6 | basedir = '.' 7 | rotateLength = 10000000 8 | maxRotatedFiles = 10 9 | configfile = 'master.cfg' 10 | 11 | # Default umask for server 12 | umask = None 13 | 14 | # if this is a relocatable tac file, get the directory containing the TAC 15 | if basedir == '.': 16 | import os 17 | basedir = os.path.abspath(os.path.dirname(__file__)) 18 | 19 | # note: this line is matched against to check that this is a buildmaster 20 | # directory; do not edit it. 21 | application = service.Application('buildmaster') 22 | from twisted.python.logfile import LogFile 23 | from twisted.python.log import ILogObserver, FileLogObserver 24 | logfile = LogFile.fromFullPath(os.path.join(basedir, "twistd.log"), rotateLength=rotateLength, 25 | maxRotatedFiles=maxRotatedFiles) 26 | application.setComponent(ILogObserver, FileLogObserver(logfile).emit) 27 | 28 | m = BuildMaster(basedir, configfile, umask) 29 | m.setServiceParent(application) 30 | m.log_rotation.rotateLength = rotateLength 31 | m.log_rotation.maxRotatedFiles = maxRotatedFiles 32 | -------------------------------------------------------------------------------- /phase2/buildbot.tac: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from twisted.application import service 4 | from buildbot.master import BuildMaster 5 | 6 | basedir = '.' 7 | rotateLength = 10000000 8 | maxRotatedFiles = 10 9 | configfile = 'master.cfg' 10 | 11 | # Default umask for server 12 | umask = None 13 | 14 | # if this is a relocatable tac file, get the directory containing the TAC 15 | if basedir == '.': 16 | import os 17 | basedir = os.path.abspath(os.path.dirname(__file__)) 18 | 19 | # note: this line is matched against to check that this is a buildmaster 20 | # directory; do not edit it. 21 | application = service.Application('buildmaster') 22 | from twisted.python.logfile import LogFile 23 | from twisted.python.log import ILogObserver, FileLogObserver 24 | logfile = LogFile.fromFullPath(os.path.join(basedir, "twistd.log"), rotateLength=rotateLength, 25 | maxRotatedFiles=maxRotatedFiles) 26 | application.setComponent(ILogObserver, FileLogObserver(logfile).emit) 27 | 28 | m = BuildMaster(basedir, configfile, umask) 29 | m.setServiceParent(application) 30 | m.log_rotation.rotateLength = rotateLength 31 | m.log_rotation.maxRotatedFiles = maxRotatedFiles 32 | -------------------------------------------------------------------------------- /docker/certs/buildmaster-phase1.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDbjCCAlYCFBczjElNehQ1sSWjdvGyPBET3j3eMA0GCSqGSIb3DQEBCwUAMGgx 3 | CzAJBgNVBAYTAlhYMQ4wDAYDVQQIDAVXb3JsZDEiMCAGA1UECgwZQnVpbGRib3Qg 4 | Q29tcG9zZXIgVGVzdGluZzElMCMGA1UECwwcQnVpbGRib3QgQ29tcG9zZXIgVGVz 5 | dGluZyBDQTAeFw0yMDAyMDMxNjUwMjlaFw0zMDAxMzExNjUwMjlaMH8xCzAJBgNV 6 | BAYTAlhYMQ4wDAYDVQQIDAVXb3JsZDEfMB0GA1UECgwWQnVpbGRib3QgQ29tcG9z 7 | ZXIgVGVzdDEiMCAGA1UECwwZQnVpbGRib3QgQ29tcG9zZXIgVGVzdCBDQTEbMBkG 8 | A1UEAwwSYnVpbGRtYXN0ZXItcGhhc2UxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A 9 | MIIBCgKCAQEAq1b4I44iYmhue1+IPSdeqcK7IL+INl/l2EE1Yw51Z+fPazkZdpiw 10 | +ZkB+dOdhiOL4+LW9SnrCUQ5CBOW8unG+nG7mvi63Pv61G5WLGlqW1pl6+Rt2Cpc 11 | CIhDcxRB+xzt1Yiu+BT+EIZO8NCLl+NHPgNrB1b2B8WmIEfWp/zEtaCTROWsHnax 12 | 1LUaP/mis1exRA1ITCNMwb1drP1eWRw99zGP2ax7nnju4zRK4QiQj3V/SNXqprvS 13 | kAAEogMtnsC6LIqPDABz/lcrfXhbbi4+MGmcy1Wz6ukDkusDf0jhssjVl29d9kL2 14 | grLohPHbmsQqEsumd6/6KUkybwHkdPQc0QIDAQABMA0GCSqGSIb3DQEBCwUAA4IB 15 | AQCd89o+MOX3//XtgsreITq8PVbY8MEATEbd1Q5F0VgMvzVMh0Agzy5zfvNtPfUK 16 | Grj2kTuL9H1TlPvIJ9x4+n6mqbXp46ajIWWlJ22lCV1vgtvA245YnmZKPlFw1FtS 17 | GU0AaIU76VLmlb6NH6sMdRX3/11WpdUJd46kyf/hkXlwk/sG7XR+IVB7cyE/iufq 18 | TTyGU9cUSEq6baYUOW2mVl91XCY2l9s7ZCIAG0MKw7aA0nOBfIutAhnXhhcWjUvp 19 | 9KOkUx14REM7x5mTtiAUwjs7d/6JDT+k2giWm01ca9Wyf2x2kND4fJOepAHIzXBI 20 | fRN/b8wrmWeAyFMBg6v/HG3u 21 | -----END CERTIFICATE----- 22 | -------------------------------------------------------------------------------- /docker/certs/buildmaster-phase2.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDbjCCAlYCFBczjElNehQ1sSWjdvGyPBET3j3fMA0GCSqGSIb3DQEBCwUAMGgx 3 | CzAJBgNVBAYTAlhYMQ4wDAYDVQQIDAVXb3JsZDEiMCAGA1UECgwZQnVpbGRib3Qg 4 | Q29tcG9zZXIgVGVzdGluZzElMCMGA1UECwwcQnVpbGRib3QgQ29tcG9zZXIgVGVz 5 | dGluZyBDQTAeFw0yMDAyMDMxNjUwMzdaFw0zMDAxMzExNjUwMzdaMH8xCzAJBgNV 6 | BAYTAlhYMQ4wDAYDVQQIDAVXb3JsZDEfMB0GA1UECgwWQnVpbGRib3QgQ29tcG9z 7 | ZXIgVGVzdDEiMCAGA1UECwwZQnVpbGRib3QgQ29tcG9zZXIgVGVzdCBDQTEbMBkG 8 | A1UEAwwSYnVpbGRtYXN0ZXItcGhhc2UyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A 9 | MIIBCgKCAQEAzuwsg3UgB1/xlhuOPF1uXkmsooEyof+/x0rZhDDURCPr8bjGUvzr 10 | WsHcKqrQCujVslVFDSqusmrhM2ONFaIbr3dGSPXBbCRfT6pi6f6XcvPtaeWcOA/g 11 | rXqb7wVUQf8t31lQhWexqmc2lietF6wC2iBOvi7/G352NkYOwy+cyodq9VUQkvT2 12 | BmL/B9On4SQkhblhovN4TtcvyRNuT87J+4yn8GmAu586Gss5xhvFIxnr016vxA/M 13 | NShKLGjsgWzn6THaJTTtAQYlBpRSkoFo+mOXHXqB/WSU0MNDybxu3Puqha8vRFMT 14 | crynEuGya9bpUMdvBedDDmH7aCmUJp0lIQIDAQABMA0GCSqGSIb3DQEBCwUAA4IB 15 | AQC/DWvwWNUBAD8znaIcNPYO3Ua4UL/ozERuij5VvZjf9ic0Pzq92qLQkTyDIlGP 16 | 7hL4Tp3g/PaGTg8A4LZfTrt1sPOHXHYR0Ysiw5iYgcljsmUoKWsh6SFaPDS4JnFG 17 | tKE4FJ4YtZOgB2fo2yRuJTGQUDyEYCfpCvhUKlMpofFM2Y/Fu1xZR/c+dxsazNHe 18 | GOqPIRPcbXGcK97H3EasBJ7oHrGV3HqOjkT+Y936Esgr6Y/jJi9NVNeV6Fwu8nWj 19 | O16Q3Yxj1G28uMcbv54SbJ0DzdXfrVs8ylFYd4becVEx2h03qthBM5j70epaHvrP 20 | HFA34mxzOcCsZ3Gc+4qsAOQp 21 | -----END CERTIFICATE----- 22 | -------------------------------------------------------------------------------- /docker/certs/ca.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDsTCCApmgAwIBAgIUUmlVvmL3Dz698ZIH9IZ95NfWyW8wDQYJKoZIhvcNAQEL 3 | BQAwaDELMAkGA1UEBhMCWFgxDjAMBgNVBAgMBVdvcmxkMSIwIAYDVQQKDBlCdWls 4 | ZGJvdCBDb21wb3NlciBUZXN0aW5nMSUwIwYDVQQLDBxCdWlsZGJvdCBDb21wb3Nl 5 | ciBUZXN0aW5nIENBMB4XDTIwMDIwMzE2NTAxNVoXDTI5MTEwMjE2NTAxNVowaDEL 6 | MAkGA1UEBhMCWFgxDjAMBgNVBAgMBVdvcmxkMSIwIAYDVQQKDBlCdWlsZGJvdCBD 7 | b21wb3NlciBUZXN0aW5nMSUwIwYDVQQLDBxCdWlsZGJvdCBDb21wb3NlciBUZXN0 8 | aW5nIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyZNSkk631K+0 9 | A+R8HJszw0hqWQo46E3SfYpc746JejXhhrASpKiOHZo2TLuQ4g1XBHsUbY3yt3kp 10 | wW3IR/WomxecfadM+g9JPWNzmAvrhqvE9SFrp6uC0q70Kz9huYq8mu+/n6uds+Bt 11 | RJfdGXxzUMCpUmtlybTqT11nkkRYtWyH/l+PHDpephrqCXd7Zx47q9d4ypavo584 12 | nQ68bV8xosSM/SL1Yo7tkP64WQEsvuA6nhpXIjnlpHVsKhnxxuFGgDGqAkiogdjY 13 | hHIqSRngIlG1yQSATMgyiINYqvloFR0/q1CoU15021l5OnA3ddshYivCPWZIFvNN 14 | eTkF5dxpQQIDAQABo1MwUTAdBgNVHQ4EFgQUe9rUZI62smrqO3x4BOxRJDjuYP8w 15 | HwYDVR0jBBgwFoAUe9rUZI62smrqO3x4BOxRJDjuYP8wDwYDVR0TAQH/BAUwAwEB 16 | /zANBgkqhkiG9w0BAQsFAAOCAQEAPzvuWMXNuP9mTHQ9Jni2ytMXjtvW70G6QUVM 17 | 36JssU7S2kyGGtXepgtuqQ1qwCcU+IZUhbGjr8uoD6hnD/GFxHO1SAJFM1E1qw+U 18 | 2aUreE/DjSLJPj3aHorw19tpnEhzGhd3sK4IruI2iyzm7bBrHjT27u7Vhb5T9O1Q 19 | HWjcM80ntuBZBWZoIb8SCQSXJF0bVSwXEPtr1l6t5iSbe9GDS4BrrRedCIEOlCk4 20 | 2WiKi1gACmxmI9Tz8alZPpzuxWs10Ft6FVHjLsH6ovDjMCBwxie2HxUaIzUK9Huq 21 | X4j0ifxFUcknI5YTWM/zUSWqFJo2aBgsgq7Q9VVr+D2UiBjSVQ== 22 | -----END CERTIFICATE----- 23 | -------------------------------------------------------------------------------- /scripts/findbin.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | 3 | use strict; 4 | use warnings; 5 | 6 | sub vernum($) { 7 | if ($_[0] =~ m!^((?:\d+\.)+\d+)$!) { 8 | my ($maj, $min) = split /\./, $1; 9 | return int($maj) * 256 + int($min); 10 | } 11 | 12 | return 0; 13 | } 14 | 15 | sub vercmp($$$) { 16 | my ($op, $v1, $v2) = @_; 17 | 18 | if ($op eq 'lt') { return $v1 < $v2 } 19 | elsif ($op eq 'le') { return $v1 <= $v2 } 20 | elsif ($op eq 'gt') { return $v1 > $v2 } 21 | elsif ($op eq 'ge') { return $v1 >= $v2 } 22 | elsif ($op eq 'eq') { return $v1 == $v2 } 23 | 24 | return 0; 25 | } 26 | 27 | sub findbin($$$) { 28 | my ($basename, $compare, $maxvstr) = @_; 29 | 30 | my $lastversion = 0; 31 | my $cmpversion = vernum($maxvstr); 32 | my $prog = undef; 33 | 34 | foreach my $dir (split /:/, $ENV{'PATH'}) { 35 | foreach my $bin (glob("$dir/$basename?*"), "$dir/$basename") { 36 | if (-x $bin && open BIN, '-|', $bin, '--version') { 37 | my $vers = 0; 38 | my $line = readline(BIN) || ''; 39 | 40 | foreach my $token (split /\s+/, $line) { 41 | $vers = vernum($token); 42 | last if $vers > 0; 43 | } 44 | 45 | if ($vers > 0 && (!$cmpversion || vercmp($compare, $vers, $cmpversion))) { 46 | if ($vers > $lastversion) { 47 | $lastversion = $vers; 48 | $prog = $bin; 49 | } 50 | } 51 | 52 | close BIN; 53 | } 54 | } 55 | } 56 | 57 | return $prog; 58 | } 59 | 60 | my $bin = findbin($ARGV[0], $ARGV[1], $ARGV[2]); 61 | 62 | if (defined $bin) { 63 | printf "%s\n", $bin; 64 | exit 0; 65 | } 66 | else { 67 | warn "Cannot find a $ARGV[0] command with version $ARGV[1] $ARGV[2]\n"; 68 | exit 1; 69 | } 70 | -------------------------------------------------------------------------------- /docker/certs/ca.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEowIBAAKCAQEAyZNSkk631K+0A+R8HJszw0hqWQo46E3SfYpc746JejXhhrAS 3 | pKiOHZo2TLuQ4g1XBHsUbY3yt3kpwW3IR/WomxecfadM+g9JPWNzmAvrhqvE9SFr 4 | p6uC0q70Kz9huYq8mu+/n6uds+BtRJfdGXxzUMCpUmtlybTqT11nkkRYtWyH/l+P 5 | HDpephrqCXd7Zx47q9d4ypavo584nQ68bV8xosSM/SL1Yo7tkP64WQEsvuA6nhpX 6 | IjnlpHVsKhnxxuFGgDGqAkiogdjYhHIqSRngIlG1yQSATMgyiINYqvloFR0/q1Co 7 | U15021l5OnA3ddshYivCPWZIFvNNeTkF5dxpQQIDAQABAoIBAAxvbTmfZ5HUYQuY 8 | bdup63CRqBXkHoyeOG0MOx2AMpT6e/Y+KHhF+bZzzAPB0ndPkV2yZhk4F5AgBmZr 9 | al6eFg+zTjEmQAZxKPiDiR8JJTeCozzoGecXGpP6vQ9p8pJqr6XzQmQMR0dQgg0o 10 | PTiUR9zkdc2i2H2wDoBk573LP5m5gzRzGSJe4WvhFKKEjjae3CrHdMUYjOdu85D7 11 | qExvo45GaWN9uo0Ylgmt1jNkjO411cv9vAB6WTg1Lw93pV9blih4aoII5KXhk/3V 12 | gHhLElrxrLs4ckeG19fUHEs/xuFaFPPMWhPf5crGvtOP1UyzlNMvYsME7xQfEjEV 13 | VzLEDq0CgYEA9B8zq9BC5YIPtEpiuwgNYmIYx5KY5BMfwuE3jW/BG5E6T+wOAT9a 14 | Ohw5iOKetUYmYyPQn1KWHzumXG/lMkrdsRCffZVpdMJSl+/E0F8l6M6spwpbtCD7 15 | 724pWusWP+gZEXyeo2Sos32euzJs8b5NrMUL4XPbXdoZVGIXfoeFNp8CgYEA02Io 16 | 8C8nzIwsGnsw0aV45VdyGrywOqCnSarrjfa4PNNMljn6i/0D//4N8mh4Ws2WsvQU 17 | qChkKITlpkJsq0kLZxUdWcvzvNlH9EFBHoiImUvq+5DOD5ucr5b3hZwrtnI6C76J 18 | oSB7BCAV8oDpMYwvtahRlkxQ+Lv8typIc8vNtB8CgYEAkblCbfB+zmPKHhQ9RWo0 19 | GyN1qURQMe1ci0dHkw0/18Xkair93S7FHGUWzyiAFrOOXKXXdhOle3VvBETjKxdX 20 | qMfEfQHAlqsdBIdjFAOILKWamIftX+REn5NB6nzkpjdVJ4Qdamm+7o4xP4uFTvUL 21 | hvOE+QrgyvBTKHT5k1UwZv8CgYBDg6KXtDf9+PdNLfOVwkgu2BM1vvZ6gz1rJhA+ 22 | M4L8ynA3uyTu+U0Bwl8qAXwPZIKxfYvreZsj5e6Df8u9mYLu1aueNqoOs0dsGDt4 23 | SRt3+ut+le16xrTw0EMWhZ7gkvM/NQg4Umt4EddwsQPKM4A5gR0t6Aokp8Y7qmGh 24 | uoJk+QKBgCMEeqEfsuQ8iYfeVNjxoZnTJsWN1cb/ZZzCfHx/Fbo1XXDchcB7MNNM 25 | 56Y6eVRs0tz9f+UNNnKaRNIjJUfqnibsInfBYf7wYJbG4azyD1jORCpf53srOAue 26 | 3gLVBrzUbaul5nRNHLVsTB7Io+vlNTlQ5PJ6OEblIQcZmukeQ9Fo 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /docker/certs/buildmaster-phase1.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEpQIBAAKCAQEAq1b4I44iYmhue1+IPSdeqcK7IL+INl/l2EE1Yw51Z+fPazkZ 3 | dpiw+ZkB+dOdhiOL4+LW9SnrCUQ5CBOW8unG+nG7mvi63Pv61G5WLGlqW1pl6+Rt 4 | 2CpcCIhDcxRB+xzt1Yiu+BT+EIZO8NCLl+NHPgNrB1b2B8WmIEfWp/zEtaCTROWs 5 | Hnax1LUaP/mis1exRA1ITCNMwb1drP1eWRw99zGP2ax7nnju4zRK4QiQj3V/SNXq 6 | prvSkAAEogMtnsC6LIqPDABz/lcrfXhbbi4+MGmcy1Wz6ukDkusDf0jhssjVl29d 7 | 9kL2grLohPHbmsQqEsumd6/6KUkybwHkdPQc0QIDAQABAoIBACuC64MD/mFlSeFU 8 | 0mFNVTHhPOpFGY9NbS4s6STdsB0R9k+xcXD3t8G7BJBwGAnPjx/xJEugOIri42TU 9 | rLnFen1xUoY5ciLabslxt7qRjqviWg28tdR2dWbJS++2jkb6Ar/+dQiVNCv4H6Xy 10 | H/ETi60I6y4y/Ene/KAn/jAs9bt1wD13wPFNHHHJes46719cqSuVMWBMW0qFJdBW 11 | xWxfeDNEKhRmby43gakzs3BNYtS5eHpmWXqYMhP34H+JURNa1tW1UWD1swqvyZKF 12 | WxXgU+ckvBJG2BLrF6LLLwDYtkwAJwPtA0arpaTs+9QBSvv1hC2G2rpPOrxKz/he 13 | c3ksIcECgYEA3rmkRXLZwTQKTZ1X90upgVJsHEQEuWmb2ETd/ED4rWfyfYaaFk7i 14 | 8bg7g8og9fUsso1gJOOXVgmwhCilKZrwau1xRDkmNOKYirh/35Rf8pEQKF7v3Njd 15 | htMN+OGuLUzqhbm9oH2d6B8VrJwAsgagpCURlCZWpvU5tmpKLaMrjDkCgYEAxPAJ 16 | kvQvCmTNXl4IUZX6sDmEywqpW1szV/ImdmVnUBkrdFQzw/IB8Mo61TW/fGv6+tlZ 17 | gKcLfvfEiP1BBuGHZY6e3ep6U0iN+KQhqsMIy8LnBqSep76E121bpwxrY08sW/R1 18 | gHDku3EAiwDns+dYydLK8QdouLcquL4/NxgtRVkCgYEAtem6ml6sLHls0OfqqTlL 19 | QS0o0A1eLnJrr8DP7vDCLB/yl0QRJpdYFUX8li/JrBqMX2nJVVfui39uhQMNo2XB 20 | aBR3ptlms1tAbE01ZE+z7lM9dzvTffZDOZO4ncb2lFl2U7LZhvQSvTxmX40rpDx1 21 | iJweN3r423T/plY6L/xN3UECgYEAsX4Ngu6kvt9e4KArKyzbBZyxfDWdsYKe4bKS 22 | y75UwLIOogeJqB4jdZsuLx8D9+VyDEd8DSGAkOxJq5Vk2AjHeNZzhFph6VHI8sEq 23 | vraM5OhCQ5B2lYR2QZqEMihVWOnwduf6Rsp4vB76eE1WhqQJN8zNrzIYRfJ/hIWi 24 | f8tAcfECgYEAqpryfEa4W7BXXxFusMCSgNpP7yBJ6x5p/UT1cZ8behVFJb78P4K5 25 | CPK2Pl+LGywEl+CHsbuPAyPzEU66/kwVN66F2W4Jz+n3QWuM1ZK8VWwF2piQL4lz 26 | wDTlzlYLBy3RLLOR4Zgs7wS8emkRhkGH7gZh0QL0//3PmH1gzzVQPSY= 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /docker/certs/buildmaster-phase2.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEpQIBAAKCAQEAzuwsg3UgB1/xlhuOPF1uXkmsooEyof+/x0rZhDDURCPr8bjG 3 | UvzrWsHcKqrQCujVslVFDSqusmrhM2ONFaIbr3dGSPXBbCRfT6pi6f6XcvPtaeWc 4 | OA/grXqb7wVUQf8t31lQhWexqmc2lietF6wC2iBOvi7/G352NkYOwy+cyodq9VUQ 5 | kvT2BmL/B9On4SQkhblhovN4TtcvyRNuT87J+4yn8GmAu586Gss5xhvFIxnr016v 6 | xA/MNShKLGjsgWzn6THaJTTtAQYlBpRSkoFo+mOXHXqB/WSU0MNDybxu3Puqha8v 7 | RFMTcrynEuGya9bpUMdvBedDDmH7aCmUJp0lIQIDAQABAoIBAQCiad3GkPhC0Zve 8 | JmLOHseyWkGWi7IiVYtB8g4pI+p4UXmwkUeZe8t/wQn+s3P4HCkfgK5iV04n3JxG 9 | qazjfgoc/5G7UqovJ51n+mUJJTvajnua0w57Mns3rzUVtykbZB+tX31EOM/K4JiH 10 | 4zyJiAn1C8bCoEC8Y9aFYxfTPFvk2lxYUh4mPe+rENRTQz6Ms4uVpXnOelcydLnA 11 | O3BpYE4GBZOT8+qWhiXI6ofuMGGno/h1s4gBfDpWpEDS/k00UHsArmur/+Wl7Ii3 12 | Mhd0+YwzBJu3hut9l5kXeS+vHAcdtjI6rN1tGIhC/bI5h1kUFuGWPyj8poZ6dS1a 13 | YKk1zCUBAoGBAOgCosDLzZfVBPjyD3S/c0rQzCSv/TCDS4jWYg4W8bcWTX5BnGHq 14 | d6Tq/7DqF7F444+GTX62kAcjEmKj0/ZV9sRI2rJ0cZVjJZLWf9PeJnn2sKRZnMKm 15 | Co1jWPx6j3ei1eszt+rHkNnSWSBvpvV00gnvVz/KeKXqrrKjRsXZ4BqNAoGBAORR 16 | dcNauLyqPPtQpwwdYWvbEAmmVyhwJ4AlJoDsvKD/bQ9HaI8eTyz1vt6nV13/EQPe 17 | Af6LXjAngx18AVUmxmgFGdxPzLrh3hwAzr+lD9b7+KDEzwBfsnYImKpS3B0UvHsn 18 | xKoKn7hVv7Uu7T+TU5heK3huE75/iBZye263LDnlAoGAWuSldFijq+cFcq4KRhe3 19 | CElyoLDdxUK6tdofQhvVCIBRTbRQmr+rrc1u7JVZQOr2Y8Ue2RSWqmUgD8rVAH2/ 20 | FjjgjOc3lGnqT3N/UraGZmOx4kFFO7CnE6snMoqlaB5AJkv1sqIKanuQ9TcotqLU 21 | opXEnbYpu/6MAGodEOgBdwUCgYEAlHSXIuf5WMtEjZCanZj5AH1XBz8+Ss/qDzuY 22 | tpm36ONMkXO3+98UUkKT0ghzGW5BLQeMumr6WktGyMQZxblJptcyQnssvpMgrYqk 23 | 5B26l+oMdtShWDfhPThHs+/eqZYTG+z2xi3UPrKazX9uyjjMUTViBJNmiSY5YYcc 24 | 1ReLTTUCgYEAyXL3k1vpoq2nKWk7SJ8/6C4YrsAbeeqQ2cJiUWPvO81Gxrgb4Tm1 25 | rNOKpXTrRj+4HQ5ovx8Oou4FyUFVL01p5bdKIMtZAXKqgPlqve1kB4rSAjhajiud 26 | J0+atj4hTgqQc8ZEOX6PVhLt35v9TQgiM3AV+e6Q6FmbooDj71DJ6x8= 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /phase2/config.ini.example: -------------------------------------------------------------------------------- 1 | [general] 2 | title = OpenWrt Project 3 | title_url = http://openwrt.org/ 4 | workdir = /buildbot 5 | 6 | [phase2] 7 | buildbot_url = http://phase2.builds.openwrt.org/ 8 | status_bind = tcp:8011:interface=127.0.0.1 9 | status_user = example 10 | status_password = example 11 | port = 9990 12 | persistent = false 13 | git_ssh = true 14 | git_ssh_key = -----BEGIN RSA PRIVATE KEY----- 15 | MIIEpAIBAAKCAQEAuCJwo6OmrRDxcGfsMgBhq0vdzp2ZIdqnedFH8u6tVYLt9WDU 16 | ... 17 | mHzkh8Uv4OAWTjiLGycbXa0/31hu9PCeNzYmjjrp8tcGjsiJJFxydgS+wc0i2UPV 18 | nSI+JbmAAF9vw6gj2i+Hqx7UloRd0tEv/leX354T5lO06LMiNhvN9g== 19 | -----END RSA PRIVATE KEY----- 20 | 21 | [repo] 22 | url = https://git.openwrt.org/openwrt/openwrt.git 23 | branch = main 24 | 25 | [rsync] 26 | binary_url = user@example.org::upload-packages 27 | binary_password = example 28 | source_url = user@example.org::upload-sources 29 | source_password = example2 30 | sdk_url = user@example.org::download-binary 31 | sdk_password = example3 32 | sdk_pattern = openwrt-sdk-*.tar.* 33 | 34 | [gpg] 35 | key = -----BEGIN PGP PRIVATE KEY BLOCK----- 36 | Version: GnuPG v2 37 | 38 | mQGNBFX4kxkBDACcTUVUl6zbn4r9tDap0/aCpcK9MO+HPatS7p2aBGY51kh78Ixr 39 | ... 40 | HwHLaFTMvYFY7WJDwA== 41 | -----END PGP PRIVATE KEY BLOCK----- 42 | passphrase = secret password 43 | comment = Unattended build signature 44 | 45 | [usign] 46 | key = RWRCSwAAA...OihABfuLvGRVfVaJ6wLf0= 47 | comment = Unattended build signature 48 | 49 | [apk] 50 | key = -----BEGIN EC PRIVATE KEY----- 51 | MHcCAQEEIIP54p1G0UgCleLObh07Gxq0S0Iz22OQpkUj8S1AzXB9oAoGCCqGSM49 52 | ... 53 | -----END EC PRIVATE KEY----- 54 | 55 | [worker 1] 56 | phase = 2 57 | name = worker-example-1 58 | password = example 59 | builds = 1 60 | 61 | [worker 2] 62 | phase = 2 63 | name = worker-example-2 64 | password = example2 65 | builds = 3 66 | -------------------------------------------------------------------------------- /docker/buildworker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM debian:11 2 | MAINTAINER OpenWrt Maintainers 3 | 4 | ARG DEBIAN_FRONTEND=noninteractive 5 | ARG BUILDBOT_VERSION=2.10.1 6 | ARG OPENWRT_VERSION=unknown 7 | 8 | ENV BUILDWORKER_MASTER builds.openwrt.org:9990 9 | ENV BUILDWORKER_ADMIN contact@openwrt.org 10 | ENV BUILDWORKER_DESCRIPTION Docker Container https://git.openwrt.org/$OPENWRT_VERSION 11 | 12 | USER root 13 | 14 | RUN \ 15 | apt-get update && \ 16 | apt-get install -y \ 17 | build-essential \ 18 | ccache \ 19 | curl \ 20 | file \ 21 | gawk \ 22 | g++-multilib \ 23 | gcc-multilib \ 24 | genisoimage \ 25 | git-core \ 26 | gosu \ 27 | libdw-dev \ 28 | libelf-dev \ 29 | libncurses5-dev \ 30 | locales \ 31 | pv \ 32 | pwgen \ 33 | python3 \ 34 | python3-venv \ 35 | python3-pip \ 36 | python3-pyelftools \ 37 | python3-cryptography \ 38 | qemu-utils \ 39 | rsync \ 40 | signify-openbsd \ 41 | subversion \ 42 | swig \ 43 | unzip \ 44 | wget \ 45 | zstd && \ 46 | apt-get clean && \ 47 | localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8 48 | 49 | RUN python3 -m venv /opt/venv 50 | ENV PATH="/opt/venv/bin:$PATH" 51 | RUN pip3 install -U pip 52 | RUN pip3 install \ 53 | "buildbot-worker==$BUILDBOT_VERSION" \ 54 | pyelftools \ 55 | pyOpenSSL \ 56 | service_identity 57 | 58 | ENV LANG=en_US.utf8 59 | 60 | COPY docker/buildworker/files/entry.sh /entry.sh 61 | COPY docker/buildworker/files/start.sh /start.sh 62 | 63 | RUN \ 64 | groupadd buildbot && \ 65 | useradd \ 66 | --create-home --home-dir /builder \ 67 | --comment "OpenWrt buildbot" \ 68 | --gid buildbot --shell /bin/bash buildbot && \ 69 | chown buildbot:buildbot /builder && \ 70 | chmod 0755 /entry.sh /start.sh 71 | 72 | VOLUME [ "/builder" ] 73 | ENTRYPOINT [ "/entry.sh" ] 74 | CMD [ "/start.sh" ] 75 | -------------------------------------------------------------------------------- /.gitlab/docker.yml: -------------------------------------------------------------------------------- 1 | .docker in docker: 2 | tags: 3 | - linux 4 | - openwrt 5 | - light-jobs 6 | - docker-privileged 7 | image: docker:19.03.7 8 | services: 9 | - docker:19.03.7-dind 10 | variables: 11 | DOCKER_DRIVER: overlay2 12 | DOCKER_TLS_CERTDIR: "/certs" 13 | 14 | .build Docker image: 15 | stage: docker 16 | extends: .docker in docker 17 | script: 18 | - export IMAGE_NAME="$(echo $CI_JOB_NAME | sed 's/build Docker image \(.*\)/\1/')" 19 | - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY 20 | - docker build --build-arg BUILDBOT_VERSION=$BUILDBOT_VERSION --build-arg OPENWRT_VERSION=$OPENWRT_VERSION -t "$IMAGE_NAME" -f "docker/$IMAGE_NAME/Dockerfile" . 21 | - docker tag "$IMAGE_NAME" "$CI_REGISTRY_IMAGE/$IMAGE_NAME-$BUILDBOT_VERSION:$CI_COMMIT_REF_SLUG" 22 | - docker push "$CI_REGISTRY_IMAGE/$IMAGE_NAME-$BUILDBOT_VERSION:$CI_COMMIT_REF_SLUG" 23 | 24 | .deploy Docker image: 25 | extends: .docker in docker 26 | rules: 27 | - if: $CI_COMMIT_TAG 28 | - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH 29 | script: 30 | - export IMAGE_NAME="$(echo $CI_JOB_NAME | sed 's/deploy Docker image \(.*\)/\1/')" 31 | - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY 32 | - docker pull "$CI_REGISTRY_IMAGE/$IMAGE_NAME-$BUILDBOT_VERSION:$CI_COMMIT_REF_SLUG" 33 | 34 | - docker tag "$CI_REGISTRY_IMAGE/$IMAGE_NAME-$BUILDBOT_VERSION:$CI_COMMIT_REF_SLUG" "$CI_REGISTRY_IMAGE/$IMAGE_NAME-$BUILDBOT_VERSION:latest" 35 | - docker tag "$CI_REGISTRY_IMAGE/$IMAGE_NAME-$BUILDBOT_VERSION:latest" "$CI_REGISTRY_IMAGE/$IMAGE_NAME-$BUILDBOT_VERSION:$CI_COMMIT_SHORT_SHA" 36 | - docker tag "$CI_REGISTRY_IMAGE/$IMAGE_NAME-$BUILDBOT_VERSION:latest" "$CI_REGISTRY_IMAGE/$IMAGE_NAME:latest" 37 | 38 | - docker push "$CI_REGISTRY_IMAGE/$IMAGE_NAME-$BUILDBOT_VERSION:latest" 39 | - docker push "$CI_REGISTRY_IMAGE/$IMAGE_NAME-$BUILDBOT_VERSION:$CI_COMMIT_SHORT_SHA" 40 | - docker push "$CI_REGISTRY_IMAGE/$IMAGE_NAME:latest" 41 | -------------------------------------------------------------------------------- /scripts/cleanup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export LC_ALL=C 4 | 5 | master_url="$1" 6 | current_worker="$2" 7 | current_builder="$3" 8 | current_mode="$4" 9 | 10 | worker_id="$(wget -qO- "${master_url%/}/api/v2/workers/$current_worker" | sed -rne 's#^ +"workerid": ([0-9]+),?$#\1#p')" 11 | active_builder_ids="$(wget -qO- "${master_url%/}/api/v2/workers/$worker_id/builds" | sed -rne '/"builderid"/ { s/^.+: ([0-9]+),$/\1/; h }; /"state_string"/ { s/^.+: "([^"]*)".*$/\1/; H; x; s/\n/ /; p }' | sed -ne 's/ building$//p')" 12 | 13 | find /tmp/ -maxdepth 1 -mtime +1 '(' -name 'npm-*' -or -name 'jsmake-*' ')' -print0 | xargs -0 -r rm -vr 14 | 15 | is_running() { 16 | local id="$(wget -qO- "${master_url%/}/api/v2/builders/${1//\//_}" | sed -rne 's#^ +"builderid": ([0-9]+),$#\1#p')" 17 | local running_builder_id 18 | for running_builder_id in $active_builder_ids; do 19 | if [ "$running_builder_id" = "$id" ]; then 20 | return 0 21 | fi 22 | done 23 | return 1 24 | } 25 | 26 | do_cleanup() { 27 | printf "Cleaning up '$current_builder' work directory" 28 | 29 | if [ -d .git ]; then 30 | echo " using git" 31 | git reset --hard HEAD 32 | git clean -f -d -x 33 | else 34 | find . -mindepth 1 -maxdepth 1 | while read entry; do 35 | rm -vrf "$entry" | while read entry2; do 36 | case "$entry2" in *directory[:\ ]*) 37 | printf "." 38 | esac 39 | done 40 | done 41 | fi 42 | 43 | echo "" 44 | } 45 | 46 | # 47 | # Sanity check, current builder should be in running builders list 48 | # 49 | 50 | if ! is_running "$current_builder"; then 51 | echo "Current builder '$current_builder' not found in current builders list, aborting cleanup." 52 | exit 1 53 | fi 54 | 55 | 56 | # 57 | # Clean up leftovers 58 | # 59 | 60 | if [ "$current_mode" = full ]; then 61 | ( 62 | if ! flock -x -w 2700 200; then 63 | echo "Unable to obtain exclusive lock, aborting cleanup." 64 | exit 1 65 | fi 66 | 67 | for build_dir in ../*; do 68 | 69 | current_builder="${build_dir##*/}" 70 | build_dir="$(readlink -f "$build_dir")" 71 | 72 | if [ -z "$build_dir" ] || [ -L "$build_dir" ] || [ ! -d "$build_dir/build" ]; then 73 | continue 74 | fi 75 | 76 | if is_running "$current_builder"; then 77 | echo "Skipping currently active '$current_builder' work directory." 78 | continue 79 | fi 80 | 81 | ( 82 | cd "$build_dir/build" 83 | do_cleanup 84 | ) 85 | done 86 | 87 | ) 200>../cleanup.lock 88 | 89 | # 90 | # Clean up current build 91 | # 92 | 93 | else 94 | if [ -d build ]; then ( 95 | cd build 96 | do_cleanup 97 | ); fi 98 | fi 99 | 100 | exit 0 101 | -------------------------------------------------------------------------------- /docker/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | 3 | services: 4 | rsync-server: 5 | build: 6 | context: ../ 7 | dockerfile: docker/rsync/Dockerfile 8 | image: rsync:latest 9 | restart: always 10 | cpuset: '0' 11 | environment: 12 | SHARE_USER: upload 13 | SHARE_PASSWORD: secret 14 | volumes: 15 | - './build/output:/data' 16 | 17 | buildmaster-phase1: 18 | build: 19 | context: ../ 20 | dockerfile: docker/buildmaster/Dockerfile 21 | image: buildmaster:latest 22 | restart: always 23 | cpuset: '0' 24 | environment: 25 | BUILDMASTER_PHASE: 1 26 | BUILDMASTER_CONFIG: /config.ini 27 | ports: 28 | - '8010:8010' 29 | - '9989:9989' 30 | volumes: 31 | - './config.ini:/config.ini' 32 | - './certs/buildmaster-phase1.crt:/certs/master.crt' 33 | - './certs/buildmaster-phase1.key:/certs/master.key' 34 | - './build/master-phase1:/master' 35 | 36 | buildmaster-phase2: 37 | build: 38 | context: ../ 39 | dockerfile: docker/buildmaster/Dockerfile 40 | image: buildmaster:latest 41 | restart: always 42 | cpuset: '0' 43 | environment: 44 | BUILDMASTER_PHASE: 2 45 | BUILDMASTER_CONFIG: /config.ini 46 | ports: 47 | - '8011:8011' 48 | - '9990:9990' 49 | volumes: 50 | - './config.ini:/config.ini' 51 | - './certs/buildmaster-phase2.crt:/certs/master.crt' 52 | - './certs/buildmaster-phase2.key:/certs/master.key' 53 | - './build/master-phase2:/master' 54 | 55 | buildworker-phase1: 56 | build: 57 | context: ../ 58 | dockerfile: docker/buildworker/Dockerfile 59 | image: buildworker:latest 60 | restart: always 61 | cpuset: 1-3 62 | environment: 63 | BUILDWORKER_MASTER: buildmaster-phase1:9989 64 | BUILDWORKER_NAME: buildworker-phase1 65 | BUILDWORKER_PASSWORD: secret 66 | BUILDWORKER_TLS: '1' 67 | links: 68 | - 'rsync-server' 69 | - 'buildmaster-phase1' 70 | volumes: 71 | - './certs/ca.crt:/certs/ca.pem' 72 | - './build/worker-phase1:/builder' 73 | 74 | buildworker-phase2: 75 | build: 76 | context: ../ 77 | dockerfile: docker/buildworker/Dockerfile 78 | image: buildworker:latest 79 | restart: always 80 | cpuset: 1-3 81 | environment: 82 | BUILDWORKER_MASTER: buildmaster-phase2:9990 83 | BUILDWORKER_NAME: buildworker-phase2 84 | BUILDWORKER_PASSWORD: secret 85 | BUILDWORKER_TLS: '1' 86 | links: 87 | - 'rsync-server' 88 | - 'buildmaster-phase2' 89 | volumes: 90 | - './certs/ca.crt:/certs/ca.pem' 91 | - './build/worker-phase2:/builder' 92 | -------------------------------------------------------------------------------- /phase1/config.ini.example: -------------------------------------------------------------------------------- 1 | [general] 2 | title = OpenWrt Project 3 | title_url = http://openwrt.org/ 4 | workdir = /buildbot 5 | 6 | [phase1] 7 | buildbot_url = http://phase1.builds.openwrt.org/ 8 | status_bind = tcp:8010:interface=127.0.0.1 9 | status_user = example 10 | status_password = example 11 | port = 9989 12 | feeds_host_override = 13 | 14 | [irc] 15 | host = irc.freenode.net 16 | port = 6667 17 | channel = #example-channel 18 | nickname = example-builder 19 | password = example 20 | 21 | [repo] 22 | url = https://git.openwrt.org/openwrt/openwrt.git 23 | tree_stable_timer = 900 24 | 25 | # branches should be listed by decreasing build priority order, typically oldest branch first (less build intensive) 26 | # branch section name should match branch "name" option until signall.sh is reworked 27 | [branch openwrt-21.02] 28 | name = openwrt-21.02 29 | gpg_key = -----BEGIN PGP PRIVATE KEY BLOCK----- 30 | Version: GnuPG v2 31 | 32 | mQGNBFX4kxkBDACcTUVUl6zbn4r9tDap0/aCpcK9MO+HPatS7p2aBGY51kh78Ixr 33 | ... 34 | HwHLaFTMvYFY7WJDwA== 35 | -----END PGP PRIVATE KEY BLOCK----- 36 | gpg_passphrase = secret password 37 | gpg_comment = Unattended build signature 38 | usign_key = RWRCSwAAA...OihABfuLvGRVfVaJ6wLf0= 39 | usign_comment = Unattended build signature 40 | apk_key = -----BEGIN EC PRIVATE KEY----- 41 | MHcCAQEEIIP54p1G0UgCleLObh07Gxq0S0Iz22OQpkUj8S1AzXB9oAoGCCqGSM49 42 | ... 43 | -----END EC PRIVATE KEY----- 44 | binary_url = user@example.org::upload-binary 45 | binary_password = example 46 | source_url = user@example.org::upload-sources 47 | source_password = example2 48 | config_seed = # Seed configuration 49 | CONFIG_BUILDBOT=y 50 | CONFIG_DEVEL=y 51 | CONFIG_CCACHE=n 52 | CONFIG_KERNEL_KALLSYMS=y 53 | CONFIG_AUTOREMOVE=y 54 | build_targets = armsr/armv8 55 | malta/be 56 | mediatek/filogic 57 | qualcommax/ipq807x 58 | x86/64 59 | 60 | [branch openwrt-22.03] 61 | name = openwrt-22.03 62 | 63 | [branch main] 64 | name = main 65 | 66 | [worker 1] 67 | phase = 1 68 | name = example-worker-1 69 | password = example 70 | 71 | [worker 2] 72 | phase = 1 73 | name = example-worker-2 74 | password = example2 75 | # for workers which share a common pipe, ul/dl resource-access locks can be defined. 76 | # if the identifier is the same for both ul/dl, then all ul/dl operations will be serialized between workers having the same id. 77 | # if the identifier differs for ul and dl, then dl operations will be serialized independently of ul operations. 78 | ul_lock = host1 79 | dl_lock = host1 80 | # tag_only workers will only build forced tag buildrequests (i.e. release builds) 81 | tag_only = yes 82 | # if rsync operations must prefer ipv4 ('rsync -4'), set the following 83 | rsync_ipv4 = yes 84 | -------------------------------------------------------------------------------- /docker/buildmaster/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpinelinux/build-base:latest-x86_64 AS apk-builder 2 | 3 | RUN abuild-apk add -u \ 4 | gcc \ 5 | git \ 6 | linux-headers \ 7 | lua5.3-dev \ 8 | lua5.3-lzlib \ 9 | make \ 10 | musl-dev \ 11 | openssl-dev \ 12 | openssl-libs-static \ 13 | zlib-dev \ 14 | zlib-static \ 15 | zstd-dev \ 16 | zstd-static 17 | 18 | ARG APK_TOOLS_COMMIT=74de0e9bd73d1af8720df40aa68d472943909804 19 | 20 | RUN git clone https://gitlab.alpinelinux.org/alpine/apk-tools.git /tmp/apk-tools 21 | WORKDIR /tmp/apk-tools 22 | RUN git checkout $APK_TOOLS_COMMIT 23 | RUN make -j$(nproc) static 24 | 25 | 26 | FROM debian:11 27 | MAINTAINER OpenWrt Maintainers 28 | 29 | ARG DEBIAN_FRONTEND=noninteractive 30 | ARG BUILDBOT_VERSION=2.10.1 31 | ARG OPENWRT_VERSION=unknown 32 | 33 | ENV BUILDMASTER_CONFIG config.ini 34 | ENV BUILDMASTER_PHASE 1 35 | 36 | USER root 37 | 38 | RUN \ 39 | apt-get update && \ 40 | apt-get install -y \ 41 | build-essential \ 42 | gawk \ 43 | git-core \ 44 | gosu \ 45 | libncurses5-dev \ 46 | locales \ 47 | pv \ 48 | pwgen \ 49 | python3-venv \ 50 | python3-pip \ 51 | signify-openbsd \ 52 | wget && \ 53 | apt-get clean && \ 54 | localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8 55 | 56 | RUN python3 -m venv /opt/venv 57 | ENV PATH="/opt/venv/bin:$PATH" 58 | RUN pip3 install -U pip 59 | RUN \ 60 | pip3 install \ 61 | "buildbot==$BUILDBOT_VERSION" \ 62 | "buildbot-www==$BUILDBOT_VERSION" \ 63 | "buildbot-waterfall-view==$BUILDBOT_VERSION" \ 64 | "buildbot-console-view==$BUILDBOT_VERSION" \ 65 | "buildbot-grid-view==$BUILDBOT_VERSION" \ 66 | "buildbot-worker==$BUILDBOT_VERSION" \ 67 | pyOpenSSL \ 68 | service_identity 69 | 70 | RUN \ 71 | sed -i \ 72 | 's/Welcome to buildbot/Welcome to OpenWrt buildbot/' \ 73 | /opt/venv/lib/python*/site-packages/buildbot_www/static/scripts.js 74 | 75 | RUN \ 76 | sed -i \ 77 | "s;\"col-sm-12\">