name: Build CHR Docker on: workflow_dispatch: inputs: channel: description: 'Channel (stable, long-term, testing, development)' required: true default: 'stable' type: choice options: - stable - long-term - testing - development version: description: "Specify version (e.g., 7.19.2), empty for latest" required: false default: '' type: string permissions: packages: write jobs: Build: runs-on: ubuntu-24.04 env: TZ: 'Asia/Shanghai' CHANNEL: ${{ inputs.channel }} VERSION: ${{ inputs.version }} IMAGE: "ghcr.io/${{ github.repository_owner }}/chr" IS_LATEST: 'false' DOCKER_BUILD_CHECKS_ANNOTATIONS: 'false' DOCKER_BUILD_SUMMARY: 'false' DOCKER_BUILD_RECORD_UPLOAD: 'false' steps: - name: Check Version id: version run: | if [ -z "$VERSION" ]; then echo "Checking latest version from $CHANNEL channel..." TIMESTAMP=$(date +%s) NEWEST=$(wget -nv -O - "https://upgrade.mikrotik.ltd/routeros/NEWESTa7.$CHANNEL?t=$TIMESTAMP") VERSION=$(echo "$NEWEST" | cut -d ' ' -f1) echo "Latest version: $VERSION" if [ "$CHANNEL" = "stable" ]; then echo "IS_LATEST=true" >> $GITHUB_ENV fi fi echo "VERSION=$VERSION" >> $GITHUB_ENV - name: Download CHR image run: | # x86 架构 mkdir -p "amd64" wget -nv -O "amd64/chr-$VERSION.img.zip" \ "https://github.com/elseif/MikroTikPatch/releases/download/$VERSION/chr-$VERSION.img.zip" unzip "amd64/chr-$VERSION.img.zip" -d "amd64/" rm "amd64/chr-$VERSION.img.zip" # arm64 架构 mkdir -p "arm64" wget -nv -O "arm64/chr-$VERSION-arm64.img.zip" \ "https://github.com/elseif/MikroTikPatch/releases/download/$VERSION-arm64/chr-$VERSION-arm64.img.zip" unzip "arm64/chr-$VERSION-arm64.img.zip" -d "arm64/" rm "arm64/chr-$VERSION-arm64.img.zip" ls -la amd64/ arm64/ - name: Create start.sh run: | cat <<'EOF' > start.sh #!/bin/sh set -e MEM="${MEM:=512m}" DISK="${DISK:=128M}" CPUS="${CPUS:=1}" bridge_index=0 get_mac_address() { ifname="$1" ip link show "$ifname" 2>/dev/null | awk '/link\/ether/ {print $2}' } increment_mac() { mac=$1 mac_no_colons=$(echo "$mac" | tr -d ':' | tr '[:lower:]' '[:upper:]') mac_dec=$((16#${mac_no_colons})) mac_dec=$((mac_dec + 1)) mac_hex=$(printf "%012X" "$mac_dec") echo "$mac_hex" | sed 's/.\{2\}/&:/g;s/:$//' } echo "" > /etc/qemu/bridge.conf qemu="qemu-system-x86_64" if [[ `uname -m` == "aarch64" ]]; then qemu="qemu-system-aarch64 -pflash /usr/share/qemu/edk2-aarch64-code.fd -M virt" fi if [ -e /dev/kvm ]; then qemu="$qemu -enable-kvm -cpu host" else if [[ `uname -m` == "aarch64" ]]; then qemu="$qemu -cpu cortex-a57" fi fi img=`ls /diskimage/*.img` qemu="$qemu -nographic -m $MEM -smp cpus=$CPUS -drive file=$img,format=raw" truncate -s $DISK $img while read -r line; do iface=$(echo "$line" | sed "s/ *\([a-z0-9]*\):.*/\1/") if [[ "$iface" =~ " " ]]; then continue fi if [[ "$iface" =~ ^br ]]; then continue fi if [[ "$iface" == "lo" ]]; then continue fi if [[ "$iface" == "" ]]; then continue fi echo "iface: $iface" bridge="br$bridge_index" ip link add name "$bridge" type bridge ip link set dev "$bridge" up ip link set "$iface" master "$bridge" echo "allow $bridge" >> /etc/qemu/bridge.conf veth_mac=$(get_mac_address "$iface") tap_mac=$(increment_mac "$veth_mac") bridge_index=$((bridge_index + 1)) qemu="$qemu -netdev bridge,id=$bridge,br=$bridge -device virtio-net,netdev=$bridge,mac=$tap_mac " done < /proc/net/dev echo "qemu: $qemu" exec $qemu EOF chmod +x start.sh - name: Create Dockerfile run: | cat > Dockerfile << 'EOF' FROM alpine:latest ARG TARGETARCH ARG VERSION RUN case "$TARGETARCH" in \ amd64) apk add --no-cache qemu-system-x86_64 ;; \ arm64) apk add --no-cache qemu-system-aarch64 ;; \ esac \ && rm -rf /var/cache/apk/* RUN mkdir -p /diskimage COPY ${TARGETARCH}/*.img /diskimage/ COPY start.sh /start.sh ENTRYPOINT ["/start.sh"] EOF - name: Log in to GitHub Container Registry uses: docker/login-action@v4 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Set up QEMU uses: docker/setup-qemu-action@v4 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v4 - name: Build and Push uses: docker/build-push-action@v7 with: context: . platforms: linux/amd64,linux/arm64 push: true tags: ${{ env.IMAGE }}:${{ env.VERSION }} build-args: VERSION=${{ env.VERSION }} cache-from: type=gha cache-to: type=gha,mode=max provenance: false sbom: false - name: Update :latest tag for stable channel if: env.IS_LATEST == 'true' run: | docker buildx imagetools create -t ${{ env.IMAGE }}:latest ${{ env.IMAGE }}:${{ env.VERSION }} - name: Save Docker Image as tar run: | mkdir -p artifacts echo "Exporting amd64 tar..." docker pull --platform linux/amd64 ${{ env.IMAGE }}:${{ env.VERSION }} docker save ${{ env.IMAGE }}:${{ env.VERSION }} -o artifacts/chr-${{ env.VERSION }}-amd64.tar echo "Exporting arm64 tar..." docker pull --platform linux/arm64 ${{ env.IMAGE }}:${{ env.VERSION }} docker save ${{ env.IMAGE }}:${{ env.VERSION }} -o artifacts/chr-${{ env.VERSION }}-arm64.tar ls -lh artifacts/ - name: Upload tar artifact uses: actions/upload-artifact@v7 with: name: chr-docker-image-${{ env.VERSION }} path: artifacts/*.tar