Github Actions
This project relies heavily on Github Actions to build and release the binaries. The actions are defined in the .github/workflows
directory.
Github repo Actions settings
Section titled “Github repo Actions settings”The required permissions for each workflow and job have been configured granularly in the workflows themselves. The permissions are defined in the permissions
section of the workflow.
Workflows
Section titled “Workflows”These workflows are using a reusable caller workflow that allows for inputs to be passed to the reusable workflows. This allows for a single workflow to be used to call multiple workflows with different inputs.
This is the structure of the workflows:
ci-main-reusable-caller├─ ci-debian-build├─ ci-alpine-build├─ ci-alpine-release└─ ci-auto-rerun-failed-jobs
ci-main-reusable-caller
The primary reusable caller workflow
name: ci - main reusable caller
on: workflow_dispatch: inputs: script_name: description: "Which script to run?" required: true default: "qbt-nox-static.bash" type: choice options: ["qbt-nox-static.bash", "qbittorrent-nox-static.sh"] debian-build: description: "Debian: build" required: true default: false type: boolean alpine-build: description: "Alpine: build" required: true default: true type: boolean workflow-files: description: "Workflow files" required: true default: true type: boolean icu: description: "Enable icu" required: true default: false type: boolean debug: description: "Debug builds (symbols)" required: true default: false type: boolean release: description: "Release assets?" required: true default: true type: boolean distinct_id: description: "Distinct id" required: false type: string skip_rerun: description: "Skip rerun?" required: true default: false type: boolean retries: description: "Number of rerun retries" required: true default: "1" type: choice options: ["1", "2", "3", "4", "5", "6", "7", "8", "9"]
permissions: {}
jobs: ci-debian-build: if: github.event.inputs.debian-build == 'true' concurrency: group: ci-debian-build cancel-in-progress: true permissions: id-token: write contents: read attestations: write uses: ./.github/workflows/ci-debian-build.yml with: distinct_id: ${{ github.event.inputs.distinct_id }} workflow-files: ${{ github.event.inputs.workflow-files == 'true' && 'yes' || 'no' }} icu: ${{ github.event.inputs.icu == 'true' && 'no' || 'yes' }} debug: ${{ github.event.inputs.debug == 'true' && 'yes' || 'no' }} script_name: ${{ github.event.inputs.script_name }}
ci-alpine-build: if: github.event.inputs.alpine-build == 'true' concurrency: group: ci-alpine-build cancel-in-progress: true permissions: id-token: write contents: read attestations: write uses: ./.github/workflows/ci-alpine-build.yml with: distinct_id: ${{ github.event.inputs.distinct_id }} workflow-files: ${{ github.event.inputs.workflow-files == 'true' && 'yes' || 'no' }} icu: ${{ github.event.inputs.icu == 'true' && 'no' || 'yes' }} debug: ${{ github.event.inputs.debug == 'true' && 'yes' || 'no' }} script_name: ${{ github.event.inputs.script_name }}
ci-alpine-release: needs: [ci-alpine-build] if: github.event.inputs.release == 'true' && contains(needs.*.result, 'success') && !contains(needs.*.result, 'failure') && !contains(needs.*.result, 'cancelled') concurrency: group: ci-alpine-release cancel-in-progress: true permissions: contents: write uses: ./.github/workflows/ci-alpine-release.yml with: distinct_id: ${{ github.event.inputs.distinct_id }}
ci-auto-rerun-failed-jobs: if: failure() && (github.event.inputs.skip_rerun || 'false') == 'false' needs: [ci-debian-build, ci-alpine-build, ci-alpine-release] concurrency: group: ci-auto-rerun-failed-jobs cancel-in-progress: true permissions: actions: write runs-on: ubuntu-24.04-arm env: GH_TOKEN: "${{ secrets.AUTO_RERUN || github.token }}" github_repo: "" # To use ci-auto-rerun-failed-jobs.yml hosted in a remote repository else default to the current repository. Requires PAT token AUTO_RERUN retries: ${{ github.event.inputs.retries || '1' }} distinct_id: ${{ github.event.inputs.distinct_id }} steps: - uses: actions/checkout@v4 with: persist-credentials: false - name: ci-auto-rerun-failed-jobs via ${{ env.github_repo || github.repository }} run: > gh workflow run ci-auto-rerun-failed-jobs-action.yml --repo "${github_repo:-$GITHUB_REPOSITORY}" -f github_repo=${GITHUB_REPOSITORY} -f run_id=${GITHUB_RUN_ID} -f attempts=${GITHUB_RUN_ATTEMPT} -f retries=${retries} -f distinct_id=${distinct_id}
ci-debian-build
The debian build workflow
name: ci - debian build
on: workflow_call: inputs: distinct_id: description: "Distinct id" required: false type: string workflow-files: description: "Alpine: workflow-files files" required: true type: string icu: description: "enable icu" required: true type: string debug: description: "debug builds" required: true type: string script_name: description: "script name" required: true type: string
jobs: build: runs-on: ${{ matrix.runs_on }} strategy: fail-fast: false matrix: runs_on: ["ubuntu-24.04", "ubuntu-24.04-arm"] os_id: ["debian", "ubuntu"] os_version_id: ["bookworm", "noble"] qbt_cross_name: ["default", "aarch64", "x86_64", "riscv64"] qbt_libtorrent_version: ["1.2", "2.0"] qbt_build_tool: [""] qbt_qt_version: ["6"] exclude: - os_id: "debian" qbt_cross_name: "riscv64" - os_id: "debian" os_version_id: "noble" - os_id: "ubuntu" os_version_id: "bookworm" - runs_on: "ubuntu-24.04" qbt_cross_name: "x86_64" - runs_on: "ubuntu-24.04-arm" qbt_cross_name: "aarch64" include: - runs_on: "ubuntu-24.04" host_name: "x86_64" - runs_on: "ubuntu-24.04-arm" host_name: "aarch64" - qbt_build_tool: "" qbt_qt_version_name: ""
name: "${{ matrix.host_name}}-${{ matrix.os_id }}-${{ matrix.os_version_id }}-${{ matrix.qbt_cross_name }}-${{ matrix.qbt_qt_version_name }}libtorrent-v${{ matrix.qbt_libtorrent_version }}"
env: qbt_build_dir: "qbt-build" container_name: "multiarch" script_name: ${{ inputs.script_name }} set_skip_icu: ${{ inputs.icu }} set_workflow_files: ${{ inputs.workflow-files }} set_build_debug: ${{ inputs.debug }} set_qbt_mcm_url: "" # default is userdocs/qbt-musl-cross-make set_qbt_with_qemu: "" # default is yes set_qbt_host_deps: "" # default is no set_qbt_host_deps_repo: "" # default is userdocs/qbt-host-deps
steps: - name: Checkout ${{ inputs.distinct_id }} uses: actions/checkout@v4 with: persist-credentials: false
- name: Host - Create Docker template env file ${{ inputs.distinct_id }} run: | printf '%s\n' "qbt_revision_url=${{ github.repository }}" > env.custom printf '%s\n' "qbt_zlib_type=zlib" >> env.custom printf '%s\n' "qbt_skip_icu=${set_skip_icu}" >> env.custom printf '%s\n' "qbt_boost_tag=${{ matrix.qbt_boost_tag }}" >> env.custom printf '%s\n' "qbt_libtorrent_version=${{ matrix.qbt_libtorrent_version }}" >> env.custom printf '%s\n' "qbt_libtorrent_tag=${{ matrix.qbt_libtorrent_tag }}" >> env.custom printf '%s\n' "qbt_libtorrent_master_jamfile=" >> env.custom printf '%s\n' "qbt_qt_version=${{ matrix.qbt_qt_version }}" >> env.custom printf '%s\n' "qbt_qt_tag=${{ matrix.qbt_qt_tag }}" >> env.custom printf '%s\n' "qbt_qbittorrent_tag=${{ matrix.qbt_qbittorrent_tag }}" >> env.custom printf '%s\n' "qbt_build_dir=${{ env.qbt_build_dir }}" >> env.custom printf '%s\n' "qbt_build_tool=${{ matrix.qbt_build_tool }}" >> env.custom printf '%s\n' "qbt_cross_name=${{ matrix.qbt_cross_name }}" >> env.custom printf '%s\n' "qbt_mcm_url=${set_qbt_mcm_url}" >> env.custom printf '%s\n' "qbt_patches_url=${{ github.repository }}" >> env.custom printf '%s\n' "qbt_workflow_files=${set_workflow_files}" >> env.custom printf '%s\n' "qbt_cache_dir=" >> env.custom printf '%s\n' "qbt_optimise_strip=" >> env.custom printf '%s\n' "qbt_build_debug=${set_build_debug}" >> env.custom printf '%s\n' "qbt_standard=" >> env.custom printf '%s\n' "qbt_static_ish=" >> env.custom printf '%s\n' "qbt_optimise=${qbt_optimise}" >> env.custom printf '%s\n' "qbt_with_qemu=${set_qbt_with_qemu}" >> env.custom printf '%s\n' "qbt_host_deps=${set_qbt_host_deps}" >> env.custom printf '%s\n\n' "qbt_host_deps_repo=${set_qbt_host_deps_repo}" >> env.custom
- name: Host - Debian based specific env ${{ inputs.distinct_id }} if : matrix.os_id != 'alpine' run: | printf '%s\n' "LANG=C.UTF-8" >> env.custom printf '%s\n' "LC_ALL=C.UTF-8" >> env.custom printf '%s\n\n' "DEBIAN_FRONTEND=noninteractive" >> env.custom
- name: Host - Bootstrap qemu uses: userdocs/actions/qemu@main
- uses: userdocs/actions/qbt_docker@main with: # if the env.custom file exists, it will be used to pass environment distinct_id: ${{ inputs.distinct_id }} use_host_env: "false" container_name: ${{ env.container_name }} os_id: ${{ matrix.os_id }} os_version_id: ${{ matrix.os_version_id }} custom_docker_commands: "" additional_alpine_apps: "bash curl git" additional_debian_apps: "bash curl git"
- name: Host - patches ${{ inputs.distinct_id }} run: mkdir -p ${qbt_build_dir}/patches && cp -r patches/* ${qbt_build_dir}/patches/
- name: Docker - bootstrap_deps ${{ inputs.distinct_id }} if: inputs.script_name == 'qbt-nox-static.bash' run: docker exec ${container_name} bash ${script_name} bootstrap_deps
- name: Docker - Bootstrap build ${{ inputs.distinct_id }} run: docker exec -u gh:gh ${container_name} bash ${script_name} -bs-a
- name: Docker - glibc ${{ inputs.distinct_id }} if : matrix.os_id != 'alpine' run: docker exec -u gh:gh ${container_name} bash ${script_name} glibc
- name: Docker - zlib ${{ inputs.distinct_id }} run: docker exec -u gh:gh ${container_name} bash ${script_name} zlib
- name: Docker - iconv ${{ inputs.distinct_id }} if: matrix.qbt_libtorrent_version == '1.2' run: docker exec -u gh:gh ${container_name} bash ${script_name} iconv
- name: Docker - icu ${{ inputs.distinct_id }} if: env.set_skip_icu == 'no' run: docker exec -u gh:gh ${container_name} bash ${script_name} icu
- name: Docker - openssl ${{ inputs.distinct_id }} run: docker exec -u gh:gh ${container_name} bash ${script_name} openssl
- name: Docker - boost ${{ inputs.distinct_id }} run: docker exec -u gh:gh ${container_name} bash ${script_name} boost
- name: Docker - libtorrent ${{ inputs.distinct_id }} run: docker exec -u gh:gh ${container_name} bash ${script_name} libtorrent
- name: Docker - double_conversion ${{ inputs.distinct_id }} if: matrix.qbt_build_tool == '' run: docker exec -u gh:gh ${container_name} bash ${script_name} double_conversion
- name: Docker - qtbase ${{ inputs.distinct_id }} run: docker exec -u gh:gh ${container_name} bash ${script_name} qtbase
- name: Docker - qttools ${{ inputs.distinct_id }} run: docker exec -u gh:gh ${container_name} bash ${script_name} qttools
- name: Docker - qbittorrent ${{ inputs.distinct_id }} run: docker exec -u gh:gh ${container_name} bash ${script_name} qbittorrent
- name: Docker - Set release asset name ${{ inputs.distinct_id }} run: docker exec -u gh:gh -w /home/gh/${{ env.qbt_build_dir }}/completed ${container_name} mv -f qbittorrent-nox ${{ matrix.qbt_cross_name }}-${{ matrix.qbt_qt_version_name }}qbittorrent-nox
# - name: Generate artifact attestation ${{ inputs.distinct_id }} # uses: actions/attest-build-provenance@v2 # with: # subject-path: "${{ env.qbt_build_dir }}/completed/${{ matrix.qbt_cross_name }}-${{ matrix.qbt_qt_version_name }}qbittorrent-nox"
# - name: Docker - Release Info ${{ inputs.distinct_id }} # run: docker exec -u gh:gh -w /home/gh/${{ env.qbt_build_dir }}/release_info ${container_name} bash -c 'mv *.md *.json '/home/gh/${{ env.qbt_build_dir }}/completed''
# - name: Host - Upload libtorrent-v${{ matrix.qbt_libtorrent_version }}-qbittorrent-nox and release info artifact ${{ inputs.distinct_id }} # if: success() # uses: actions/upload-artifact@v4 # with: # name: libtorrent-v${{ matrix.qbt_libtorrent_version }}-${{ matrix.qbt_cross_name }}-${{ matrix.qbt_qt_version_name }}qbittorrent-nox # path: | # ${{ env.qbt_build_dir }}/completed/* # !${{ env.qbt_build_dir }}/completed/*.png
# - name: Host - Upload cmake graphs artifact ${{ inputs.distinct_id }} # if: success() && matrix.qbt_build_tool == '' # uses: actions/upload-artifact@v4 # with: # name: "${{ matrix.qbt_cross_name }}-libtorrent-v${{ matrix.qbt_libtorrent_version }}-graphs" # path: "${{ env.qbt_build_dir }}/completed/*.png"
# - name: Host - Upload build dir on error or cancel # if: ( cancelled() || failure() ) # uses: actions/upload-artifact@v4 # with: # name: "${{ matrix.qbt_cross_name }}-libtorrent-v${{ matrix.qbt_libtorrent_version }}-logs" # path: "${{ env.qbt_build_dir }}"
ci-alpine-build
The alpine build workflow
name: ci - alpine build
on: workflow_call: inputs: distinct_id: description: "Distinct id" required: false type: string workflow-files: description: "Alpine: workflow-files files" required: true type: string icu: description: "enable icu" required: true type: string debug: description: "debug builds" required: true type: string script_name: description: "script name" required: true type: string
jobs: build: runs-on: ${{ matrix.runs_on }} strategy: fail-fast: false matrix: runs_on: ["ubuntu-24.04-arm"] os_id: [alpine] os_version_id: [edge] qbt_cross_name: ["armhf", "armv7", "aarch64", "riscv64", "x86_64", "x86"] qbt_libtorrent_version: ["1.2", "2.0"] qbt_build_tool: [""] qbt_qbittorrent_tag: [""] include: - qbt_build_tool: "" qbt_qt_version_name: ""
name: "${{ matrix.qbt_cross_name }}-${{ matrix.qbt_qt_version_name }}libtorrent-v${{ matrix.qbt_libtorrent_version }}"
env: qbt_build_dir: "qbt-build" container_name: "multiarch" script_name: ${{ inputs.script_name }} set_skip_icu: ${{ inputs.icu }} set_workflow_files: ${{ inputs.workflow-files }} set_build_debug: ${{ inputs.debug }} set_qbt_mcm_url: "" # default is userdocs/qbt-musl-cross-make set_qbt_with_qemu: "" # default is yes set_qbt_host_deps: "" # default is no set_qbt_host_deps_repo: "" # default is userdocs/qbt-host-deps
steps: - name: Checkout ${{ inputs.distinct_id }} uses: actions/checkout@v4 with: persist-credentials: false
- name: Download ${{ env.script_name }} run: | # Make sure the branch is set to master for qbittorrent-nox-static and main qbittorrent-nox-static-test if [[ ! -f "${script_name}" ]]; then echo "Downloading ${script_name} from userdocs/qbittorrent-nox-static" curl -LO "https://raw.githubusercontent.com/userdocs/qbittorrent-nox-static/refs/heads/master/${script_name}" chmod +x "${script_name}" fi
- name: Host - Create Docker template env file ${{ inputs.distinct_id }} run: | printf '%s\n' "qbt_revision_url=${{ github.repository }}" > env.custom printf '%s\n' "qbt_zlib_type=zlib" >> env.custom printf '%s\n' "qbt_skip_icu=${set_skip_icu}" >> env.custom printf '%s\n' "qbt_boost_tag=${{ matrix.qbt_boost_tag }}" >> env.custom printf '%s\n' "qbt_libtorrent_version=${{ matrix.qbt_libtorrent_version }}" >> env.custom printf '%s\n' "qbt_libtorrent_tag=${{ matrix.qbt_libtorrent_tag }}" >> env.custom printf '%s\n' "qbt_libtorrent_master_jamfile=" >> env.custom printf '%s\n' "qbt_qt_version=${{ matrix.qbt_qt_version }}" >> env.custom printf '%s\n' "qbt_qt_tag=${{ matrix.qbt_qt_tag }}" >> env.custom printf '%s\n' "qbt_qbittorrent_tag=${{ matrix.qbt_qbittorrent_tag }}" >> env.custom printf '%s\n' "qbt_build_dir=${qbt_build_dir}" >> env.custom printf '%s\n' "qbt_build_tool=${{ matrix.qbt_build_tool }}" >> env.custom printf '%s\n' "qbt_cross_name=${{ matrix.qbt_cross_name }}" >> env.custom printf '%s\n' "qbt_mcm_url=${set_qbt_mcm_url}" >> env.custom printf '%s\n' "qbt_patches_url=${{ github.repository }}" >> env.custom printf '%s\n' "qbt_workflow_files=${set_workflow_files}" >> env.custom printf '%s\n' "qbt_cache_dir=" >> env.custom printf '%s\n' "qbt_optimise_strip=" >> env.custom printf '%s\n' "qbt_build_debug=${set_build_debug}" >> env.custom printf '%s\n' "qbt_standard=" >> env.custom printf '%s\n' "qbt_static_ish=" >> env.custom printf '%s\n' "qbt_optimise=${qbt_optimise}" >> env.custom printf '%s\n' "qbt_with_qemu=${set_qbt_with_qemu}" >> env.custom printf '%s\n' "qbt_host_deps=${set_qbt_host_deps}" >> env.custom printf '%s\n\n' "qbt_host_deps_repo=${set_qbt_host_deps_repo}" >> env.custom
- name: Host - Debian based specific env ${{ inputs.distinct_id }} if : matrix.os_id != 'alpine' run: | printf '%s\n' "LANG=C.UTF-8" >> env.custom printf '%s\n' "LC_ALL=C.UTF-8" >> env.custom printf '%s\n\n' "DEBIAN_FRONTEND=noninteractive" >> env.custom
- name: Host - Bootstrap qemu uses: userdocs/actions/qemu@main
- uses: userdocs/actions/qbt_docker@main with: # if the env.custom file exists, it will be used to pass environment distinct_id: ${{ inputs.distinct_id }} use_host_env: "false" container_name: ${{ env.container_name }} os_id: ${{ matrix.os_id }} os_version_id: ${{ matrix.os_version_id }} custom_docker_commands: "" additional_alpine_apps: "bash curl git" additional_debian_apps: "bash curl git"
- name: Host - patches ${{ inputs.distinct_id }} if: hashFiles('patches/**') != '' run: mkdir -p ${qbt_build_dir}/patches && cp -rf patches/* ${qbt_build_dir}/patches/
- name: Docker - bootstrap_deps ${{ inputs.distinct_id }} if: inputs.script_name == 'qbt-nox-static.bash' run: docker exec -u gh:gh ${container_name} bash ${script_name} bootstrap_deps
- name: Docker - Bootstrap build ${{ inputs.distinct_id }} run: docker exec -u gh:gh ${container_name} bash ${script_name} -bs-a
- name: Docker - glibc ${{ inputs.distinct_id }} if : matrix.os_id != 'alpine' run: docker exec -u gh:gh ${container_name} bash ${script_name} glibc
- name: Docker - zlib ${{ inputs.distinct_id }} run: docker exec -u gh:gh ${container_name} bash ${script_name} zlib
- name: Docker - iconv ${{ inputs.distinct_id }} if: matrix.qbt_libtorrent_version == '1.2' run: docker exec -u gh:gh ${container_name} bash ${script_name} iconv
- name: Docker - icu ${{ inputs.distinct_id }} if: env.set_skip_icu == 'no' run: docker exec -u gh:gh ${container_name} bash ${script_name} icu
- name: Docker - openssl ${{ inputs.distinct_id }} run: docker exec -u gh:gh ${container_name} bash ${script_name} openssl
- name: Docker - boost ${{ inputs.distinct_id }} run: docker exec -u gh:gh ${container_name} bash ${script_name} boost
- name: Docker - libtorrent ${{ inputs.distinct_id }} run: docker exec -u gh:gh ${container_name} bash ${script_name} libtorrent
- name: Docker - double_conversion ${{ inputs.distinct_id }} if: matrix.qbt_build_tool == '' run: docker exec -u gh:gh ${container_name} bash ${script_name} double_conversion
- name: Docker - qtbase ${{ inputs.distinct_id }} run: docker exec -u gh:gh ${container_name} bash ${script_name} qtbase
- name: Docker - qttools ${{ inputs.distinct_id }} run: docker exec -u gh:gh ${container_name} bash ${script_name} qttools
- name: Docker - qbittorrent ${{ inputs.distinct_id }} run: docker exec -u gh:gh ${container_name} bash ${script_name} qbittorrent
- name: Docker - Set release asset name ${{ inputs.distinct_id }} run: docker exec -u gh:gh -w /home/gh/${qbt_build_dir}/completed ${container_name} mv -f qbittorrent-nox ${{ matrix.qbt_cross_name }}-${{ matrix.qbt_qt_version_name }}qbittorrent-nox
- name: Generate artifact attestation ${{ inputs.distinct_id }} uses: actions/attest-build-provenance@v2 with: subject-path: "${{ env.qbt_build_dir }}/completed/${{ matrix.qbt_cross_name }}-${{ matrix.qbt_qt_version_name }}qbittorrent-nox"
- name: Docker - Release Info ${{ inputs.distinct_id }} run: docker exec -u gh:gh -w /home/gh/${qbt_build_dir}/release_info ${container_name} bash -c 'mv *.md *.json '/home/gh/${qbt_build_dir}/completed''
- name: Host - Upload libtorrent-v${{ matrix.qbt_libtorrent_version }}-qbittorrent-nox and release info artifact ${{ inputs.distinct_id }} if: success() uses: actions/upload-artifact@v4 with: name: libtorrent-v${{ matrix.qbt_libtorrent_version }}-${{ matrix.qbt_cross_name }}-${{ matrix.qbt_qt_version_name }}qbittorrent-nox path: | ${{ env.qbt_build_dir }}/completed/* !${{ env.qbt_build_dir }}/completed/*.png
- name: Host - Upload cmake graphs artifact ${{ inputs.distinct_id }} if: success() && matrix.qbt_build_tool == '' uses: actions/upload-artifact@v4 with: name: "${{ matrix.qbt_cross_name }}-libtorrent-v${{ matrix.qbt_libtorrent_version }}-graphs" path: "${{ env.qbt_build_dir }}/completed/*.png"
# - name: Host - Upload build dir on error or cancel # if: ( cancelled() || failure() ) # uses: actions/upload-artifact@v4 # with: # name: "${{ matrix.qbt_cross_name }}-libtorrent-v${{ matrix.qbt_libtorrent_version }}-logs" # path: "${{ env.qbt_build_dir }}"
ci-alpine-release
The alpine release workflow
name: ci - alpine-release
on: workflow_call: inputs: distinct_id: description: "Distinct ID for the artifacts" required: true type: string
jobs: release: runs-on: ubuntu-24.04-arm strategy: fail-fast: false matrix: qbt_libtorrent_version: ["1.2", "2.0"] include: - qbt_libtorrent_version: "1.2" preview_release: true
- qbt_libtorrent_version: "2.0" preview_release: false
name: "Publish release libtorrent-v${{ matrix.qbt_libtorrent_version }}"
env: qbt_build_dir: "qbt-build"
steps: - name: Checkout ${{ inputs.distinct_id }} uses: actions/checkout@v4 with: persist-credentials: false
- name: Pandoc - Bootstrap run: | pandoc_git_tag="$(git ls-remote -q -t --refs https://github.com/jgm/pandoc.git | awk '/tags\/[0-9]/{sub("refs/tags/", ""); print $2 }' | awk '!/^$/' | sort -rV | head -n 1)" curl -sLo- "https://github.com/jgm/pandoc/releases/latest/download/pandoc-${pandoc_git_tag}-linux-$(dpkg --print-architecture).tar.gz" | tar xzf - --strip-components 2 -C "$(pwd)" --exclude="share"
- name: Host - Download 1.2 qbittorrent-nox artifacts ${{ inputs.distinct_id }} uses: actions/download-artifact@v4 with: path: "1.2" pattern: libtorrent-v1.2-*-qbittorrent-nox merge-multiple: true
- name: Host - Download 2.0 qbittorrent-nox artifacts ${{ inputs.distinct_id }} uses: actions/download-artifact@v4 with: path: "2.0" pattern: libtorrent-v2.0-*-qbittorrent-nox merge-multiple: true
- name: Host - merge release-info ${{ inputs.distinct_id }} run: | if [[ ${{ matrix.qbt_libtorrent_version }} == "1.2" ]]; then for release in 1\.2/*-release.md; do [[ -f "${release}" ]] && release+=("${release}") done revision="$(jq -r .revision 1\.2/*-dependency-version.json | head -n1)" boost="$(jq -r .boost 1\.2/*-dependency-version.json | head -n1)" fi
if [[ ${{ matrix.qbt_libtorrent_version }} == "2.0" ]]; then for release in 2\.0/*-release.md; do [[ -f "${release}" ]] && release+=("${release}") done revision="$(jq -r .revision 2\.0/*-dependency-version.json | head -n1)" boost="$(jq -r .boost 2\.0/*-dependency-version.json | head -n1)" fi
readarray -t release_sorted < <(printf '%s\n' "${release[@]}" | sort)
for dependency_version_files in 1\.2/*-dependency-version.json 2\.0/*-dependency-version.json; do if [[ -f "${dependency_version_files}" ]]; then sed -r 's/"boost": (.*)/BOOST_PLACEHOLDER/g' -i "${dependency_version_files}" sed -r 's/"revision": (.*)/REVISION_PLACEHOLDER/g' -i "${dependency_version_files}" dependency_version+=("${dependency_version_files}") fi done
readarray -t dependency_version_sorted < <(printf '%s\n' "${dependency_version[@]}" | sort)
paste -d '\n' "${release_sorted[@]}" | uniq | awk '!(NF && seen[$0]++) || /^>/' > "tmp-release.md" paste -d '\n' "${dependency_version_sorted[@]}" | uniq | awk '!(NF && seen[$0]++)' > "dependency-version.json"
sed -i "s|BOOST_PLACEHOLDER|\"boost\": \"${boost}\",|" dependency-version.json sed -i "s|REVISION_PLACEHOLDER|\"revision\": \"${revision}\"|" dependency-version.json
./pandoc --wrap=preserve -f gfm tmp-release.md -t gfm -o release.md
- name: Host - Bootstrap release tag ${{ inputs.distinct_id }} run: printf '%s\n' "release_tag=$(cat ${{ matrix.qbt_libtorrent_version }}/tag.md)" >> $GITHUB_ENV
- name: Host - Bootstrap release title ${{ inputs.distinct_id }} run: printf '%s\n' "release_title=$(cat ${{ matrix.qbt_libtorrent_version }}/title.md)" >> $GITHUB_ENV
- name: Host- Create release - tag - assets ${{ inputs.distinct_id }} uses: ncipollo/release-action@v1 with: prerelease: "${{ matrix.preview_release }}" artifacts: "${{ matrix.qbt_libtorrent_version }}/*-qbittorrent-nox,dependency-version.json" replacesArtifacts: true tag: "${{ env.release_tag }}" name: "${{ env.release_title }}" bodyFile: "release.md" allowUpdates: true token: "${{ github.TOKEN }}"
ci-auto-rerun-failed-jobs-action
This workflow automatically reruns any failed jobs. Mostly targeted for the release jobs to ensure the release is created.
name: ci - auto rerun failed jobs
on: workflow_dispatch: inputs: run_id: description: "The run id of the workflow to rerun" required: true attempts: description: "The number of attempts to rerun the workflow" required: true retries: description: "The number of retries to rerun the workflow" required: true github_repo: description: "The repository to rerun the workflow" required: false distinct_id: description: "The distinct id of the workflow to rerun" required: false
run-name: ci auto rerun failed jobs - attempt ${{ inputs.attempts }}
jobs: gh-cli-rerun: name: rerun - attempt ${{ inputs.attempts }} permissions: actions: write runs-on: ubuntu-24.04-arm env: GH_TOKEN: "${{ secrets.AUTO_RERUN || github.token }}" steps: - name: Host - Checkout action ${{ inputs.distinct_id }} uses: actions/checkout@v4 with: persist-credentials: false
- uses: userdocs/gh-cli-workflow-reruns/actions/auto-rerun-failed@main with: run_id: ${{ inputs.run_id }} attempts: ${{ inputs.attempts }} retries: ${{ inputs.retries }} github_repo: ${{ inputs.github_repo || github.repository }} distinct_id: ${{ inputs.distinct_id || github.run_id }}