From 346c418b4a8c0e1f8c9aace44b00373a4bf76732 Mon Sep 17 00:00:00 2001 From: Earl Warren Date: Wed, 14 Jun 2023 13:32:20 +0200 Subject: [PATCH] [CI] Forgejo Actions based release process Refs: https://codeberg.org/forgejo/website/pulls/230 (cherry picked from commit 87d56bf6c73d726dae8aafbc7e147969f1899931) [CI] Forgejo Actions based release process (squash) base64 -w0 to avoid wrapping when the doer name is long as it creates a broken config.json (cherry picked from commit 9efdc27e49bdfb3e62401baf27b224385f9f3e5e) [CI] Forgejo Actions based release process (squash) generate .xz files and sources Generate .xz files Check .sha256 Generate the source tarbal (cherry picked from commit 7afec520c4b1032d7e67a05a41e4e2913bcd9312) [CI] Forgejo Actions based release process (squash) release notes (cherry picked from commit d8f4f4807b28297b318d2f555a76d0efef762cf7) [CI] Forgejo Actions based release process (squash) publish and sign release (cherry picked from commit a52778c74785fe57cdee3b64b4c6c8a326471532) (cherry picked from commit cf2ec6274094ac7aebda71d54c64581f528df00a) [CI] Forgejo Actions based release process (squash) version use Actions environment variables in Makefile (#25319) (#25318) uses Actions variable to determine the version. But Forgejo builds happen in a container where they are not available. Do not use them. Also verify the version of the binary is as expected for sanity check. (cherry picked from commit 6decf111a132a869f9e5c6f4d20e368b8f74309f) (cherry picked from commit 206d0b3886b2d56b585bf552e53d952b35f07284) [CI] read STORED_VERSION_FILE if available (cherry picked from commit af74085ebf51c91a51db865a66667fca511838d5) [CI] backward compatible executable compilation Add a new static-executable target to use in Dockerfiles and restore the $(EXECUTABLE) target to what it was before to for backward compatibility. The release process now builds static executables instead of dynamically linked ones which makes them more portable. It changes the requirements at compile time and is not backward compatible. In particular it may break packaging that rely on the target that currently creates a dynamically linked executable. (cherry picked from commit 84d02a174a4398b1f8ee62e08db5483a9859650f) (cherry picked from commit 854be47328cc0283119dfb78f9ba0b8306c85f75) [CI] Forgejo Actions based release process (squash) doc / ca / verbosity - Document workflow - Increase verbosity if VERBOSE=true - Download the Certificate Authority if behind the VPN (cherry picked from commit 168d5d586904835762d213b2b8815b458a38c78f) (cherry picked from commit 8756c9a72a40830441124256b7382f900a1052f8) (cherry picked from commit 2dad7ef20f3bf9ebe2425e2e28b66a4ca21c6786) [CI] Forgejo Actions based release process (squash) add assets sources-tarbal Refs: https://codeberg.org/forgejo/forgejo/issues/1115 (cherry picked from commit 5531d01f1981df665f5b8f642e9241e8ea4f4578) [CI] Forgejo Actions based release process (squash) add assets sources-tarbal bindata.go is a file, not a directory Refs: https://codeberg.org/forgejo/forgejo/issues/1115 (cherry picked from commit bd88a4477817be34ea86ebb2f460b9fe8ab5f1b7) (cherry picked from commit b408085138c578dfaacafbd4b7719ca926456855) [CI] Forgejo Actions based release process (squash) public/assets moved (cherry picked from commit d8c921d5a643ed05f2935348531996fe4d08c654) (cherry picked from commit f29e50b1a09b1a22fc2dbdb77e9a1def1196175b) [CI] Fix release notes link - Use substitution to replace all dots with dashes. - Resolves https://codeberg.org/forgejo/forgejo/issues/1163 (cherry picked from commit 96783728f53a072915cace392aa269adfe9a5c73) (cherry picked from commit c8d8bf8996beb650cd86cafb110e85e1e05917a0) [CI] pin go v1.20 for testing Refs: https://codeberg.org/forgejo/forgejo/issues/1228 (cherry picked from commit fd4b5a013ee0f31453b623d12001a8b810cd7ebc) (cherry picked from commit 00bb15f57f2ae5a11abc8b044ed99dc949e812a7) Conflicts: Dockerfile Dockerfile.rootless see https://codeberg.org/forgejo/forgejo/pulls/1303 (cherry picked from commit 6e2be54a6d95412ce770d4bab1a39c77591f44dc) --- .forgejo/actions/build-release/action.yml | 154 +++++++++++++++ .forgejo/actions/publish-release/action.yml | 110 +++++++++++ .forgejo/testdata/build-release/Dockerfile | 3 + .forgejo/testdata/build-release/Makefile | 5 + .../build-release/modules/public/bindata.go | 0 .../public/assets/css/placeholder | 0 .../public/assets/fonts/placeholder | 0 .../public/assets/js/placeholder | 0 .../workflows/build-release-integration.yml | 99 ++++++++++ .forgejo/workflows/build-release.yml | 186 ++++++++++++++++++ .forgejo/workflows/publish-release.yml | 60 ++++++ .forgejo/workflows/testing.yml | 12 +- Dockerfile | 35 +++- Dockerfile.rootless | 35 +++- Makefile | 33 ++-- 15 files changed, 684 insertions(+), 48 deletions(-) create mode 100644 .forgejo/actions/build-release/action.yml create mode 100644 .forgejo/actions/publish-release/action.yml create mode 100644 .forgejo/testdata/build-release/Dockerfile create mode 100644 .forgejo/testdata/build-release/Makefile create mode 100644 .forgejo/testdata/build-release/modules/public/bindata.go create mode 100644 .forgejo/testdata/build-release/public/assets/css/placeholder create mode 100644 .forgejo/testdata/build-release/public/assets/fonts/placeholder create mode 100644 .forgejo/testdata/build-release/public/assets/js/placeholder create mode 100644 .forgejo/workflows/build-release-integration.yml create mode 100644 .forgejo/workflows/build-release.yml create mode 100644 .forgejo/workflows/publish-release.yml diff --git a/.forgejo/actions/build-release/action.yml b/.forgejo/actions/build-release/action.yml new file mode 100644 index 0000000000..01fdfdedfc --- /dev/null +++ b/.forgejo/actions/build-release/action.yml @@ -0,0 +1,154 @@ +name: 'Build release' +author: 'Forgejo authors' +description: | + Build release + +inputs: + forgejo: + description: 'URL of the Forgejo instance where the release is uploaded' + required: true + owner: + description: 'User or organization where the release is uploaded, relative to the Forgejo instance' + required: true + repository: + description: 'Repository where the release is uploaded, relative to the owner' + required: true + doer: + description: 'Name of the user authoring the release' + required: true + tag-version: + description: 'Version of the release derived from the tag withint the leading v' + required: true + suffix: + description: 'Suffix to add to the image tag' + token: + description: 'token' + required: true + dockerfile: + description: 'path to the dockerfile' + default: 'Dockerfile' + platforms: + description: 'Coma separated list of platforms' + default: 'linux/amd64,linux/arm64' + release-notes: + description: 'Full text of the release notes' + default: 'Release notes placeholder' + binary-name: + description: 'Name of the binary' + binary-path: + description: 'Path of the binary within the container to extract into binary-name' + verbose: + description: 'Increase the verbosity level' + default: 'false' + +runs: + using: "composite" + steps: + - run: echo "${{ github.action_path }}" >> $GITHUB_PATH + shell: bash + + - name: Install dependencies + run: | + apt-get install -y -qq xz-utils + + - name: set -x if verbose is required + id: verbose + run: | + if ${{ inputs.verbose }} ; then + echo "shell=set -x" >> "$GITHUB_OUTPUT" + fi + + - name: Create the insecure and buildx-config variables for the container registry + id: registry + run: | + ${{ steps.verbose.outputs.shell }} + url="${{ inputs.forgejo }}" + hostport=${url##http*://} + hostport=${hostport%%/} + echo "host-port=${hostport}" >> "$GITHUB_OUTPUT" + if ! [[ $url =~ ^http:// ]] ; then + exit 0 + fi + cat >> "$GITHUB_OUTPUT" < /etc/docker/daemon.json < ~/.docker/config.json + env: + CI_REGISTRY: "${{ steps.registry.outputs.host-port }}" + + - name: Build the container image for each architecture + uses: https://github.com/docker/build-push-action@v4 + # workaround until https://github.com/docker/build-push-action/commit/d8823bfaed2a82c6f5d4799a2f8e86173c461aba is in @v4 or @v5 is released + env: + ACTIONS_RUNTIME_TOKEN: '' + with: + context: . + push: true + file: ${{ inputs.dockerfile }} + platforms: ${{ inputs.platforms }} + tags: ${{ steps.registry.outputs.host-port }}/${{ inputs.owner }}/${{ inputs.repository }}:${{ inputs.tag-version }}${{ inputs.suffix }} + + - name: Extract the binary from the container images into the release directory + if: inputs.binary-name != '' + run: | + ${{ steps.verbose.outputs.shell }} + mkdir -p release + cd release + for platform in $(echo ${{ inputs.platforms }} | tr ',' ' '); do + arch=$(echo $platform | sed -e 's|linux/||g' -e 's|arm/v6|arm-6|g') + docker create --platform $platform --name forgejo-$arch ${{ steps.registry.outputs.host-port }}/${{ inputs.owner }}/${{ inputs.repository }}:${{ inputs.tag-version }}${{ inputs.suffix }} + binary="${{ inputs.binary-name }}-${{ inputs.tag-version }}-linux" + docker cp forgejo-$arch:${{ inputs.binary-path }} $binary-$arch + chmod +x $binary-$arch + # the displayed version has a + instead of the first -, deal with it + pattern=$(echo "${{ inputs.tag-version }}" | tr - .) + if ! ./$binary-$arch --version | grep "$pattern" ; then + echo "ERROR: expected version pattern $pattern not found in the output of $binary-$arch --version" + ./$binary-$arch --version + exit 1 + fi + xz --keep -9 $binary-$arch + shasum -a 256 $binary-$arch > $binary-$arch.sha256 + shasum -a 256 $binary-$arch.xz > $binary-$arch.xz.sha256 + docker rm forgejo-$arch + done + + - name: publish release + if: inputs.binary-name != '' + uses: https://code.forgejo.org/actions/forgejo-release@v1 + with: + direction: upload + release-dir: release + release-notes: "${{ inputs.release-notes }}" + token: ${{ inputs.token }} + verbose: ${{ steps.verbose.outputs.value }} diff --git a/.forgejo/actions/publish-release/action.yml b/.forgejo/actions/publish-release/action.yml new file mode 100644 index 0000000000..569ec55bfd --- /dev/null +++ b/.forgejo/actions/publish-release/action.yml @@ -0,0 +1,110 @@ +name: 'Publish release' +author: 'Forgejo authors' +description: | + Publish release + +inputs: + forgejo: + description: 'URL of the Forgejo instance where the release is uploaded (e.g. https://codeberg.org)' + required: true + from-owner: + description: 'the owner from which a release is to be copied (e.g forgejo-integration)' + required: true + to-owner: + description: 'the owner to which a release is to be copied (e.g. forgejo-experimental). It has be an organization in which doer has the required permissions. Or be the same as the doer' + required: true + repo: + description: 'the repository from which a release is to be copied relative to from-owner and to-owner' + default: 'forgejo' + ref-name: + description: 'ref_name of the tag of the release to be copied (e.g. github.ref_name)' + required: true + doer: + description: 'Name of the user authoring the release (e.g. release-team). The user must be authorized to create packages in to-owner and releases in to-owner/repo' + required: true + token: + description: 'application token created on forgejo by the doer, with a scope allowing it to create packages in to-owner and releases in to-owner/repo' + required: true + gpg-private-key: + description: 'GPG Private Key to sign the release artifacts' + gpg-passphrase: + description: 'Passphrase of the GPG Private Key' + verbose: + description: 'Increase the verbosity level' + default: 'false' + +runs: + using: "composite" + steps: + - id: hostport + run: | + url="${{ inputs.forgejo }}" + hostport=${url##http*://} + hostport=${hostport%%/} + echo "value=$hostport" >> "$GITHUB_OUTPUT" + + - id: tag-version + run: | + version="${{ inputs.ref-name }}" + version=${version##*v} + echo "value=$version" >> "$GITHUB_OUTPUT" + + - name: Create the release notes + id: release-notes + run: | + anchor=${{ steps.tag-version.outputs.value }} + anchor=${anchor//./-} + cat >> "$GITHUB_OUTPUT" < /app/gitea/gitea ; chmod +x /app/gitea/gitea diff --git a/.forgejo/testdata/build-release/Makefile b/.forgejo/testdata/build-release/Makefile new file mode 100644 index 0000000000..406acd06d2 --- /dev/null +++ b/.forgejo/testdata/build-release/Makefile @@ -0,0 +1,5 @@ +VERSION ?= $(shell cat VERSION 2>/dev/null) +sources-tarbal: + mkdir -p dist/release + echo $(VERSION) > VERSION + sources=forgejo-src-$(VERSION).tar.gz ; tar --transform 's|^./|forgejo-src-$(VERSION)/|' -czf dist/release/forgejo-src-$(VERSION).tar.gz . ; cd dist/release ; shasum -a 256 $$sources > $$sources.sha256 diff --git a/.forgejo/testdata/build-release/modules/public/bindata.go b/.forgejo/testdata/build-release/modules/public/bindata.go new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.forgejo/testdata/build-release/public/assets/css/placeholder b/.forgejo/testdata/build-release/public/assets/css/placeholder new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.forgejo/testdata/build-release/public/assets/fonts/placeholder b/.forgejo/testdata/build-release/public/assets/fonts/placeholder new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.forgejo/testdata/build-release/public/assets/js/placeholder b/.forgejo/testdata/build-release/public/assets/js/placeholder new file mode 100644 index 0000000000..e69de29bb2 diff --git a/.forgejo/workflows/build-release-integration.yml b/.forgejo/workflows/build-release-integration.yml new file mode 100644 index 0000000000..d893bd39af --- /dev/null +++ b/.forgejo/workflows/build-release-integration.yml @@ -0,0 +1,99 @@ +name: Integration tests for the release process + +on: + push: + paths: + - Makefile + - Dockerfile + - Dockerfile.rootless + - docker/** + - .forgejo/actions/build-release/action.yml + - .forgejo/workflows/build-release.yml + - .forgejo/workflows/build-release-integration.yml + +jobs: + release-simulation: + runs-on: self-hosted + if: secrets.ROLE != 'forgejo-integration' && secrets.ROLE != 'forgejo-experimental' && secrets.ROLE != 'forgejo-release' + steps: + - uses: actions/checkout@v3 + + - id: forgejo + uses: https://code.forgejo.org/actions/setup-forgejo@v1 + with: + user: root + password: admin1234 + image-version: 1.19 + lxc-ip-prefix: 10.0.9 + + - name: publish the forgejo release + run: | + set -x + + version=1.2.3 + cat > /etc/docker/daemon.json < $binary$suffix + if test "$suffix" = .xz ; then + unxz --keep $binary$suffix + fi + chmod +x $binary + ./$binary --version | grep $version + curl --fail -L -sS $url/root/forgejo/releases/download/v$version/$binary$suffix.sha256 > $binary$suffix.sha256 + shasum -a 256 --check $binary$suffix.sha256 + rm $binary$suffix + done + done + + sources=forgejo-src-$version.tar.gz + curl --fail -L -sS $url/root/forgejo/releases/download/v$version/$sources > $sources + curl --fail -L -sS $url/root/forgejo/releases/download/v$version/$sources.sha256 > $sources.sha256 + shasum -a 256 --check $sources.sha256 + + docker pull ${{ steps.forgejo.outputs.host-port }}/root/forgejo:$version + docker pull ${{ steps.forgejo.outputs.host-port }}/root/forgejo:$version-rootless diff --git a/.forgejo/workflows/build-release.yml b/.forgejo/workflows/build-release.yml new file mode 100644 index 0000000000..7e6aabb8a3 --- /dev/null +++ b/.forgejo/workflows/build-release.yml @@ -0,0 +1,186 @@ +name: Build release + +on: + push: + tags: 'v*' + +jobs: + release: + runs-on: self-hosted + # root is used for testing, allow it + if: secrets.ROLE == 'forgejo-integration' || github.repository_owner == 'root' + steps: + - uses: actions/checkout@v3 + + - name: Increase the verbosity when there are no secrets + id: verbose + run: | + if test -z "${{ secrets.TOKEN }}"; then + value=true + else + value=false + fi + echo "value=$value" >> "$GITHUB_OUTPUT" + + - name: Sanitize the name of the repository + id: repository + run: | + set -x # comment out + repository="${{ github.repository }}" + echo "value=${repository##*/}" >> "$GITHUB_OUTPUT" + + - name: When in a test environment, create a token + id: token + if: ${{ secrets.TOKEN == '' }} + run: | + apt-get -qq install -y jq + url="${{ env.GITHUB_SERVER_URL }}" + hostport=${url##http*://} + hostport=${hostport%%/} + doer=root + api=http://$doer:admin1234@$hostport/api/v1/users/$doer/tokens + curl -sS -X DELETE $api/release + token=$(curl -sS -X POST -H 'Content-Type: application/json' --data-raw '{"name": "release", "scopes": ["all"]}' $api | jq --raw-output .sha1) + echo "value=${token}" >> "$GITHUB_OUTPUT" + + - uses: https://code.forgejo.org/actions/setup-go@v4 + with: + go-version: ">=1.20" + check-latest: true + + - name: Create the version from ref_name + id: tag-version + run: | + version="${{ github.ref_name }}" + version=${version##*v} + echo "value=$version" >> "$GITHUB_OUTPUT" + + - name: Create the release notes + id: release-notes + run: | + cat >> "$GITHUB_OUTPUT" < 2.0.1 + # css-loader: 6.8.1 => 6.8.1 + # esbuild-loader: 3.0.1 => 3.0.1 + # license-checker-webpack-plugin: 0.2.1 => 0.2.1 + # monaco-editor-webpack-plugin: 7.0.1 => 7.0.1 + # vue-loader: 17.2.2 => 17.2.2 + # webpack: 5.87.0 => 5.87.0 + # webpack-cli: 5.1.4 => 5.1.4 + # + chown -R $(id -u) . + make VERSION=$version TAGS=bindata sources-tarbal + mv dist/release release + + ( + tmp=$(mktemp -d) + tar --directory $tmp -zxvf release/*$version*.tar.gz + cd $tmp/* + # + # Verify `make frontend` files are available + # + test -d public/assets/css + test -d public/assets/fonts + test -d public/assets/js + # + # Verify `make generate` files are available + # + test -f modules/public/bindata.go + # + # Sanity check to verify that the source tarbal knows the + # version and is able to rebuild itself from it. + # + # When in sources the version is determined with git. + # When in the tarbal the version is determined from a VERSION file. + # + make sources-tarbal + tarbal=$(echo dist/release/*$version*.tar.gz) + if ! test -f $tarbal ; then + echo $tarbal does not exist + find dist release + exit 1 + fi + ) + + - name: build container & release (when TOKEN secret is not set) + if: ${{ secrets.TOKEN == '' }} + uses: ./.forgejo/actions/build-release + with: + forgejo: "${{ env.GITHUB_SERVER_URL }}" + owner: "${{ env.GITHUB_REPOSITORY_OWNER }}" + repository: "${{ steps.repository.outputs.value }}" + doer: root + tag-version: "${{ steps.tag-version.outputs.value }}" + token: ${{ steps.token.outputs.value }} + platforms: linux/amd64,linux/arm64,linux/arm/v6 + release-notes: "${{ steps.release-notes.outputs.value }}" + binary-name: forgejo + binary-path: /app/gitea/gitea + verbose: ${{ steps.verbose.outputs.value }} + + - name: build rootless container (when TOKEN secret is not set) + if: ${{ secrets.TOKEN == '' }} + uses: ./.forgejo/actions/build-release + with: + forgejo: "${{ env.GITHUB_SERVER_URL }}" + owner: "${{ env.GITHUB_REPOSITORY_OWNER }}" + repository: "${{ steps.repository.outputs.value }}" + doer: root + tag-version: "${{ steps.tag-version.outputs.value }}" + token: ${{ steps.token.outputs.value }} + platforms: linux/amd64,linux/arm64,linux/arm/v6 + suffix: -rootless + dockerfile: Dockerfile.rootless + verbose: ${{ steps.verbose.outputs.value }} + + - name: build container & release (when TOKEN secret is set) + if: ${{ secrets.TOKEN != '' }} + uses: ./.forgejo/actions/build-release + with: + forgejo: "${{ env.GITHUB_SERVER_URL }}" + owner: "${{ env.GITHUB_REPOSITORY_OWNER }}" + repository: "${{ steps.repository.outputs.value }}" + doer: "${{ secrets.DOER }}" + tag-version: "${{ steps.tag-version.outputs.value }}" + token: "${{ secrets.TOKEN }}" + platforms: linux/amd64,linux/arm64,linux/arm/v6 + release-notes: "${{ steps.release-notes.outputs.value }}" + binary-name: forgejo + binary-path: /app/gitea/gitea + verbose: ${{ steps.verbose.outputs.value }} + + - name: build rootless container (when TOKEN secret is set) + if: ${{ secrets.TOKEN != '' }} + uses: ./.forgejo/actions/build-release + with: + forgejo: "${{ env.GITHUB_SERVER_URL }}" + owner: "${{ env.GITHUB_REPOSITORY_OWNER }}" + repository: "${{ steps.repository.outputs.value }}" + doer: "${{ secrets.DOER }}" + tag-version: "${{ steps.tag-version.outputs.value }}" + token: "${{ secrets.TOKEN }}" + platforms: linux/amd64,linux/arm64,linux/arm/v6 + suffix: -rootless + dockerfile: Dockerfile.rootless + verbose: ${{ steps.verbose.outputs.value }} diff --git a/.forgejo/workflows/publish-release.yml b/.forgejo/workflows/publish-release.yml new file mode 100644 index 0000000000..c76e78cc12 --- /dev/null +++ b/.forgejo/workflows/publish-release.yml @@ -0,0 +1,60 @@ +# SPDX-License-Identifier: MIT +# +# See also https://forgejo.org/docs/next/developer/RELEASE/#release-process +# +# https://codeberg.org/forgejo-experimental/forgejo +# +# Copies a release from codeberg.org/forgejo-integration to codeberg.org/forgejo-experimental +# +# ROLE: forgejo-experimental +# FORGEJO: https://codeberg.org +# FROM_OWNER: forgejo-integration +# TO_OWNER: forgejo-experimental +# DOER: forgejo-experimental-ci +# TOKEN: +# +# https://forgejo.octopuce.forgejo.org/forgejo/forgejo +# +# Copies & sign a release from codeberg.org/forgejo-integration to codeberg.org/forgejo +# +# ROLE: forgejo-release +# FORGEJO: https://codeberg.org +# FROM_OWNER: forgejo-integration +# TO_OWNER: forgejo +# DOER: release-team +# TOKEN: +# GPG_PRIVATE_KEY: +# GPG_PASSPHRASE: +# +name: Pubish release + +on: + push: + tags: 'v*' + +jobs: + publish: + runs-on: self-hosted + if: secrets.DOER != '' && secrets.FORGEJO != '' && secrets.TO_OWNER != '' && secrets.FROM_OWNER != '' && secrets.TOKEN != '' + steps: + - name: install the certificate authority + if: secrets.ROLE == 'forgejo-release' + run: | + apt-get install -qq -y wget + wget --no-check-certificate -O /usr/local/share/ca-certificates/enough.crt https://forgejo.octopuce.forgejo.org/forgejo/enough/raw/branch/main/certs/2023-05-13/ca.crt + update-ca-certificates --fresh + + - uses: actions/checkout@v3 + + - name: copy & sign binaries and container images from one owner to another + uses: ./.forgejo/actions/publish-release + with: + forgejo: ${{ secrets.FORGEJO }} + from-owner: ${{ secrets.FROM_OWNER }} + to-owner: ${{ secrets.TO_OWNER }} + ref-name: ${{ github.ref_name }} + doer: ${{ secrets.DOER }} + token: ${{ secrets.TOKEN }} + gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }} + gpg-passphrase: ${{ secrets.GPG_PASSPHRASE }} + verbose: ${{ secrets.VERBOSE }} diff --git a/.forgejo/workflows/testing.yml b/.forgejo/workflows/testing.yml index eb1958528a..05732ed42a 100644 --- a/.forgejo/workflows/testing.yml +++ b/.forgejo/workflows/testing.yml @@ -14,7 +14,7 @@ jobs: - uses: https://code.forgejo.org/actions/checkout@v3 - uses: https://code.forgejo.org/actions/setup-go@v4 with: - go-version: ">=1.20" + go-version: "1.21" check-latest: true - run: make deps-backend deps-tools - run: make lint-backend @@ -26,7 +26,7 @@ jobs: - uses: https://code.forgejo.org/actions/checkout@v3 - uses: https://code.forgejo.org/actions/setup-go@v4 with: - go-version: ">=1.20" + go-version: "1.21" check-latest: true - run: make deps-backend deps-tools - run: make --always-make checks-backend # ensure the "go-licenses" make target runs @@ -39,7 +39,7 @@ jobs: - uses: https://code.forgejo.org/actions/checkout@v3 - uses: https://code.forgejo.org/actions/setup-go@v4 with: - go-version: ">=1.20.0" + go-version: "1.21" - run: | git config --add safe.directory '*' chown -R gitea:gitea . /go @@ -76,7 +76,7 @@ jobs: - uses: https://code.forgejo.org/actions/checkout@v3 - uses: https://code.forgejo.org/actions/setup-go@v4 with: - go-version: ">=1.20.0" + go-version: "1.21" - run: | git config --add safe.directory '*' chown -R gitea:gitea . /go @@ -109,7 +109,7 @@ jobs: - uses: https://code.forgejo.org/actions/checkout@v3 - uses: https://code.forgejo.org/actions/setup-go@v4 with: - go-version: ">=1.20.0" + go-version: "1.21" - run: | git config --add safe.directory '*' chown -R gitea:gitea . /go @@ -136,7 +136,7 @@ jobs: - uses: https://code.forgejo.org/actions/checkout@v3 - uses: https://code.forgejo.org/actions/setup-go@v4 with: - go-version: ">=1.20.0" + go-version: "1.21" - run: | git config --add safe.directory '*' chown -R gitea:gitea . /go diff --git a/Dockerfile b/Dockerfile index 04adedbe55..8068e824a1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,6 @@ -#Build stage -FROM docker.io/library/golang:1.21-alpine3.18 AS build-env +FROM --platform=$BUILDPLATFORM tonistiigi/xx AS xx + +FROM --platform=$BUILDPLATFORM docker.io/library/golang:1.21-alpine3.18 as build-env ARG GOPROXY ENV GOPROXY ${GOPROXY:-direct} @@ -9,19 +10,33 @@ ARG TAGS="sqlite sqlite_unlock_notify" ENV TAGS "bindata timetzdata $TAGS" ARG CGO_EXTRA_CFLAGS -#Build deps +# +# Transparently cross compile for the target platform +# +COPY --from=xx / / +ARG TARGETPLATFORM +RUN apk --no-cache add clang lld +RUN xx-apk --no-cache add gcc musl-dev +ENV CGO_ENABLED=1 +RUN xx-go --wrap +# +# for go generate and binfmt to find +# without it the generate phase will fail with +# #19 25.04 modules/public/public_bindata.go:8: running "go": exit status 1 +# #19 25.39 aarch64-binfmt-P: Could not open '/lib/ld-musl-aarch64.so.1': No such file or directory +# why exactly is it needed? where is binfmt involved? +# +RUN cp /*-alpine-linux-musl*/lib/ld-musl-*.so.1 /lib || true + RUN apk --no-cache add build-base git nodejs npm -#Setup repo COPY . ${GOPATH}/src/code.gitea.io/gitea WORKDIR ${GOPATH}/src/code.gitea.io/gitea -#Checkout version if set -RUN if [ -n "${GITEA_VERSION}" ]; then git checkout "${GITEA_VERSION}"; fi \ - && make clean-all build - -# Begin env-to-ini build -RUN go build contrib/environment-to-ini/environment-to-ini.go +RUN make clean-all +RUN make frontend +RUN go build contrib/environment-to-ini/environment-to-ini.go && xx-verify environment-to-ini +RUN make go-check generate-backend static-executable && xx-verify gitea FROM docker.io/library/alpine:3.18 LABEL maintainer="contact@forgejo.org" diff --git a/Dockerfile.rootless b/Dockerfile.rootless index 870db396bb..d7676c906a 100644 --- a/Dockerfile.rootless +++ b/Dockerfile.rootless @@ -1,5 +1,6 @@ -#Build stage -FROM docker.io/library/golang:1.21-alpine3.18 AS build-env +FROM --platform=$BUILDPLATFORM tonistiigi/xx AS xx + +FROM --platform=$BUILDPLATFORM docker.io/library/golang:1.21-alpine3.18 as build-env ARG GOPROXY ENV GOPROXY ${GOPROXY:-direct} @@ -9,19 +10,33 @@ ARG TAGS="sqlite sqlite_unlock_notify" ENV TAGS "bindata timetzdata $TAGS" ARG CGO_EXTRA_CFLAGS -#Build deps +# +# Transparently cross compile for the target platform +# +COPY --from=xx / / +ARG TARGETPLATFORM +RUN apk --no-cache add clang lld +RUN xx-apk --no-cache add gcc musl-dev +ENV CGO_ENABLED=1 +RUN xx-go --wrap +# +# for go generate and binfmt to find +# without it the generate phase will fail with +# #19 25.04 modules/public/public_bindata.go:8: running "go": exit status 1 +# #19 25.39 aarch64-binfmt-P: Could not open '/lib/ld-musl-aarch64.so.1': No such file or directory +# why exactly is it needed? where is binfmt involved? +# +RUN cp /*-alpine-linux-musl*/lib/ld-musl-*.so.1 /lib || true + RUN apk --no-cache add build-base git nodejs npm -#Setup repo COPY . ${GOPATH}/src/code.gitea.io/gitea WORKDIR ${GOPATH}/src/code.gitea.io/gitea -#Checkout version if set -RUN if [ -n "${GITEA_VERSION}" ]; then git checkout "${GITEA_VERSION}"; fi \ - && make clean-all build - -# Begin env-to-ini build -RUN go build contrib/environment-to-ini/environment-to-ini.go +RUN make clean-all +RUN make frontend +RUN go build contrib/environment-to-ini/environment-to-ini.go && xx-verify environment-to-ini +RUN make go-check generate-backend static-executable && xx-verify gitea FROM docker.io/library/alpine:3.18 LABEL maintainer="contact@forgejo.org" diff --git a/Makefile b/Makefile index 24a49c33a1..d7346ab7ed 100644 --- a/Makefile +++ b/Makefile @@ -79,31 +79,14 @@ endif STORED_VERSION_FILE := VERSION HUGO_VERSION ?= 0.111.3 -GITHUB_REF_TYPE ?= branch -GITHUB_REF_NAME ?= $(shell git rev-parse --abbrev-ref HEAD) -ifneq ($(GITHUB_REF_TYPE),branch) - VERSION ?= $(subst v,,$(GITHUB_REF_NAME)) - GITEA_VERSION ?= $(VERSION) +STORED_VERSION=$(shell cat $(STORED_VERSION_FILE) 2>/dev/null) +ifneq ($(STORED_VERSION),) + GITEA_VERSION ?= $(STORED_VERSION) else - ifneq ($(GITHUB_REF_NAME),) - VERSION ?= $(subst release/v,,$(GITHUB_REF_NAME)) - else - VERSION ?= main - endif - - STORED_VERSION=$(shell cat $(STORED_VERSION_FILE) 2>/dev/null) - ifneq ($(STORED_VERSION),) - GITEA_VERSION ?= $(STORED_VERSION) - else - GITEA_VERSION ?= $(shell git describe --tags --always | sed 's/-/+/' | sed 's/^v//') - endif -endif - -# if version = "main" then update version to "nightly" -ifeq ($(VERSION),main) - VERSION := main-nightly + GITEA_VERSION ?= $(shell git describe --tags --always | sed 's/-/+/' | sed 's/^v//') endif +VERSION = ${GITEA_VERSION} LDFLAGS := $(LDFLAGS) -X "main.MakeVersion=$(MAKE_VERSION)" -X "main.Version=$(GITEA_VERSION)" -X "main.Tags=$(TAGS)" @@ -829,9 +812,15 @@ security-check: $(EXECUTABLE): $(GO_SOURCES) $(TAGS_PREREQ) CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) build $(GOFLAGS) $(EXTRA_GOFLAGS) -tags '$(TAGS)' -ldflags '-s -w $(LDFLAGS)' -o $@ +static-executable: $(GO_SOURCES) $(TAGS_PREREQ) + CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) build $(GOFLAGS) $(EXTRA_GOFLAGS) -tags 'netgo osusergo $(TAGS)' -ldflags '-s -w -linkmode external -extldflags "-static" $(LDFLAGS)' -o $(EXECUTABLE) + .PHONY: release release: frontend generate release-windows release-linux release-darwin release-freebsd release-copy release-compress vendor release-sources release-docs release-check +# just the sources, with all assets builtin and frontend resources generated +sources-tarbal: frontend generate vendor release-sources release-check + $(DIST_DIRS): mkdir -p $(DIST_DIRS)