From 06df00c8110e3d9295a17522f409814957901df9 Mon Sep 17 00:00:00 2001 From: daywalker90 Date: Wed, 22 Jul 2026 12:07:40 +0200 Subject: [PATCH 1/2] Dockerfile: add protobuf-compiler for vls signer step After 608f6952ea2772a31f4699580bce75a8f82f7f1c the vls docker image build fails because it is missing protoc. ``` > [vls-builder 9/10] RUN cargo build --release --target x86_64-unknown-linux-gnu: 177.2 177.2 Caused by: 177.2 process didn't exit successfully: `/opt/validating-lightning-signer/target/release/build/lightning-storage-server-85c73031cf3e0f51/build-script-build` (exit status: 1) 177.2 --- stdout 177.2 cargo:rerun-if-changed=proto/lss.proto 177.2 cargo:rerun-if-changed=proto 177.2 177.2 --- stderr 177.2 Error: Custom { kind: NotFound, error: "Could not find `protoc`. If `protoc` is installed, try setting the `PROTOC` environment variable to the path of the `protoc` binary. To install it on Debian, run `apt-get install protobuf-compiler`. It is also available at https://github.com/protocolbuffers/protobuf/releases For more information: https://docs.rs/prost-build/#sourcing-protoc" } 177.2 warning: build failed, waiting for other jobs to finish... ``` vls 0.14 also has an external dependency that requires protoc, so vls vendoring it would not be enough. --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index 6714e5f4775f..b6285d8bc6a2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -188,6 +188,7 @@ RUN dpkg --add-architecture ${target_arch_dpkg} RUN apt-get update && \ apt-get install -qq -y --no-install-recommends \ + protobuf-compiler \ pkg-config:${target_arch_dpkg} \ crossbuild-essential-${target_arch_dpkg} && \ apt-get clean && \ From 1a22d0eb1314dab6165535867e1f8d3be11ddc73 Mon Sep 17 00:00:00 2001 From: daywalker90 Date: Thu, 23 Jul 2026 13:58:17 +0200 Subject: [PATCH 2/2] CI: restructure release workflows Binaries, docker images, and python packages are now separated into build and publish flows. First everything gets built and if every build step succeeds the publish step can continue. Also fan out the docker build into a matrix to speed up the workflow. Changelog-None --- .github/workflows/check-release-tag.yml | 56 ++++++ .github/workflows/docker-build.yml | 86 ++++++++ .github/workflows/docker-publish.yml | 67 +++++++ .github/workflows/docker-release.yml | 134 ------------- .github/workflows/pypi-build.yml | 48 +++++ .github/workflows/pypi-publish.yml | 58 ++++++ .github/workflows/pypi.yml | 96 --------- .github/workflows/release-build.yml | 67 +++++++ .github/workflows/release-publish.yml | 69 +++++++ .github/workflows/release.yml | 251 ++++++++---------------- 10 files changed, 536 insertions(+), 396 deletions(-) create mode 100644 .github/workflows/check-release-tag.yml create mode 100644 .github/workflows/docker-build.yml create mode 100644 .github/workflows/docker-publish.yml delete mode 100644 .github/workflows/docker-release.yml create mode 100644 .github/workflows/pypi-build.yml create mode 100644 .github/workflows/pypi-publish.yml delete mode 100644 .github/workflows/pypi.yml create mode 100644 .github/workflows/release-build.yml create mode 100644 .github/workflows/release-publish.yml diff --git a/.github/workflows/check-release-tag.yml b/.github/workflows/check-release-tag.yml new file mode 100644 index 000000000000..1b2b3aa1e49c --- /dev/null +++ b/.github/workflows/check-release-tag.yml @@ -0,0 +1,56 @@ +name: Check release tag + +on: + workflow_call: + inputs: + version: + type: string + required: false + skip_validation: + type: boolean + default: false + outputs: + version: + description: "Resolved release version" + value: ${{ jobs.check.outputs.version }} + +jobs: + check: + name: Validate tag against .version file and release content + runs-on: ubuntu-24.04 + outputs: + version: ${{ steps.resolve.outputs.version }} + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Validate tag matches .version file + id: resolve + run: | + if [[ "${{ github.ref_type }}" != "tag" ]]; then + echo "::notice::Not triggered by a tag push (ref_type=${{ github.ref_type }}); skipping .version check." + echo "version=${{ inputs.version }}" >> "$GITHUB_OUTPUT" + exit 0 + fi + + if [[ ! -f .version ]]; then + echo "::error::.version file not found in repository root." + exit 1 + fi + + FILE_VERSION="$(tr -d '[:space:]' < .version)" + TAG_VERSION="${{ github.ref_name }}" + + if [[ "$TAG_VERSION" != "$FILE_VERSION" ]]; then + echo "::error::Tag '$TAG_VERSION' does not match version in .version file ('$FILE_VERSION'). Refusing to release." + exit 1 + fi + + echo "Tag '$TAG_VERSION' matches .version file." + echo "version=$TAG_VERSION" >> "$GITHUB_OUTPUT" + + - name: Validate release + if: ${{ !inputs.skip_validation }} + run: tools/check-release.sh --version=${{ steps.resolve.outputs.version }} diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml new file mode 100644 index 000000000000..6b2479309cad --- /dev/null +++ b/.github/workflows/docker-build.yml @@ -0,0 +1,86 @@ +name: Docker build + +on: + workflow_call: + inputs: + version: + type: string + required: true + dh-repository-owner: + type: string + required: true + platforms-to-build: + type: string + required: true + +jobs: + # Turn the comma-separated platforms-to-build input into a JSON matrix array, + # so we can fan out per-platform without hardcoding the list twice. + plan: + name: Plan platform matrix + runs-on: ubuntu-24.04 + outputs: + platforms: ${{ steps.plan.outputs.platforms }} + steps: + - id: plan + run: | + IFS=',' read -ra ARR <<< "${{ inputs.platforms-to-build }}" + JSON=$(printf '%s\n' "${ARR[@]}" | jq -R . | jq -sc .) + echo "platforms=$JSON" >> "$GITHUB_OUTPUT" + + build: + name: Build ${{ matrix.target == 'lightningd-vls-signer' && 'vls' || 'normal' }} / ${{ matrix.platform }} + needs: plan + strategy: + fail-fast: false + matrix: + target: + - lightningd + - lightningd-vls-signer + platform: ${{ fromJson(needs.plan.outputs.platforms) }} + runs-on: ${{ matrix.platform == 'linux/arm64' && 'ubuntu-22.04-arm' || 'ubuntu-22.04' }} + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Set up QEMU + if: matrix.platform == 'linux/arm/v7' + uses: docker/setup-qemu-action@v4 + + - name: Setup Docker Buildx + uses: docker/setup-buildx-action@v4 + + - name: Log in to Docker Hub + uses: docker/login-action@v4 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Build single-platform image, push by digest + id: build + uses: docker/build-push-action@v7 + with: + context: . + file: ./Dockerfile + target: ${{ matrix.target }} + platforms: ${{ matrix.platform }} + build-args: | + VERSION=${{ inputs.version }} + outputs: type=image,name=${{ inputs.dh-repository-owner }}/lightningd,push-by-digest=true,name-canonical=true,push=true + cache-from: type=gha,scope=${{ matrix.target }}-${{ matrix.platform }} + cache-to: type=gha,mode=max,scope=${{ matrix.target }}-${{ matrix.platform }} + + - name: Save digest + run: | + mkdir -p /tmp/digests + echo "${{ steps.build.outputs.digest }}" > /tmp/digests/digest.txt + + - name: Upload digest + uses: actions/upload-artifact@v7 + with: + name: digest_${{ matrix.target }}_${{ strategy.job-index }} + path: /tmp/digests/digest.txt + if-no-files-found: error + retention-days: 1 diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml new file mode 100644 index 000000000000..78bcaf64eefd --- /dev/null +++ b/.github/workflows/docker-publish.yml @@ -0,0 +1,67 @@ +name: Docker publish + +on: + workflow_call: + inputs: + version: + type: string + required: true + dh-repository-owner: + type: string + required: true + push-latest: + type: string + required: true + +jobs: + publish: + name: Tag and publish ${{ matrix.target }} + runs-on: ubuntu-22.04 + strategy: + fail-fast: false + matrix: + include: + - target: lightningd + tag_suffix: '' + - target: lightningd-vls-signer + tag_suffix: '-vls' + steps: + - name: Setup Docker Buildx + uses: docker/setup-buildx-action@v4 + + - name: Log in to Docker Hub + uses: docker/login-action@v4 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Download platform digests for this target + uses: actions/download-artifact@v8 + with: + pattern: digest_${{ matrix.target }}_* + path: /tmp/digests + merge-multiple: false + + - name: Set up values + run: | + DIGEST_REFS="" + for f in /tmp/digests/*/digest.txt; do + D=$(cat "$f") + DIGEST_REFS="$DIGEST_REFS ${{ inputs.dh-repository-owner }}/lightningd@${D}" + done + echo "DIGEST_REFS=$DIGEST_REFS" >> $GITHUB_ENV + + if [[ "${{ inputs.push-latest }}" == "true" ]] || + ([[ "${{ github.ref_type }}" == "tag" ]] && [[ ! "${{ inputs.version }}" =~ rc ]]); then + echo "PUSHLATEST=true" >> $GITHUB_ENV + else + echo "PUSHLATEST=false" >> $GITHUB_ENV + fi + + - name: Create and push real tag(s) + run: | + TAG_ARGS=(-t "${{ inputs.dh-repository-owner }}/lightningd:${{ inputs.version }}${{ matrix.tag_suffix }}") + if [[ "$PUSHLATEST" == "true" ]]; then + TAG_ARGS+=(-t "${{ inputs.dh-repository-owner }}/lightningd:latest${{ matrix.tag_suffix }}") + fi + docker buildx imagetools create "${TAG_ARGS[@]}" $DIGEST_REFS diff --git a/.github/workflows/docker-release.yml b/.github/workflows/docker-release.yml deleted file mode 100644 index 738634999db2..000000000000 --- a/.github/workflows/docker-release.yml +++ /dev/null @@ -1,134 +0,0 @@ -name: Publish multi-platform docker images - -on: - push: - tags: - - 'v[0-9]+.[0-9]+' - - 'v[0-9]+.[0-9]+.[0-9]+' - - 'v[0-9]+.[0-9]+[0-9a-z]+' - workflow_dispatch: - inputs: - version: - description: 'Release version' - required: true - - repository-name: - description: 'Docker repository name' - default: 'elementsproject' - required: false - - platforms-to-build: - description: 'List of platforms to build' - default: 'linux/amd64,linux/arm64,linux/arm/v7' - required: false - - push-latest: - description: 'Push the latest tag also?' - default: 'false' - required: false - -jobs: - build: - runs-on: ubuntu-22.04 - strategy: - fail-fast: false # Let each tag finish. - matrix: - include: - - target: lightningd - tag_suffix: '' - - target: lightningd-vls-signer - tag_suffix: '-vls' - - steps: - - name: Checkout repository - uses: actions/checkout@v6 - with: - ref: ${{ github.ref }} # Ensures the branch triggering the workflow is checked out - fetch-depth: 0 - - - name: Set up QEMU - uses: docker/setup-qemu-action@v4 - - - name: Setup Docker Buildx - uses: docker/setup-buildx-action@v4 - - - name: Log in to Docker Hub - uses: docker/login-action@v4 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} - - - name: Set up values for ${{ matrix.target }} - id: set-values - run: | - if [[ "${{ github.event.inputs.version }}" != "" ]]; then - echo "Input version provided" - VERSION=${{ github.event.inputs.version }} - elif [[ ${{ github.ref_type }} == "tag" ]]; then - echo "This is a tag event" - VERSION=${{ github.ref_name }} - else - echo "No version provided and no tag found." - exit 1 - fi - echo "VERSION=$VERSION" >> $GITHUB_ENV - - if [[ "${{ github.event.inputs.repository-name }}" != "" ]]; then - REPONAME=${{ github.event.inputs.repository-name }} - else - REPONAME="elementsproject" - fi - echo "REPONAME=$REPONAME" >> $GITHUB_ENV - - if [[ "${{ github.event.inputs.platforms-to-build }}" != "" ]]; then - PLATFORMS=${{ github.event.inputs.platforms-to-build }} - else - PLATFORMS="linux/amd64,linux/arm64,linux/arm/v7" - fi - echo "PLATFORMS=$PLATFORMS" >> $GITHUB_ENV - - if [[ "${{ github.event.inputs.push-latest }}" == "true" ]] || - ([[ "${{ github.ref_type }}" == "tag" ]] && [[ ! "$VERSION" =~ rc ]]); then - echo "Latest true" - PUSHLATEST="true" - else - echo "Latest false" - PUSHLATEST="false" - fi - echo "PUSHLATEST=$PUSHLATEST" >> $GITHUB_ENV - - TAGS="$REPONAME/lightningd:$VERSION${{ matrix.tag_suffix }}" - if [[ "$PUSHLATEST" == "true" ]]; then - TAGS="$TAGS,$REPONAME/lightningd:latest${{ matrix.tag_suffix }}" - fi - echo "TAGS=$TAGS" >> $GITHUB_ENV - - - name: Print GitHub Ref Values - run: | - echo "TARGET: ${{ matrix.target }}" - echo "TAG SUFFIX: ${{ matrix.tag_suffix }}" - echo "GITHUB REF TYPE: ${{ github.ref_type }}" - echo "GITHUB REF NAME: ${{ github.ref_name }}" - echo "EVENT INPUT VERSION: ${{ github.event.inputs.version }}" - echo "EVENT INPUT REPO: ${{ github.event.inputs.repository-name }}" - echo "EVENT INPUT PLATFORMS: ${{ github.event.inputs.platforms-to-build }}" - echo "EVENT INPUT PUSH LATEST: ${{ github.event.inputs.push-latest }}" - echo "ENV VERSION: ${{ env.VERSION }}" - echo "ENV REPO NAME: ${{ env.REPONAME }}" - echo "ENV PLATFORMS: ${{ env.PLATFORMS }}" - echo "ENV PUSH LATEST: ${{ env.PUSHLATEST }}" - echo "ENV TAGS: ${{ env.TAGS }}" - - - name: Build and push Docker tag - ${{ env.TAGS }} - uses: docker/build-push-action@v7 - with: - context: . - file: ./Dockerfile - target: ${{ matrix.target }} - push: true - platforms: ${{ env.PLATFORMS }} - tags: ${{ env.TAGS }} - build-args: | - VERSION=${{ env.VERSION }} - cache-from: type=gha - cache-to: type=gha,mode=max diff --git a/.github/workflows/pypi-build.yml b/.github/workflows/pypi-build.yml new file mode 100644 index 000000000000..83f80eb7bca3 --- /dev/null +++ b/.github/workflows/pypi-build.yml @@ -0,0 +1,48 @@ +name: PyPI build + +on: + workflow_call: + inputs: + version: + type: string + required: true + +jobs: + build: + name: Build ${{ matrix.PACKAGE }} 🐍 + runs-on: ubuntu-22.04 + timeout-minutes: 120 + strategy: + fail-fast: false + matrix: + include: + - PACKAGE: pyln-client + - PACKAGE: pyln-testing + - PACKAGE: pyln-proto + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: '3.10' + + - name: Install uv + uses: astral-sh/setup-uv@v8.1.0 + + - name: Update pyln versions + run: | + make update-pyln-versions NEW_VERSION=${{ inputs.version }} + + - name: Build distribution 📦 + run: uv build --package ${{ matrix.PACKAGE }} + + - name: Upload distribution artifact + uses: actions/upload-artifact@v7 + with: + name: dist-${{ matrix.PACKAGE }} + path: dist/ + if-no-files-found: error diff --git a/.github/workflows/pypi-publish.yml b/.github/workflows/pypi-publish.yml new file mode 100644 index 000000000000..6244891c74a0 --- /dev/null +++ b/.github/workflows/pypi-publish.yml @@ -0,0 +1,58 @@ +name: PyPI publish + +on: + workflow_call: + inputs: + version: + type: string + required: true + dist-location: + type: string + required: true + +jobs: + publish: + name: Publish ${{ matrix.PACKAGE }} 🐍 + runs-on: ubuntu-22.04 + strategy: + fail-fast: false + matrix: + include: + - PACKAGE: pyln-client + - PACKAGE: pyln-testing + - PACKAGE: pyln-proto + steps: + - name: Download built distribution + uses: actions/download-artifact@v8 + with: + name: dist-${{ matrix.PACKAGE }} + path: dist/ + + - name: Determine PyPI distribution location + id: set-values + run: | + if [[ "${{ inputs.dist-location }}" != "" ]]; then + DISTLOCATION="${{ inputs.dist-location }}" + elif [[ "${{ github.ref_type }}" == "tag" ]] && [[ ! "${{ inputs.version }}" =~ rc ]]; then + DISTLOCATION="prod" + else + DISTLOCATION="test" + fi + echo "DISTLOCATION=$DISTLOCATION" >> "$GITHUB_OUTPUT" + echo "EVENT DISTLOCATION: ${{ github.event.inputs.dist-location }}" + echo "Resolved dist-location: $DISTLOCATION" + + - name: Install uv + uses: astral-sh/setup-uv@v8.1.0 + + - name: Publish distribution 📦 to Test PyPI + if: github.repository == 'ElementsProject/lightning' && steps.set-values.outputs.DISTLOCATION == 'test' + env: + UV_PUBLISH_TOKEN: ${{ secrets.TEST_PYPI_API_TOKEN }} + run: uv publish --publish-url https://test.pypi.org/legacy/ --check-url https://test.pypi.org/simple/ dist/* + + - name: Publish distribution 📦 to PyPI + if: github.repository == 'ElementsProject/lightning' && steps.set-values.outputs.DISTLOCATION == 'prod' + env: + UV_PUBLISH_TOKEN: ${{ secrets.PYPI_API_TOKEN }} + run: uv publish dist/* diff --git a/.github/workflows/pypi.yml b/.github/workflows/pypi.yml deleted file mode 100644 index 346c413f31db..000000000000 --- a/.github/workflows/pypi.yml +++ /dev/null @@ -1,96 +0,0 @@ -name: Publish Python 🐍 distributions 📦 to PyPI and TestPyPI - -on: - push: - tags: - - 'v[0-9]+.[0-9]+' - - 'v[0-9]+.[0-9]+.[0-9]+' - - 'v[0-9]+.[0-9]+[0-9a-z]+' - workflow_dispatch: - inputs: - dist-location: - description: 'Distribution location (test/prod)' - default: 'test' - required: false - -jobs: - deploy: - name: Build and publish ${{ matrix.package }} 🐍 - runs-on: ubuntu-22.04 - timeout-minutes: 120 - strategy: - fail-fast: true - matrix: - include: - - PACKAGE: pyln-client - WORKDIR: contrib/pyln-client - - PACKAGE: pyln-testing - WORKDIR: contrib/pyln-testing - - PACKAGE: pyln-proto - WORKDIR: contrib/pyln-proto - steps: - - name: Checkout repository - uses: actions/checkout@v6 - with: - # Need to fetch entire history in order to locate the version tag - fetch-depth: 0 - - - name: Check version tag - run: >- - git describe --tags --always --dirty=-modded --abbrev=7 - - - name: Setup Version - env: - WORKDIR: ${{ matrix.WORKDIR }} - run: | - echo "VERSION=$(git describe --tags --abbrev=0).post$(git describe --tags --abbrev=1 | awk -F "-" '{print $2}')" >> $GITHUB_ENV - - - name: Set up values - id: set-values - run: | - if [[ "${{ github.event.inputs.dist-location }}" != "" ]]; then - DISTLOCATION=${{ github.event.inputs.dist-location }} - elif [[ "${{ github.ref_type }}" == "tag" ]] && [[ ! "${{ github.ref_name }}" =~ rc ]]; then - DISTLOCATION="prod" - else - DISTLOCATION="test" - fi - echo "DISTLOCATION=$DISTLOCATION" >> $GITHUB_OUTPUT - echo "EVENT DISTLOCATION: ${{ github.event.inputs.dist-location }}" - echo "DISTRIBUTION LOCATION: $DISTLOCATION" - - - name: Set up Python - uses: actions/setup-python@v6 - with: - python-version: '3.10' - - - name: Install uv - uses: astral-sh/setup-uv@v8.1.0 - - - name: Update pyln versions - id: update-versions - run: | - export VERSION=$(git describe --tags --abbrev=0) - echo "Pyln VERSION: $VERSION" - make update-pyln-versions NEW_VERSION=$VERSION - - - name: Publish distribution 📦 to Test PyPI - if: github.repository == 'ElementsProject/lightning' && steps.set-values.outputs.DISTLOCATION == 'test' - env: - UV_PUBLISH_TOKEN: ${{ secrets.TEST_PYPI_API_TOKEN }} - WORKDIR: ${{ matrix.WORKDIR }} - run: | - echo "Pyln VERSION: $VERSION" - uv build --package ${{ matrix.PACKAGE }} - uv publish --publish-url https://test.pypi.org/legacy/ --check-url https://test.pypi.org/simple/ - - - name: Publish distribution 📦 to PyPI - if: github.repository == 'ElementsProject/lightning' && steps.set-values.outputs.DISTLOCATION == 'prod' - env: - UV_PUBLISH_TOKEN: ${{ secrets.PYPI_API_TOKEN }} - WORKDIR: ${{ matrix.WORKDIR }} - run: | - echo "UV VERSION PUBLISH: $(uv --version)" - echo "Pyln VERSION: $VERSION" - uv build --package ${{ matrix.PACKAGE }} - uv publish diff --git a/.github/workflows/release-build.yml b/.github/workflows/release-build.yml new file mode 100644 index 000000000000..b99965dc34f6 --- /dev/null +++ b/.github/workflows/release-build.yml @@ -0,0 +1,67 @@ +name: Release binaries build + +on: + workflow_call: + inputs: + version: + type: string + required: true + skip_validation: + type: boolean + required: true + +jobs: + releases: + name: Releases + runs-on: ubuntu-24.04 + strategy: + fail-fast: false + matrix: + target: + - 'bin-Fedora' + - 'bin-Ubuntu-jammy' + - 'bin-Ubuntu-noble' + - 'bin-Ubuntu-resolute' + steps: + - name: Git checkout + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Build environment setup + run: | + distribution=$(echo ${{ matrix.target }} | cut -d'-' -f3) + sudo docker run --rm -v $(pwd):/build ubuntu:${distribution} bash -c "\ + apt-get update && \ + apt-get install -y debootstrap && \ + debootstrap ${distribution} /build/${distribution}" + sudo tar -C ${distribution} -c . | docker import - ${distribution} + docker build -t cl-repro-${distribution} - < contrib/reprobuild/Dockerfile.${distribution} + if: contains(matrix.target, 'Ubuntu') + + - name: Build release + run: | + if [[ "${{ inputs.skip_validation }}" == "true" ]]; then + tools/build-release.sh ${{ matrix.target }} --force-version "${{ inputs.version }}" --force-unclean --force-mtime "$(date +%Y-%m-%d)" + else + tools/build-release.sh ${{ matrix.target }} + fi + + - name: Upload target artifacts + uses: actions/upload-artifact@v7 + with: + path: release/ + name: ${{ matrix.target }} + if-no-files-found: error + + artifact: + name: Construct release artifact + needs: releases + runs-on: ubuntu-24.04 + steps: + - name: Merge artifacts + uses: actions/upload-artifact/merge@v7 + with: + name: c-lightning-${{ inputs.version }} + pattern: bin-* + delete-merged: true diff --git a/.github/workflows/release-publish.yml b/.github/workflows/release-publish.yml new file mode 100644 index 000000000000..be7146ab126a --- /dev/null +++ b/.github/workflows/release-publish.yml @@ -0,0 +1,69 @@ +name: Release publish + +on: + workflow_call: + inputs: + version: + type: string + required: true + create_release: + type: boolean + required: true + +jobs: + release: + name: Sign and prepare release draft + runs-on: ubuntu-24.04 + steps: + - name: Git checkout + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Download artifact + uses: actions/download-artifact@v8 + with: + name: c-lightning-${{ inputs.version }} + path: release/ + + - name: Import GPG keys + id: gpg + uses: crazy-max/ghaction-import-gpg@v7 + with: + gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }} + passphrase: ${{ secrets.GPG_PASSPHRASE }} + trust_level: 5 + + - name: Set default GPG key + run: echo "default-key ${{ steps.gpg.outputs.keyid }}" >> ~/.gnupg/gpg.conf + + - name: Sign release + run: tools/build-release.sh --without-zip sign + + - name: Upload signed artifact + uses: actions/upload-artifact@v7 + with: + name: c-lightning-${{ inputs.version }} + overwrite: true + path: release/ + + - name: Determine release data + id: release_data + run: | + CHANGELOG_VERSION=${VERSION#v} + VERSION="${{ inputs.version }}" + CHANGELOG_VERSION=${VERSION#v} + CHANGELOG_TITLE=$(grep "## \[${CHANGELOG_VERSION}\]" CHANGELOG.md) + RELEASE_TITLE=$(echo $CHANGELOG_TITLE | cut -d'"' -f2) + echo "release_title=$RELEASE_TITLE" >> "$GITHUB_OUTPUT" + + - name: Prepare release draft + if: ${{ github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && inputs.create_release) }} + uses: softprops/action-gh-release@v3 + with: + name: "${{ inputs.version }} ${{ steps.release_data.outputs.release_title }}" + tag_name: ${{ inputs.version }} + draft: true + prerelease: contains(inputs.version, "-rc") + files: release/* + fail_on_unmatched_files: true diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 824264848463..7bb09de679b8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -7,6 +7,7 @@ on: - 'v[0-9]+.[0-9]+' - 'v[0-9]+.[0-9]+.[0-9]+' - 'v[0-9]+.[0-9]+[0-9a-z]+' + - 'v[0-9]+.[0-9]+.[0-9]+[0-9a-z]+' workflow_dispatch: inputs: version: @@ -20,173 +21,91 @@ on: description: Create a draft release default: false type: boolean + dh-repository-owner: + description: 'Dockerhub repository owner' + default: 'elementsproject' + platforms-to-build: + description: 'List of platforms to build' + default: 'linux/amd64,linux/arm64,linux/arm/v7' + push-latest: + description: 'Push the latest Docker tag' + type: boolean + default: false + dist-location: + description: 'PyPI distribution location' + type: choice + options: + - test + - prod + default: 'test' jobs: - check: - name: Check - outputs: - version: ${{ steps.capture.outputs.version }} - runs-on: ubuntu-24.04 - steps: - - name: Git checkout - uses: actions/checkout@v6 - with: - ref: ${{ github.ref }} - fetch-depth: 0 - - - name: Determine version - run: | - if [[ "${{ github.event.inputs.version }}" != "" ]]; then - VERSION="${{ github.event.inputs.version }}" - elif [ "${{ github.ref_type }}" == "tag" ]; then - VERSION="${{ github.ref_name }}" - else - echo "No release version provided and no tag found." - exit 1 - fi - echo "VERSION=$VERSION" >> "$GITHUB_ENV" - echo "Determined version: $VERSION" - - - name: Validate release - if: ${{ !(github.event_name == 'workflow_dispatch' && github.event.inputs.skip_validation) }} - run: tools/check-release.sh --version=${VERSION} - - - name: Catpure version output - id: capture - run: echo "version=${VERSION}" >> "$GITHUB_OUTPUT" - - releases: - name: Releases - needs: check - env: - version: ${{ needs.check.outputs.version }} + check-version: + name: Verify release tag + uses: ./.github/workflows/check-release-tag.yml + with: + version: ${{ github.event.inputs.version }} + skip_validation: ${{ github.event.inputs.skip_validation == 'true' }} + + + docker-build: + name: Docker build + needs: check-version + uses: ./.github/workflows/docker-build.yml + with: + version: ${{ needs.check-version.outputs.version }} + dh-repository-owner: ${{ github.event.inputs.dh-repository-owner || 'elementsproject' }} + platforms-to-build: ${{ github.event.inputs.platforms-to-build || 'linux/amd64,linux/arm64,linux/arm/v7' }} + secrets: inherit + + pypi-build: + name: PyPI build + needs: check-version + uses: ./.github/workflows/pypi-build.yml + with: + version: ${{ needs.check-version.outputs.version }} + secrets: inherit + + release-build: + name: Release binaries build + needs: check-version + uses: ./.github/workflows/release-build.yml + with: + version: ${{ needs.check-version.outputs.version }} + skip_validation: ${{ github.event.inputs.skip_validation == 'true' }} + secrets: inherit + + gate: + name: All builds succeeded + needs: [docker-build, pypi-build, release-build] runs-on: ubuntu-24.04 - strategy: - fail-fast: false # Let each build finish. - matrix: - target: - - 'bin-Fedora' - - 'bin-Ubuntu-jammy' - - 'bin-Ubuntu-noble' - - 'bin-Ubuntu-resolute' steps: - - name: Git checkout - uses: actions/checkout@v6 - with: - ref: ${{ github.ref }} - fetch-depth: 0 - - - name: Build environment setup - run: | - distribution=$(echo ${{ matrix.target }} | cut -d'-' -f3) - echo "Building base image for ${distribution}" - sudo docker run --rm -v $(pwd):/build ubuntu:${distribution} bash -c "\ - apt-get update && \ - apt-get install -y debootstrap && \ - debootstrap ${distribution} /build/${distribution}" - sudo tar -C ${distribution} -c . | docker import - ${distribution} - - # Build Docker image - docker build -t cl-repro-${distribution} - < contrib/reprobuild/Dockerfile.${distribution} - if: contains(matrix.target, 'Ubuntu') - - - name: Build release - run: | - # Allow build release to execute if manually triggered for testing - if [[ "${{ github.event_name }}" == "workflow_dispatch" && "${{ github.event.inputs.skip_validation }}" == "true" ]]; then - tools/build-release.sh ${{ matrix.target }} --force-version "${{ env.version }}" --force-unclean --force-mtime "$(date +%Y-%m-%d)" - else - tools/build-release.sh ${{ matrix.target }} - fi - - - name: Upload target artifacts - uses: actions/upload-artifact@v7 - with: - path: release/ - name: ${{ matrix.target }} - if-no-files-found: error - - artifact: - name: Construct release artifact - needs: - - check - - releases - env: - version: ${{ needs.check.outputs.version }} - runs-on: ubuntu-24.04 - steps: - - name: Merge artifacts - uses: actions/upload-artifact/merge@v7 - with: - name: c-lightning-${{ env.version }} - pattern: bin-* - delete-merged: true - - release: - name: Sign and prepare release draft - needs: - - check - - artifact - env: - version: ${{ needs.check.outputs.version }} - runs-on: ubuntu-24.04 - steps: - - name: Git checkout - uses: actions/checkout@v6 - with: - ref: ${{ github.ref }} - fetch-depth: 0 - - - name: Download artifact - uses: actions/download-artifact@v8 - with: - name: c-lightning-${{ env.version }} - path: release/ - - - name: Import GPG keys - id: gpg - uses: crazy-max/ghaction-import-gpg@v7 - with: - gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }} - passphrase: ${{ secrets.GPG_PASSPHRASE }} - trust_level: 5 - - - name: Set default GPG key - run: echo "default-key ${{ steps.gpg.outputs.keyid }}" >> ~/.gnupg/gpg.conf - - - name: Sign release - run: tools/build-release.sh --without-zip sign - - - name: Upload signed artifact - uses: actions/upload-artifact@v7 - with: - name: c-lightning-${{ env.version }} - overwrite: true - path: release/ - - - name: Determine release data - id: release_data - run: | - VERSION=${{ env.version }} - CHANGELOG_VERSION=${VERSION#v} - echo "CHANGELOG_VERSION=$CHANGELOG_VERSION" - echo "changelog_version=$CHANGELOG_VERSION" >> "$GITHUB_OUTPUT" - - CHANGELOG_TITLE=$(grep "## \[${CHANGELOG_VERSION}\]" CHANGELOG.md) - echo "CHANGELOG_TITLE=$CHANGELOG_TITLE" - echo "changelog_title=$CHANGELOG_TITLE" >> "$GITHUB_OUTPUT" - - RELEASE_TITLE=$(echo $CHANGELOG_TITLE | cut -d'"' -f2) - echo "RELEASE_TITLE=$RELEASE_TITLE" - echo "release_title=$RELEASE_TITLE" >> "$GITHUB_OUTPUT" - - - name: Prepare release draft - if: ${{ github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && github.event.inputs.create_release) }} - uses: softprops/action-gh-release@v3 - with: - name: "${{ env.version }} ${{ steps.release_data.outputs.release_title }}" - tag_name: ${{ env.version }} - draft: true - prerelease: contains(env.version, "-rc") - files: release/* - fail_on_unmatched_files: true + - run: echo "All three build paths succeeded — proceeding to publish." + + docker-publish: + name: Docker publish + needs: [check-version, gate] + uses: ./.github/workflows/docker-publish.yml + with: + version: ${{ needs.check-version.outputs.version }} + dh-repository-owner: ${{ github.event.inputs.dh-repository-owner || 'elementsproject' }} + push-latest: ${{ github.event.inputs.push-latest }} + secrets: inherit + + pypi-publish: + name: PyPI publish + needs: [check-version, gate] + uses: ./.github/workflows/pypi-publish.yml + with: + version: ${{ needs.check-version.outputs.version }} + dist-location: ${{ github.event.inputs.dist-location }} + secrets: inherit + + release-publish: + name: Release sign + draft + needs: [check-version, gate] + uses: ./.github/workflows/release-publish.yml + with: + version: ${{ needs.check-version.outputs.version }} + create_release: ${{ github.event.inputs.create_release == 'true' }} + secrets: inherit