Build FnNAS Image #265
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #===================================================================================== | |
| # https://github.com/ophub/fnnas | |
| # Description: Build FnNAS Image | |
| #===================================================================================== | |
| name: Build FnNAS Image | |
| on: | |
| repository_dispatch: | |
| workflow_dispatch: | |
| inputs: | |
| fnnas_base_version: | |
| description: "Select fnnas base image version" | |
| required: false | |
| default: "rockchip_1253" | |
| type: choice | |
| options: | |
| - amlogic_1252 | |
| - amlogic_693 | |
| - rockchip_1253 | |
| - rockchip_692 | |
| - allwinner_1254 | |
| - allwinner_691 | |
| fnnas_board: | |
| description: "Select fnnas device board" | |
| required: false | |
| default: "rockchip50" | |
| type: choice | |
| options: | |
| - allwinner | |
| - amlogic | |
| - rockchip50 | |
| - rockchip50_100 | |
| - rockchip100_150 | |
| - a311d | |
| - a311d-oes | |
| - alark35-3500 | |
| - anas3035 | |
| - aio-3399b | |
| - aio-3399c | |
| - aio-3399c-ai | |
| - bdkj-bd-one | |
| - bdy-g18-pro | |
| - beikeyun | |
| - boca-tcn100 | |
| - boca-tcn200 | |
| - bt-100m | |
| - bt-1000m | |
| - cd1000 | |
| - chainedbox | |
| - cm3588-nas | |
| - crrc | |
| - dc-a588 | |
| - dg3399 | |
| - dg-nas-lite | |
| - dg-tn3568 | |
| - dlfr100 | |
| - e20c | |
| - e25 | |
| - eaidk-610 | |
| - easepi-a2 | |
| - easepi-r2 | |
| - emb3531 | |
| - fine3399 | |
| - firefly-itx-3588j | |
| - firefly-jd4 | |
| - firefly-rk3399 | |
| - fmx1-pro | |
| - fmx1-pro-b | |
| - gea-6319 | |
| - gzpeite-p01 | |
| - h28k | |
| - h618-devboard | |
| - h66k | |
| - h68k | |
| - h69k | |
| - h88k | |
| - h88k-v3 | |
| - h96-max-m2 | |
| - hk1-rbox-k8s | |
| - hs530r | |
| - ht2 | |
| - hugsun-x99 | |
| - indiedroid-nova | |
| - ipc-r | |
| - jp-tvbox | |
| - king3399 | |
| - kylin3399 | |
| - lckfb-tspi | |
| - lckfb-tspi-3m | |
| - leez | |
| - lubancat-1 | |
| - lubancat-2 | |
| - lubancat-4 | |
| - lx-r3s | |
| - lyt-t68m | |
| - lz-d3568 | |
| - lz-d3588 | |
| - lz-k3568 | |
| - md1000 | |
| - mrkaio-m68s | |
| - nanopc-t4 | |
| - nanopc-t6 | |
| - nanopi-m5 | |
| - nanopi-r5c | |
| - nanopi-r5s | |
| - nsy-g16-plus | |
| - nsy-g68-plus | |
| - orangepi-3b | |
| - orangepi-5-plus | |
| - orangepi-5-pro | |
| - orangepi-5b | |
| - orangepi-zero3 | |
| - painet-p3 | |
| - panther-x2 | |
| - photonicat | |
| - r66s | |
| - r68s | |
| - renegade-rk3328 | |
| - rk3318-box | |
| - roceos-k40pro | |
| - rock-5-itx | |
| - rock-3b | |
| - rock-3c | |
| - rock5b | |
| - rock5c | |
| - ruisen-box | |
| - s905 | |
| - s905-beelink-mini | |
| - s905-mxqpro-plus | |
| - s905d | |
| - s905d-ki-pro | |
| - s905d-sml5442tw | |
| - s905d3-khadas-vim3l | |
| - s905l | |
| - s905l-aurora-1s | |
| - s905l-b860av21u | |
| - s905l-mg101 | |
| - s905l2 | |
| - s905l2-e900v21e | |
| - s905l2-wojia | |
| - s905l3 | |
| - s905l3-cm211 | |
| - s905l3-unt400g1 | |
| - s905l3-unt402a | |
| - s905l3a | |
| - s905l3a-cm311 | |
| - s905l3a-m401a | |
| - s905l3b | |
| - s905l3b-e900v21d | |
| - s905l3b-e900v22d | |
| - s905l3b-e900v22e | |
| - s905l3b-ip103h | |
| - s905l3b-rg020et-ca | |
| - s905l3b-unt403a | |
| - s905lb-ipbs9505 | |
| - s905lb-q96-mini | |
| - s905lb-r3300l | |
| - s905mb | |
| - s905w | |
| - s905w-w95 | |
| - s905w-x96-mini | |
| - s905w-x96w | |
| - s905x | |
| - s905x-b860h | |
| - s905x-nexbox-a95x | |
| - s905x-t95 | |
| - s905x-tbee | |
| - s905x-tx9 | |
| - s905x2 | |
| - s905x2-km3 | |
| - s905x2-x96max-2g | |
| - s905x2-hg680fj | |
| - s905x3 | |
| - s905x3-2101 | |
| - s905x3-a100 | |
| - s905x3-a95xf3 | |
| - s905x3-a95xf3-gb | |
| - s905x3-b | |
| - s905x3-h96max | |
| - s905x3-hk1 | |
| - s905x3-ip1001m | |
| - s905x3-q1 | |
| - s905x3-q2 | |
| - s905x3-tox1 | |
| - s905x3-tx3 | |
| - s905x3-tx3-bz | |
| - s905x3-ugoosx3 | |
| - s905x3-whale | |
| - s905x3-x88-pro-x3 | |
| - s905x3-x96air | |
| - s905x3-x96air-gb | |
| - s905x3-x96max | |
| - s912 | |
| - s912-h96pro-plus | |
| - s912-m8s-pro | |
| - s912-nexbox-a1 | |
| - s912-nexbox-a2 | |
| - s912-onecloudpro | |
| - s912-phicomm-t1 | |
| - s912-t95z-plus | |
| - s912-tx8-max | |
| - s912-tx9-pro-2g | |
| - s912-tx9-pro-3g | |
| - s912-x92 | |
| - s912-zyxq-fake | |
| - s922x | |
| - s922x-ct2000 | |
| - s922x-gtking | |
| - s922x-gtkingpro-h | |
| - s922x-odroid-n2 | |
| - s922x-oes-plus | |
| - s922x-reva | |
| - s922x-ugoos-am6 | |
| - seewo-sv21 | |
| - seewo-sv50 | |
| - smart-am40 | |
| - smart-am60 | |
| - station-m1 | |
| - station-m2 | |
| - station-p2 | |
| - sv-33a6x | |
| - sv-33a6x-vpu | |
| - swan1-w28 | |
| - sw799 | |
| - taram | |
| - tanix-tx6 | |
| - tb-ls3399 | |
| - tn3399 | |
| - tpm312 | |
| - tqc-a01 | |
| - tvi3315a | |
| - vontar-h618 | |
| - vplus | |
| - wocyber-a3 | |
| - wxy-oect | |
| - wxy-oect-mod | |
| - x88pro20 | |
| - x98h | |
| - xiaobao | |
| - yskj | |
| - zcube1-max | |
| - zk-r39a | |
| - zysj | |
| kernel_repo: | |
| description: "Set fnnas kernel repository" | |
| required: false | |
| default: "ophub/fnnas" | |
| type: choice | |
| options: | |
| - ophub/fnnas | |
| fnnas_kernel: | |
| description: "Select fnnas kernel version" | |
| required: false | |
| default: "6.18.y" | |
| type: choice | |
| options: | |
| - 6.18.y | |
| - 6.12.y | |
| auto_kernel: | |
| description: "Auto use the latest kernel" | |
| required: false | |
| default: true | |
| type: boolean | |
| rootfs_expand: | |
| description: "Set rootfs expansion size(GiB)" | |
| required: false | |
| default: "16" | |
| fnnas_url: | |
| description: "Custom fnnas image download url" | |
| required: false | |
| default: "" | |
| builder_name: | |
| description: "Set fnnas builder signature" | |
| required: false | |
| default: "ophub" | |
| type: choice | |
| options: | |
| - ophub | |
| - angel | |
| - yourname | |
| env: | |
| TZ: Etc/UTC | |
| jobs: | |
| build: | |
| runs-on: ubuntu-24.04 | |
| if: ${{ github.event.repository.owner.id == github.event.sender.id }} | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Initialize the build environment | |
| id: init | |
| env: | |
| DEBIAN_FRONTEND: noninteractive | |
| run: | | |
| docker rmi -f $(docker images -q) 2>/dev/null || true | |
| [[ -n "${AGENT_TOOLSDIRECTORY}" ]] && sudo rm -rf "${AGENT_TOOLSDIRECTORY}" | |
| sudo rm -rf /usr/share/dotnet /usr/local/lib/android 2>/dev/null | |
| sudo swapoff -a | |
| sudo rm -f /swapfile /mnt/swapfile | |
| sudo -E apt-get -y update | |
| sudo -E apt-get -y purge azure-cli ghc* zulu* llvm* firefox google* dotnet* powershell openjdk* mongodb* moby* || true | |
| sudo -E apt-get -y install $(curl -fsSL https://ophub.org/ubuntu2404-make-fnnas-depends) | |
| sudo -E systemctl daemon-reload | |
| #sudo -E apt-get -y full-upgrade | |
| sudo -E apt-get -y autoremove --purge | |
| sudo -E apt-get clean | |
| sudo sed -i '/NVM_DIR/d;/skel/d' /root/{.bashrc,.profile} | |
| sudo rm -rf ~/{.cargo,.dotnet,.rustup} | |
| sudo -E timedatectl set-timezone "${TZ:-Etc/UTC}" | |
| sudo -E ntpdate ntp.ubuntu.com 0.pool.ntp.org || true | |
| sudo -E timedatectl set-ntp true | |
| date -u | |
| timedatectl status || true | |
| echo "status=success" >> ${GITHUB_OUTPUT} | |
| - name: Create virtual disk for extended storage | |
| id: disk | |
| run: | | |
| # Get available space in exact GB | |
| root_avail=$(df --block-size=1G / | tail -1 | awk '{print $4}') | |
| root_size=$(( root_avail - 4 )) | |
| [[ "${root_size}" -gt 0 ]] || { echo "Error: Insufficient space on /: ${root_avail}G available"; exit 1; } | |
| sudo truncate -s "${root_size}"G /root.img | |
| build_dev=$(sudo losetup --find --show /root.img) | |
| echo "Using /: ${root_size}G" | |
| sudo mkfs.xfs -f -i sparse=0 -b size=4096 "${build_dev}" | |
| sudo mkdir -p /builder | |
| sudo mount "${build_dev}" /builder | |
| sudo chown -R runner:runner /builder | |
| df -Th | |
| echo "status=success" >> ${GITHUB_OUTPUT} | |
| - name: Download fnnas image [ ${{ inputs.fnnas_base_version }} ] | |
| id: down | |
| working-directory: /builder | |
| if: (!cancelled()) | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| # Create directory | |
| [[ -d "fnnas" ]] || mkdir -p fnnas | |
| input_url="${{ inputs.fnnas_url }}" | |
| fnnas_base_version="${{ inputs.fnnas_base_version }}" | |
| [[ -n "${fnnas_base_version}" ]] && build_tag="fnnas_${fnnas_base_version}" || build_tag="fnnas_save" | |
| # ------------------------------------------------------- | |
| # Case A: URL specified | |
| # ------------------------------------------------------- | |
| if [[ -n "${input_url}" ]]; then | |
| echo "Custom URL detected: ${input_url}" | |
| # Remove any parameters that may be included in the URL (?...) | |
| clean_url="${input_url%%\?*}" | |
| # Regex match GitHub Release URL format | |
| # Format: https://github.com/<owner>/<repo>/releases/download/<tag>/<filename> | |
| regex="github\.com/([^/]+)/([^/]+)/releases/download/([^/]+)/(.+)" | |
| if [[ "${clean_url}" =~ $regex ]]; then | |
| # Extract information | |
| owner="${BASH_REMATCH[1]}" | |
| repo="${BASH_REMATCH[2]}" | |
| tag="${BASH_REMATCH[3]}" | |
| filename="${BASH_REMATCH[4]}" | |
| echo "Detected GitHub Release URL." | |
| echo "Repo: $owner/$repo | Tag: $tag | File: $filename" | |
| # Use gh cli to download | |
| gh release download "${tag}" \ | |
| --repo "${owner}/${repo}" \ | |
| --pattern "${filename}" \ | |
| --dir "fnnas" \ | |
| --clobber | |
| # Check download result | |
| if [[ -f "fnnas/${filename}" ]]; then | |
| echo "Download success via gh-cli." | |
| echo "status=success" >> ${GITHUB_OUTPUT} | |
| exit 0 | |
| else | |
| echo "Error: gh download failed." | |
| exit 1 | |
| fi | |
| else | |
| # If not a standard Release URL (e.g., API URL or third-party URL), fallback to curl | |
| echo "Using curl fallback..." | |
| latest_url="${input_url}" | |
| fnnas_filename=$(basename "${clean_url}") | |
| fi | |
| # ------------------------------------------------------- | |
| # Case B: Automatically fetch the latest version | |
| # ------------------------------------------------------- | |
| else | |
| echo "Auto-detecting latest release..." | |
| latest_version=$(curl -s \ | |
| -H "Accept: application/vnd.github+json" \ | |
| -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \ | |
| https://api.github.com/repos/ophub/fnnas/releases?per_page=20 | \ | |
| jq -r --arg RTK "fnnas_base_image" \ | |
| --arg BOARD "${fnnas_base_version}" \ | |
| '[.[] | select(.tag_name | contains($RTK))] | | |
| map(.assets[] | select(.name | contains($BOARD) and endswith(".img.xz"))) | | |
| sort_by(.updated_at) | | |
| reverse | | |
| .[0] | | |
| {data: .updated_at, url: .url, name: .name}') | |
| [[ -z "${latest_version}" || "${latest_version}" == "null" ]] && { | |
| echo "Error: Failed to resolve FnNAS image download URL." | |
| } | |
| latest_url="$(echo ${latest_version} | jq -r '.url')" | |
| fnnas_filename="$(echo ${latest_version} | jq -r '.name')" | |
| fi | |
| # ------------------------------------------------------- | |
| # Execute curl download (only if the above gh did not run) | |
| # ------------------------------------------------------- | |
| echo "Downloading: ${fnnas_filename}" | |
| echo "Source: ${latest_url}" | |
| curl -fsSL \ | |
| -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \ | |
| -H "Accept: application/octet-stream" \ | |
| "${latest_url}" \ | |
| -o "fnnas/${fnnas_filename}" | |
| [[ "${?}" -ne "0" ]] && echo "Error: Download failed." && exit 1 | |
| # Create directory symlinks for packaging | |
| ln -sf /builder/fnnas ${{ github.workspace }}/fnnas | |
| ln -sf /builder/fnnas /home/runner/work/_actions/ophub/fnnas/main/fnnas | |
| echo "build_tag=${build_tag}" >> ${GITHUB_ENV} | |
| echo "status=success" >> ${GITHUB_OUTPUT} | |
| - name: Package FnNAS for target boards | |
| if: ${{ steps.down.outputs.status == 'success' && !cancelled() }} | |
| uses: ophub/fnnas@main | |
| with: | |
| fnnas_path: fnnas/*.img.xz | |
| fnnas_board: ${{ inputs.fnnas_board }} | |
| fnnas_kernel: ${{ inputs.fnnas_kernel }} | |
| auto_kernel: ${{ inputs.auto_kernel }} | |
| kernel_repo: ${{ inputs.kernel_repo }} | |
| rootfs_expand: ${{ inputs.rootfs_expand }} | |
| builder_name: ${{ inputs.builder_name }} | |
| - name: Upload packaged FnNAS to Release | |
| uses: ophub/upload-to-releases@main | |
| if: ${{ env.PACKAGED_STATUS == 'success' && !cancelled() }} | |
| with: | |
| tag: ${{ env.build_tag }} | |
| artifacts: ${{ env.PACKAGED_OUTPUTPATH }}/* | |
| allow_updates: true | |
| remove_artifacts: false | |
| replaces_artifacts: true | |
| make_latest: true | |
| gh_token: ${{ secrets.GITHUB_TOKEN }} | |
| body: | | |
| - Built based on the fnnas.com [official Arm64 image](https://github.com/ophub/fnnas/releases/tag/fnnas_base_image), | |
| fully preserving the original official system experience. | |
| Extends support to a wider range of Amlogic, Rockchip, and Allwinner devices. | |
| - 基于 fnnas.com [官方 Arm64 镜像](https://github.com/ophub/fnnas/releases/tag/fnnas_base_image) 构建, | |
| 完整保留官方原版系统体验。 | |
| 扩展支持更多基于 Amlogic、Rockchip 及 Allwinner 平台的设备。 |