All checks were successful
Forgejo Release Builder / release (push) Successful in 20m37s
Only create mapping zip when the mapping directory exists to avoid zip failures when code shrinking is disabled.
282 lines
10 KiB
YAML
Executable file
282 lines
10 KiB
YAML
Executable file
name: Forgejo Release Builder
|
|
# NOTE: keep Forgejo action refs node20-compatible for runner v3.5.1.
|
|
|
|
on:
|
|
push:
|
|
tags:
|
|
- v*
|
|
|
|
permissions:
|
|
contents: write
|
|
|
|
concurrency:
|
|
group: ${{ github.workflow }}-${{ github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
jobs:
|
|
release:
|
|
runs-on: forgejo-release
|
|
steps:
|
|
- name: Clone repository
|
|
shell: bash
|
|
env:
|
|
FORGEJO_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: |
|
|
set -euo pipefail
|
|
rm -rf .git
|
|
git init .
|
|
git remote add origin "http://copilot:${FORGEJO_TOKEN}@127.0.0.1:3030/${GITHUB_REPOSITORY}.git"
|
|
git fetch --tags --prune --depth=1 origin "${GITHUB_SHA}"
|
|
git checkout --force FETCH_HEAD
|
|
|
|
- name: Set up JDK
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
pkg_install() {
|
|
if [ "$(id -u)" -eq 0 ]; then
|
|
"$@"
|
|
elif command -v sudo >/dev/null 2>&1; then
|
|
sudo "$@"
|
|
else
|
|
echo "Need root or sudo to install packages."
|
|
exit 1
|
|
fi
|
|
}
|
|
if command -v java >/dev/null 2>&1; then
|
|
java -version
|
|
else
|
|
echo "PATH=$PATH"
|
|
echo "pkg managers: dnf=$(command -v dnf || true) apt=$(command -v apt-get || true) apk=$(command -v apk || true) pacman=$(command -v pacman || true)"
|
|
if [ -x /usr/bin/dnf ] || command -v dnf >/dev/null 2>&1; then
|
|
pkg_install dnf install -y java-17-openjdk-devel
|
|
elif [ -x /usr/bin/apt-get ] || command -v apt-get >/dev/null 2>&1; then
|
|
pkg_install apt-get update
|
|
pkg_install apt-get install -y openjdk-17-jdk
|
|
elif [ -x /sbin/apk ] || [ -x /usr/sbin/apk ] || command -v apk >/dev/null 2>&1; then
|
|
pkg_install apk add --no-cache openjdk17
|
|
elif [ -x /usr/bin/pacman ] || command -v pacman >/dev/null 2>&1; then
|
|
pkg_install pacman -Sy --noconfirm jdk17-openjdk
|
|
else
|
|
echo "No supported package manager found for JDK installation."
|
|
exit 1
|
|
fi
|
|
java -version
|
|
fi
|
|
|
|
- name: Prepare release metadata
|
|
id: prepare
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
|
|
version_tag="${GITHUB_REF_NAME:-${GITHUB_REF#refs/tags/}}"
|
|
previous_tag="$(git tag --list 'v*' --sort=-version:refname | grep -Fxv "$version_tag" | head -n 1 || true)"
|
|
|
|
echo "VERSION_TAG=$version_tag" >> "$GITHUB_OUTPUT"
|
|
echo "PREV_TAG_NAME=$previous_tag" >> "$GITHUB_OUTPUT"
|
|
|
|
if [ -n "$previous_tag" ]; then
|
|
commit_logs="$(git log --pretty=format:'- %s (@%an)' "${previous_tag}..HEAD")"
|
|
else
|
|
commit_logs='- Initial release'
|
|
fi
|
|
|
|
{
|
|
echo 'COMMIT_LOGS<<EOF'
|
|
printf '%s\n' "$commit_logs"
|
|
echo 'EOF'
|
|
} >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Set up Gradle
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
if [ -d /opt/android-sdk-linux ]; then
|
|
export ANDROID_HOME=/opt/android-sdk-linux
|
|
export ANDROID_SDK_ROOT=/opt/android-sdk-linux
|
|
echo "ANDROID_HOME=$ANDROID_HOME" >> "$GITHUB_ENV"
|
|
echo "ANDROID_SDK_ROOT=$ANDROID_SDK_ROOT" >> "$GITHUB_ENV"
|
|
printf 'sdk.dir=%s\n' "$ANDROID_HOME" > local.properties
|
|
fi
|
|
chmod +x ./gradlew
|
|
GRADLE_OPTS="-Xmx2g -XX:MaxMetaspaceSize=768m -Dkotlin.daemon.enabled=false -Dkotlin.compiler.execution.strategy=in-process" \
|
|
./gradlew --no-daemon --max-workers=1 --version
|
|
|
|
- name: Check code format
|
|
run: |
|
|
GRADLE_OPTS="-Xmx2g -XX:MaxMetaspaceSize=768m -Dkotlin.daemon.enabled=false -Dkotlin.compiler.execution.strategy=in-process" \
|
|
./gradlew --no-daemon --max-workers=1 spotlessCheck
|
|
|
|
- name: Build app
|
|
run: |
|
|
GRADLE_OPTS="-Xmx2g -XX:MaxMetaspaceSize=768m -Dkotlin.daemon.enabled=false -Dkotlin.compiler.execution.strategy=in-process" \
|
|
./gradlew --no-daemon --max-workers=1 assembleRelease -Penable-updater -Pdisable-code-shrink
|
|
|
|
- name: Run unit tests
|
|
run: |
|
|
GRADLE_OPTS="-Xmx2g -XX:MaxMetaspaceSize=768m -Dkotlin.daemon.enabled=false -Dkotlin.compiler.execution.strategy=in-process" \
|
|
./gradlew --no-daemon --max-workers=1 testReleaseUnitTest
|
|
|
|
- name: Rename release artifacts
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
|
|
version_tag="${{ steps.prepare.outputs.VERSION_TAG }}"
|
|
|
|
mv app/build/outputs/apk/release/app-universal-release-unsigned.apk "Komikku-${version_tag}-unsigned.apk"
|
|
mv app/build/outputs/apk/release/app-arm64-v8a-release-unsigned.apk "Komikku-arm64-v8a-${version_tag}-unsigned.apk"
|
|
mv app/build/outputs/apk/release/app-armeabi-v7a-release-unsigned.apk "Komikku-armeabi-v7a-${version_tag}-unsigned.apk"
|
|
mv app/build/outputs/apk/release/app-x86-release-unsigned.apk "Komikku-x86-${version_tag}-unsigned.apk"
|
|
mv app/build/outputs/apk/release/app-x86_64-release-unsigned.apk "Komikku-x86_64-${version_tag}-unsigned.apk"
|
|
|
|
if [ -d app/build/outputs/mapping/release ]; then
|
|
zip -qr "Komikku-mapping-${version_tag}.zip" app/build/outputs/mapping/release
|
|
fi
|
|
|
|
- name: Create or update release
|
|
id: release
|
|
shell: bash
|
|
env:
|
|
FORGEJO_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
VERSION_TAG: ${{ steps.prepare.outputs.VERSION_TAG }}
|
|
PREV_TAG_NAME: ${{ steps.prepare.outputs.PREV_TAG_NAME }}
|
|
COMMIT_LOGS: ${{ steps.prepare.outputs.COMMIT_LOGS }}
|
|
REPO_URL: ${{ github.server_url }}/${{ github.repository }}
|
|
REPOSITORY_NAME: ${{ github.repository }}
|
|
run: |
|
|
set -euo pipefail
|
|
|
|
api_base="${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}/releases"
|
|
payload_file="$(mktemp)"
|
|
response_file="$(mktemp)"
|
|
|
|
python3 - <<'PY' > "$payload_file"
|
|
import json
|
|
import os
|
|
import textwrap
|
|
|
|
version_tag = os.environ["VERSION_TAG"]
|
|
previous_tag = os.environ.get("PREV_TAG_NAME", "").strip()
|
|
commit_logs = os.environ.get("COMMIT_LOGS", "").strip() or "- Initial release"
|
|
repo_url = os.environ["REPO_URL"]
|
|
repository_name = os.environ["REPOSITORY_NAME"]
|
|
|
|
if previous_tag:
|
|
full_changelog = (
|
|
f"**Full Changelog**: "
|
|
f"[{repository_name}@{previous_tag}...{version_tag}]"
|
|
f"({repo_url}/compare/{previous_tag}...{version_tag})"
|
|
)
|
|
else:
|
|
full_changelog = ""
|
|
|
|
body = textwrap.dedent(
|
|
f"""\
|
|
#### What's Changed
|
|
##### New
|
|
|
|
##### Improve
|
|
|
|
##### Fix
|
|
|
|
{commit_logs}
|
|
|
|
##### Based on
|
|
|
|
{full_changelog}
|
|
|
|
<!-->
|
|
> [!TIP]
|
|
>
|
|
> ### If you are unsure which version to download then go with `Komikku-{version_tag}.apk`
|
|
""",
|
|
)
|
|
|
|
print(
|
|
json.dumps(
|
|
{
|
|
"tag_name": version_tag,
|
|
"name": f"Komikku {version_tag}",
|
|
"body": body,
|
|
"draft": True,
|
|
"prerelease": False,
|
|
},
|
|
),
|
|
)
|
|
PY
|
|
|
|
status="$(curl -sS -o "$response_file" -w '%{http_code}' \
|
|
-H "Authorization: token ${FORGEJO_TOKEN}" \
|
|
"${api_base}/tags/${VERSION_TAG}")"
|
|
|
|
if [ "$status" = "200" ]; then
|
|
release_id="$(python3 -c 'import json, sys; print(json.load(sys.stdin)["id"])' < "$response_file")"
|
|
curl -fsS \
|
|
-X PATCH \
|
|
-H "Authorization: token ${FORGEJO_TOKEN}" \
|
|
-H 'Content-Type: application/json' \
|
|
--data @"$payload_file" \
|
|
"${api_base}/${release_id}" \
|
|
> "$response_file"
|
|
elif [ "$status" = "404" ]; then
|
|
curl -fsS \
|
|
-X POST \
|
|
-H "Authorization: token ${FORGEJO_TOKEN}" \
|
|
-H 'Content-Type: application/json' \
|
|
--data @"$payload_file" \
|
|
"${api_base}" \
|
|
> "$response_file"
|
|
release_id="$(python3 -c 'import json, sys; print(json.load(sys.stdin)["id"])' < "$response_file")"
|
|
else
|
|
cat "$response_file"
|
|
exit 1
|
|
fi
|
|
|
|
echo "RELEASE_ID=$release_id" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Upload release assets
|
|
shell: bash
|
|
env:
|
|
FORGEJO_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
RELEASE_ID: ${{ steps.release.outputs.RELEASE_ID }}
|
|
run: |
|
|
set -euo pipefail
|
|
|
|
release_api="${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}/releases/${RELEASE_ID}"
|
|
assets_file="$(mktemp)"
|
|
|
|
curl -fsS \
|
|
-H "Authorization: token ${FORGEJO_TOKEN}" \
|
|
"${release_api}/assets" \
|
|
> "$assets_file"
|
|
|
|
for file in Komikku-*.apk Komikku-mapping-*.zip; do
|
|
[ -e "$file" ] || continue
|
|
|
|
asset_name="$(basename "$file")"
|
|
asset_id="$(
|
|
python3 -c 'import json, sys; assets = json.load(open(sys.argv[1], encoding="utf-8")); name = sys.argv[2]; print(next((str(asset["id"]) for asset in assets if asset.get("name") == name), ""))' \
|
|
"$assets_file" \
|
|
"$asset_name"
|
|
)"
|
|
|
|
if [ -n "$asset_id" ]; then
|
|
curl -fsS \
|
|
-X DELETE \
|
|
-H "Authorization: token ${FORGEJO_TOKEN}" \
|
|
"${release_api}/assets/${asset_id}" \
|
|
> /dev/null
|
|
fi
|
|
|
|
encoded_name="$(python3 -c 'import sys, urllib.parse; print(urllib.parse.quote(sys.argv[1]))' "$asset_name")"
|
|
|
|
curl -fsS \
|
|
-X POST \
|
|
-H "Authorization: token ${FORGEJO_TOKEN}" \
|
|
-H 'Content-Type: application/octet-stream' \
|
|
--data-binary @"$file" \
|
|
"${release_api}/assets?name=${encoded_name}" \
|
|
> /dev/null
|
|
done
|