name: Build and Release OpenWrt packages on: push: branches: - main tags: - "v*" pull_request: workflow_dispatch: # Gitea's built-in GITEA_TOKEN needs release write permission for tag releases. permissions: contents: read actions: read releases: write jobs: build: runs-on: ubuntu-latest strategy: fail-fast: false matrix: include: - openwrt: "25.12.0" format: "apk" sdk_file: "openwrt-sdk-25.12.0-x86-64_gcc-14.3.0_musl.Linux-x86_64.tar.zst" sdk_sha256: "9f371906ce6d2f95418f69fac06df58bf9df0ffc4abed6206c30f1b547fcfc12" sdk_url: "https://downloads.openwrt.org/releases/25.12.0/targets/x86/64/openwrt-sdk-25.12.0-x86-64_gcc-14.3.0_musl.Linux-x86_64.tar.zst" - openwrt: "24.10.8" format: "ipk" sdk_file: "openwrt-sdk-24.10.8-x86-64_gcc-13.3.0_musl.Linux-x86_64.tar.zst" sdk_sha256: "ac4a0405d2eea821b06f93c14ba13ffa90ad0457648903df7dde02570027ab21" sdk_url: "https://downloads.openwrt.org/releases/24.10.8/targets/x86/64/openwrt-sdk-24.10.8-x86-64_gcc-13.3.0_musl.Linux-x86_64.tar.zst" - openwrt: "23.05.5" format: "ipk" sdk_file: "openwrt-sdk-23.05.5-x86-64_gcc-12.3.0_musl.Linux-x86_64.tar.xz" sdk_sha256: "9e5b6813a3f810123391f5f3ea10dfd1c14be1a880f410c70ec4424bbd1573d2" sdk_url: "https://downloads.openwrt.org/releases/23.05.5/targets/x86/64/openwrt-sdk-23.05.5-x86-64_gcc-12.3.0_musl.Linux-x86_64.tar.xz" steps: - name: Checkout uses: actions/checkout@v4 - name: Resolve package version shell: bash run: | set -euo pipefail if [ "${GITHUB_REF_TYPE}" = "tag" ]; then VERSION="${GITHUB_REF_NAME#v}" else VERSION="$(sed -n 's/^PKG_VERSION:=//p' Makefile | head -n1)" fi if [ -z "${VERSION}" ]; then echo "Unable to resolve package version" exit 1 fi echo "PACKAGE_VERSION=${VERSION}" >> "${GITHUB_ENV}" echo "Package version: ${VERSION}" - name: Install build dependencies shell: bash run: | set -eux if command -v sudo >/dev/null 2>&1; then SUDO=sudo else SUDO= fi ${SUDO} apt-get update ${SUDO} env DEBIAN_FRONTEND=noninteractive apt-get install -y \ build-essential \ clang \ flex \ bison \ gawk \ gettext \ git \ libncurses-dev \ libssl-dev \ python3 \ python3-pyelftools \ python3-setuptools \ rsync \ swig \ unzip \ wget \ xz-utils \ zlib1g-dev \ zstd - name: Download and verify OpenWrt SDK shell: bash run: | set -eux wget -O "${{ matrix.sdk_file }}" "${{ matrix.sdk_url }}" echo "${{ matrix.sdk_sha256 }} ${{ matrix.sdk_file }}" | sha256sum -c - - name: Extract OpenWrt SDK shell: bash run: | set -eux rm -rf _sdk mkdir -p _sdk case "${{ matrix.sdk_file }}" in *.tar.zst) tar --zstd -xf "${{ matrix.sdk_file }}" \ --strip-components=1 \ -C _sdk ;; *.tar.xz) tar -xJf "${{ matrix.sdk_file }}" \ --strip-components=1 \ -C _sdk ;; *) echo "Unsupported SDK archive: ${{ matrix.sdk_file }}" exit 1 ;; esac - name: Prepare LuCI feed shell: bash working-directory: _sdk run: | set -eux ./scripts/feeds update luci ./scripts/feeds install luci-base - name: Add package source shell: bash run: | set -eux PKG="_sdk/package/luci-app-led-scheduler" rm -rf "${PKG}" mkdir -p "${PKG}" cp -a \ Makefile \ LICENSE \ README.md \ htdocs \ root \ "${PKG}/" # For tag builds, package version follows the Git tag. # Example: v0.3.1 -> PKG_VERSION:=0.3.1 sed -i \ "s/^PKG_VERSION:=.*/PKG_VERSION:=${PACKAGE_VERSION}/" \ "${PKG}/Makefile" grep '^PKG_VERSION:=' "${PKG}/Makefile" - name: Configure SDK shell: bash working-directory: _sdk run: | set -eux make defconfig - name: Build package shell: bash working-directory: _sdk run: | set -eux make -j"$(nproc)" \ package/luci-app-led-scheduler/compile \ V=s - name: Collect package shell: bash run: | set -eux mkdir -p artifacts FILE="$(find _sdk/bin -type f \ -name "luci-app-led-scheduler*.${{ matrix.format }}" \ -print -quit)" if [ -z "${FILE}" ]; then echo "No ${{ matrix.format }} package found" exit 1 fi ORIGINAL_NAME="$(basename "${FILE}")" RELEASE_NAME="openwrt-${{ matrix.openwrt }}-${ORIGINAL_NAME}" cp -v "${FILE}" "artifacts/${RELEASE_NAME}" echo "Built package:" ls -lh artifacts/ - name: Upload Actions artifact uses: actions/upload-artifact@v4 with: name: luci-app-led-scheduler-openwrt-${{ matrix.openwrt }}-${{ matrix.format }} path: artifacts/* if-no-files-found: error release: # Ordinary pushes only build artifacts. # A tag such as v0.3.1 additionally creates/updates a Gitea Release. if: ${{ gitea.ref_type == 'tag' }} needs: - build runs-on: ubuntu-latest permissions: contents: read actions: read releases: write steps: - name: Download all build artifacts uses: actions/download-artifact@v4 with: pattern: luci-app-led-scheduler-openwrt-* path: release-assets merge-multiple: true - name: Show release files shell: bash run: | set -eux find release-assets -maxdepth 1 -type f -print test -n "$(find release-assets -maxdepth 1 -type f -print -quit)" - name: Create or update Gitea Release id: release shell: bash env: GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} run: | set -euo pipefail TAG="${GITHUB_REF_NAME}" VERSION="${TAG#v}" API="${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}" BODY="$(cat </tmp/release.json elif [ "${HTTP_CODE}" = "404" ]; then curl -fsS \ -X POST \ -H "Authorization: token ${GITEA_TOKEN}" \ -H "Content-Type: application/json" \ -d "${PAYLOAD}" \ "${API}/releases" \ >/tmp/release.json RELEASE_ID="$(python3 - <<'PY' import json with open("/tmp/release.json", "r", encoding="utf-8") as f: print(json.load(f)["id"]) PY )" else echo "Failed to query existing release, HTTP ${HTTP_CODE}" cat /tmp/existing-release.json || true exit 1 fi echo "Release ID: ${RELEASE_ID}" echo "RELEASE_ID=${RELEASE_ID}" >> "${GITHUB_ENV}" - name: Remove duplicate release attachments shell: bash env: GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} run: | set -euo pipefail API="${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}" curl -fsS \ -H "Authorization: token ${GITEA_TOKEN}" \ "${API}/releases/${RELEASE_ID}/assets" \ >/tmp/assets.json python3 - <<'PY' >/tmp/delete-assets.txt import json from pathlib import Path wanted = {p.name for p in Path("release-assets").iterdir() if p.is_file()} with open("/tmp/assets.json", "r", encoding="utf-8") as f: assets = json.load(f) for asset in assets: if asset.get("name") in wanted: print(asset["id"]) PY while IFS= read -r ASSET_ID; do [ -n "${ASSET_ID}" ] || continue echo "Removing existing attachment ID ${ASSET_ID}" curl -fsS \ -X DELETE \ -H "Authorization: token ${GITEA_TOKEN}" \ "${API}/releases/${RELEASE_ID}/assets/${ASSET_ID}" \ >/dev/null done /dev/null done echo "Release assets uploaded:" find release-assets -maxdepth 1 -type f -printf ' %f\n'