Skip to content

Commit 206d0b3

Browse files
committed
[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 (go-gitea#25319) (go-gitea#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)
1 parent 8a246d2 commit 206d0b3

File tree

8 files changed

+565
-46
lines changed

8 files changed

+565
-46
lines changed
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
name: 'Build release'
2+
author: 'Forgejo authors'
3+
description: |
4+
Build release
5+
6+
inputs:
7+
forgejo:
8+
description: 'URL of the Forgejo instance where the release is uploaded'
9+
required: true
10+
owner:
11+
description: 'User or organization where the release is uploaded, relative to the Forgejo instance'
12+
required: true
13+
repository:
14+
description: 'Repository where the release is uploaded, relative to the owner'
15+
required: true
16+
doer:
17+
description: 'Name of the user authoring the release'
18+
required: true
19+
tag-version:
20+
description: 'Version of the release derived from the tag withint the leading v'
21+
required: true
22+
suffix:
23+
description: 'Suffix to add to the image tag'
24+
token:
25+
description: 'token'
26+
required: true
27+
dockerfile:
28+
description: 'path to the dockerfile'
29+
default: 'Dockerfile'
30+
platforms:
31+
description: 'Coma separated list of platforms'
32+
default: 'linux/amd64,linux/arm64'
33+
release-notes:
34+
description: 'Full text of the release notes'
35+
default: 'Release notes placeholder'
36+
binary-name:
37+
description: 'Name of the binary'
38+
binary-path:
39+
description: 'Path of the binary within the container to extract into binary-name'
40+
verbose:
41+
description: 'Increase the verbosity level'
42+
default: 'false'
43+
44+
runs:
45+
using: "composite"
46+
steps:
47+
- run: echo "${{ github.action_path }}" >> $GITHUB_PATH
48+
shell: bash
49+
50+
- name: Install dependencies
51+
run: |
52+
apt-get install -y -qq xz-utils
53+
54+
- name: set -x if verbose is required
55+
id: verbose
56+
run: |
57+
if ${{ inputs.verbose }} ; then
58+
echo "shell=set -x" >> "$GITHUB_OUTPUT"
59+
fi
60+
61+
- name: Create the insecure and buildx-config variables for the container registry
62+
id: registry
63+
run: |
64+
${{ steps.verbose.outputs.shell }}
65+
url="${{ inputs.forgejo }}"
66+
hostport=${url##http*://}
67+
hostport=${hostport%%/}
68+
echo "host-port=${hostport}" >> "$GITHUB_OUTPUT"
69+
if ! [[ $url =~ ^http:// ]] ; then
70+
exit 0
71+
fi
72+
cat >> "$GITHUB_OUTPUT" <<EOF
73+
insecure=true
74+
buildx-config<<ENDVAR
75+
[registry."${hostport}"]
76+
http = true
77+
ENDVAR
78+
EOF
79+
80+
- name: Allow docker pull/push to forgejo
81+
if: ${{ steps.registry.outputs.insecure }}
82+
run: |-
83+
mkdir -p /etc/docker
84+
cat > /etc/docker/daemon.json <<EOF
85+
{
86+
"insecure-registries" : ["${{ steps.registry.outputs.host-port }}"],
87+
"bip": "172.26.0.1/16"
88+
}
89+
EOF
90+
91+
- name: Install docker
92+
run: |
93+
echo deb http://deb.debian.org/debian bullseye-backports main | tee /etc/apt/sources.list.d/backports.list && apt-get -qq update
94+
DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -qq -y -t bullseye-backports docker.io
95+
96+
- uses: https://github.com/docker/setup-buildx-action@v2
97+
with:
98+
config-inline: |
99+
${{ steps.registry.outputs.buildx-config }}
100+
101+
- name: Login to the container registry
102+
run: |
103+
BASE64_AUTH=`echo -n "${{ inputs.doer }}:${{ inputs.token }}" | base64 -w0`
104+
mkdir -p ~/.docker
105+
echo "{\"auths\": {\"$CI_REGISTRY\": {\"auth\": \"$BASE64_AUTH\"}}}" > ~/.docker/config.json
106+
env:
107+
CI_REGISTRY: "${{ steps.registry.outputs.host-port }}"
108+
109+
- name: Build the container image for each architecture
110+
uses: https://github.com/docker/build-push-action@v4
111+
# workaround until https://github.com/docker/build-push-action/commit/d8823bfaed2a82c6f5d4799a2f8e86173c461aba is in @v4 or @v5 is released
112+
env:
113+
ACTIONS_RUNTIME_TOKEN: ''
114+
with:
115+
context: .
116+
push: true
117+
file: ${{ inputs.dockerfile }}
118+
platforms: ${{ inputs.platforms }}
119+
tags: ${{ steps.registry.outputs.host-port }}/${{ inputs.owner }}/${{ inputs.repository }}:${{ inputs.tag-version }}${{ inputs.suffix }}
120+
121+
- name: Extract the binary from the container images into the release directory
122+
if: inputs.binary-name != ''
123+
run: |
124+
${{ steps.verbose.outputs.shell }}
125+
mkdir -p release
126+
cd release
127+
for platform in $(echo ${{ inputs.platforms }} | tr ',' ' '); do
128+
arch=$(echo $platform | sed -e 's|linux/||g' -e 's|arm/v6|arm-6|g')
129+
docker create --platform $platform --name forgejo-$arch ${{ steps.registry.outputs.host-port }}/${{ inputs.owner }}/${{ inputs.repository }}:${{ inputs.tag-version }}${{ inputs.suffix }}
130+
binary="${{ inputs.binary-name }}-${{ inputs.tag-version }}-linux"
131+
docker cp forgejo-$arch:${{ inputs.binary-path }} $binary-$arch
132+
chmod +x $binary-$arch
133+
# the displayed version is converted with - sometime changed into +, deal with it
134+
pattern=$(echo "${{ inputs.tag-version }}" | tr - .)
135+
if ! ./$binary-$arch --version | grep "$pattern" ; then
136+
echo "ERROR: expected version pattern $pattern not found in the output of $binary-$arch --version"
137+
./$binary-$arch --version
138+
exit 1
139+
fi
140+
xz --keep -9 $binary-$arch
141+
shasum -a 256 $binary-$arch > $binary-$arch.sha256
142+
shasum -a 256 $binary-$arch.xz > $binary-$arch.xz.sha256
143+
docker rm forgejo-$arch
144+
done
145+
146+
- name: publish release
147+
if: inputs.binary-name != ''
148+
uses: https://code.forgejo.org/actions/forgejo-release@v1
149+
with:
150+
direction: upload
151+
release-dir: release
152+
release-notes: "${{ inputs.release-notes }}"
153+
token: ${{ inputs.token }}
154+
verbose: ${{ steps.verbose.outputs.value }}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
name: 'Publish release'
2+
author: 'Forgejo authors'
3+
description: |
4+
Publish release
5+
6+
inputs:
7+
forgejo:
8+
description: 'URL of the Forgejo instance where the release is uploaded'
9+
required: true
10+
from-owner:
11+
description: 'the owner from which a release is to be copied'
12+
required: true
13+
to-owner:
14+
description: 'the owner to which a release is to be copied'
15+
required: true
16+
repo:
17+
description: 'the repository from which a release is to be copied relative to from-owner and to-owner'
18+
default: 'forgejo'
19+
ref-name:
20+
description: 'ref_name of the tag of the release to be copied'
21+
required: true
22+
doer:
23+
description: 'Name of the user authoring the release'
24+
required: true
25+
token:
26+
description: 'application token on FORGEJO with permission to the repository and the packages'
27+
required: true
28+
gpg-private-key:
29+
description: 'GPG Private Key to sign the release artifacts'
30+
gpg-passphrase:
31+
description: 'Passphrase of the GPG Private Key'
32+
33+
runs:
34+
using: "composite"
35+
steps:
36+
- id: hostport
37+
run: |
38+
url="${{ inputs.forgejo }}"
39+
hostport=${url##http*://}
40+
hostport=${hostport%%/}
41+
echo "value=$hostport" >> "$GITHUB_OUTPUT"
42+
43+
- id: tag-version
44+
run: |
45+
version="${{ inputs.ref-name }}"
46+
version=${version##*v}
47+
echo "value=$version" >> "$GITHUB_OUTPUT"
48+
49+
- name: apt-get install docker.io
50+
run: |
51+
DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -qq -y docker.io
52+
53+
- name: download release
54+
uses: https://code.forgejo.org/actions/forgejo-release@v1
55+
with:
56+
url: ${{ inputs.forgejo }}
57+
repo: ${{ inputs.from-owner }}/${{ inputs.repo }}
58+
direction: download
59+
release-dir: release
60+
download-retry: 60
61+
token: ${{ inputs.token }}
62+
63+
- name: upload release
64+
uses: https://code.forgejo.org/actions/forgejo-release@v1
65+
with:
66+
url: ${{ inputs.forgejo }}
67+
repo: ${{ inputs.to-owner }}/${{ inputs.repo }}
68+
direction: upload
69+
release-dir: release
70+
release-notes: "See https://codeberg.org/forgejo/forgejo/src/branch/forgejo/RELEASE-NOTES.md#${{ steps.tag-version.outputs.value }}"
71+
token: ${{ inputs.token }}
72+
gpg-private-key: ${{ inputs.gpg-private-key }}
73+
gpg-passphrase: ${{ inputs.gpg-passphrase }}
74+
75+
- name: login to the registry
76+
uses: https://github.com/docker/login-action@v2
77+
with:
78+
registry: ${{ steps.hostport.outputs.value }}
79+
username: ${{ inputs.doer }}
80+
password: ${{ inputs.token }}
81+
82+
- uses: https://code.forgejo.org/forgejo/forgejo-container-image@v1
83+
env:
84+
VERIFY: 'false'
85+
with:
86+
url: https://${{ steps.hostport.outputs.value }}
87+
destination-owner: ${{ inputs.to-owner }}
88+
owner: ${{ inputs.from-owner }}
89+
suffixes: '-rootless'
90+
project: ${{ inputs.repo }}
91+
tag: ${{ steps.tag-version.outputs.value }}
92+
doer: ${{ inputs.doer }}
93+
token: ${{ inputs.token }}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
name: Integration tests for the release process
2+
3+
on:
4+
push:
5+
paths:
6+
- Makefile
7+
- Dockerfile
8+
- Dockerfile.rootless
9+
- docker/**
10+
- .forgejo/actions/build-release/action.yml
11+
- .forgejo/workflows/build-release.yml
12+
- .forgejo/workflows/build-release-integration.yml
13+
14+
jobs:
15+
release-simulation:
16+
runs-on: self-hosted
17+
if: secrets.ROLE != 'forgejo-integration' && secrets.ROLE != 'forgejo-experimental' && secrets.ROLE != 'forgejo-release'
18+
steps:
19+
- uses: actions/checkout@v3
20+
21+
- id: forgejo
22+
uses: https://code.forgejo.org/actions/setup-forgejo@v1
23+
with:
24+
user: root
25+
password: admin1234
26+
image-version: 1.19
27+
lxc-ip-prefix: 10.0.9
28+
29+
- name: publish the forgejo release
30+
run: |
31+
set -x
32+
33+
version=1.2.3
34+
cat > /etc/docker/daemon.json <<EOF
35+
{
36+
"insecure-registries" : ["${{ steps.forgejo.outputs.host-port }}"]
37+
}
38+
EOF
39+
systemctl restart docker
40+
41+
apt-get install -qq -y xz-utils
42+
43+
dir=$(mktemp -d)
44+
trap "rm -fr $dir" EXIT
45+
46+
url=http://root:admin1234@${{ steps.forgejo.outputs.host-port }}
47+
export FORGEJO_RUNNER_LOGS="${{ steps.forgejo.outputs.runner-logs }}"
48+
49+
#
50+
# Create a new project with a fake forgejo and the release workflow only
51+
#
52+
mkdir -p $dir/.forgejo/workflows
53+
cp .forgejo/workflows/build-release.yml $dir/.forgejo/workflows
54+
cp -a .forgejo/actions $dir/.forgejo/actions
55+
cat > $dir/Dockerfile <<EOF
56+
FROM docker.io/library/alpine:3.18
57+
RUN mkdir -p /app/gitea
58+
RUN ( echo '#!/bin/sh' ; echo "echo forgejo v$version" ) > /app/gitea/gitea ; chmod +x /app/gitea/gitea
59+
EOF
60+
cp $dir/Dockerfile $dir/Dockerfile.rootless
61+
sources=forgejo-src-$version.tar.gz
62+
( echo 'sources-tarbal:' ; echo -e '\tmkdir -p dist/release ; cd dist/release ; sources=forgejo-src-$(VERSION).tar.gz ; echo sources > $$sources ; shasum -a 256 $$sources > $$sources.sha256' ) > $dir/Makefile
63+
64+
forgejo-test-helper.sh push $dir $url root forgejo |& tee $dir/pushed
65+
eval $(grep '^sha=' < $dir/pushed)
66+
67+
#
68+
# Push a tag to trigger the release workflow and wait for it to complete
69+
#
70+
forgejo-test-helper.sh api POST $url repos/root/forgejo/tags ${{ steps.forgejo.outputs.token }} --data-raw '{"tag_name": "v'$version'", "target": "'$sha'"}'
71+
LOOPS=180 forgejo-test-helper.sh wait_success "$url" root/forgejo $sha
72+
73+
#
74+
# uncomment to see the logs even when everything is reported to be working ok
75+
#
76+
#cat $FORGEJO_RUNNER_LOGS
77+
78+
#
79+
# Minimal sanity checks. e2e test is for the setup-forgejo
80+
# action and the infrastructure playbook. Since the binary
81+
# is a script shell it does not test the sanity of the cross
82+
# build, only the sanity of the naming of the binaries.
83+
#
84+
for arch in amd64 arm64 arm-6 ; do
85+
binary=forgejo-$version-linux-$arch
86+
for suffix in '' '.xz' ; do
87+
curl --fail -L -sS $url/root/forgejo/releases/download/v$version/$binary$suffix > $binary$suffix
88+
if test "$suffix" = .xz ; then
89+
unxz --keep $binary$suffix
90+
fi
91+
chmod +x $binary
92+
./$binary --version | grep $version
93+
curl --fail -L -sS $url/root/forgejo/releases/download/v$version/$binary$suffix.sha256 > $binary$suffix.sha256
94+
shasum -a 256 --check $binary$suffix.sha256
95+
rm $binary$suffix
96+
done
97+
done
98+
99+
curl --fail -L -sS $url/root/forgejo/releases/download/v$version/$sources > $sources
100+
curl --fail -L -sS $url/root/forgejo/releases/download/v$version/$sources.sha256 > $sources.sha256
101+
shasum -a 256 --check $sources.sha256
102+
103+
docker pull ${{ steps.forgejo.outputs.host-port }}/root/forgejo:$version
104+
docker pull ${{ steps.forgejo.outputs.host-port }}/root/forgejo:$version-rootless

0 commit comments

Comments
 (0)