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 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 && \