314 lines
11 KiB
YAML
314 lines
11 KiB
YAML
name: release
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
inputs:
|
|
tag_name:
|
|
description: Release tag (for example v0.1.0)
|
|
required: true
|
|
release_name:
|
|
description: Optional release title
|
|
required: false
|
|
release_notes:
|
|
description: Release notes / body
|
|
required: false
|
|
|
|
jobs:
|
|
create-release:
|
|
name: Create release
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
release_id: ${{ steps.release.outputs.release_id }}
|
|
release_name: ${{ steps.release.outputs.release_name }}
|
|
steps:
|
|
- name: Create or reuse Gitea release
|
|
id: release
|
|
env:
|
|
GITEA_TOKEN: ${{ github.token }}
|
|
GITEA_API: ${{ github.server_url }}/api/v1
|
|
REPO: ${{ github.repository }}
|
|
TAG_NAME: ${{ inputs.tag_name }}
|
|
INPUT_RELEASE_NAME: ${{ inputs.release_name }}
|
|
RELEASE_NOTES: ${{ inputs.release_notes }}
|
|
TARGET_COMMITISH: ${{ github.sha }}
|
|
run: |
|
|
set -euo pipefail
|
|
|
|
if [ -n "${INPUT_RELEASE_NAME}" ]; then
|
|
RELEASE_NAME="${INPUT_RELEASE_NAME}"
|
|
else
|
|
RELEASE_NAME="Release ${TAG_NAME}"
|
|
fi
|
|
export RELEASE_NAME
|
|
|
|
get_release_url="${GITEA_API}/repos/${REPO}/releases/tags/${TAG_NAME}"
|
|
create_release_url="${GITEA_API}/repos/${REPO}/releases"
|
|
|
|
status="$(curl -sS -o /tmp/release.json -w '%{http_code}' \
|
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
|
"${get_release_url}")"
|
|
|
|
if [ "${status}" = "200" ]; then
|
|
python3 - <<'PY' >> "$GITHUB_OUTPUT"
|
|
import json
|
|
with open('/tmp/release.json', 'r', encoding='utf-8') as f:
|
|
data = json.load(f)
|
|
print(f"release_id={data['id']}")
|
|
print(f"release_name={data['name']}")
|
|
PY
|
|
exit 0
|
|
fi
|
|
|
|
if [ "${status}" != "404" ]; then
|
|
echo "Unexpected response while checking release: HTTP ${status}"
|
|
cat /tmp/release.json
|
|
exit 1
|
|
fi
|
|
|
|
python3 - <<'PY' > /tmp/release-payload.json
|
|
import json, os
|
|
payload = {
|
|
"tag_name": os.environ["TAG_NAME"],
|
|
"target_commitish": os.environ["TARGET_COMMITISH"],
|
|
"name": os.environ["RELEASE_NAME"],
|
|
"body": os.environ.get("RELEASE_NOTES", ""),
|
|
"draft": False,
|
|
"prerelease": False,
|
|
}
|
|
print(json.dumps(payload))
|
|
PY
|
|
|
|
curl -sS \
|
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
|
-H "Content-Type: application/json" \
|
|
-X POST \
|
|
--data @/tmp/release-payload.json \
|
|
"${create_release_url}" \
|
|
-o /tmp/release.json
|
|
|
|
python3 - <<'PY' >> "$GITHUB_OUTPUT"
|
|
import json
|
|
with open('/tmp/release.json', 'r', encoding='utf-8') as f:
|
|
data = json.load(f)
|
|
if 'id' not in data:
|
|
raise SystemExit(json.dumps(data, indent=2))
|
|
print(f"release_id={data['id']}")
|
|
print(f"release_name={data['name']}")
|
|
PY
|
|
|
|
build-release:
|
|
name: ${{ matrix.toolchain.name }}
|
|
needs: create-release
|
|
runs-on: ubuntu-latest
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
toolchain:
|
|
- name: x86_64 Linux
|
|
host: x86_64-linux-gnu
|
|
packages: gperf cmake python3-zmq libdbus-1-dev libharfbuzz-dev
|
|
- name: Win64
|
|
host: x86_64-w64-mingw32
|
|
packages: cmake python3 g++-mingw-w64-x86-64
|
|
- name: ARM v8
|
|
host: aarch64-linux-gnu
|
|
packages: python3 gperf g++-aarch64-linux-gnu
|
|
- name: Cross-Mac aarch64
|
|
host: aarch64-apple-darwin
|
|
packages: cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python3-dev python3-setuptools-git
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: https://github.com/actions/checkout@v4
|
|
with:
|
|
fetch-depth: 1
|
|
fetch-tags: true
|
|
submodules: false
|
|
|
|
- name: Prepare cache keys
|
|
run: |
|
|
git submodule status --cached --recursive > .ci-submodules.lock
|
|
DEPENDS_KEY="$(cat contrib/depends/Makefile contrib/depends/funcs.mk contrib/depends/hosts/*.mk contrib/depends/packages/*.mk contrib/depends/toolchain.cmake.in | sha256sum | cut -d' ' -f1)"
|
|
echo "EXTERNAL_CACHE_KEY=v2-$(sha256sum .ci-submodules.lock | cut -d' ' -f1)" >> "$GITHUB_ENV"
|
|
echo "DEPENDS_CACHE_KEY=${DEPENDS_KEY}" >> "$GITHUB_ENV"
|
|
|
|
- name: Restore external cache
|
|
run: |
|
|
CACHE_ROOT="${RUNNER_TOOL_CACHE:-/tmp}/peya-ci"
|
|
EXTERNAL_ARCHIVE="${CACHE_ROOT}/external-${EXTERNAL_CACHE_KEY}.tar.zst"
|
|
if [ -f "${EXTERNAL_ARCHIVE}" ]; then
|
|
echo "Restoring external cache from ${EXTERNAL_ARCHIVE}"
|
|
rm -rf external .git/modules/external
|
|
mkdir -p external .git/modules
|
|
tar --zstd -xf "${EXTERNAL_ARCHIVE}"
|
|
if [ -d ".git/modules/external" ]; then
|
|
echo "EXTERNAL_CACHE_HIT=true" >> "$GITHUB_ENV"
|
|
else
|
|
echo "External cache is missing .git/modules/external, ignoring it"
|
|
rm -rf external .git/modules/external
|
|
echo "EXTERNAL_CACHE_HIT=false" >> "$GITHUB_ENV"
|
|
fi
|
|
else
|
|
echo "No external cache found"
|
|
echo "EXTERNAL_CACHE_HIT=false" >> "$GITHUB_ENV"
|
|
fi
|
|
|
|
- name: Sync submodules
|
|
run: |
|
|
git submodule sync --recursive
|
|
git submodule update --init --recursive --depth 1 --jobs "$(nproc)"
|
|
|
|
- name: Install dependencies
|
|
run: |
|
|
sudo apt-get update
|
|
sudo apt-get install -y \
|
|
automake \
|
|
autotools-dev \
|
|
build-essential \
|
|
ca-certificates \
|
|
ccache \
|
|
clang \
|
|
cmake \
|
|
curl \
|
|
git \
|
|
libssl-dev \
|
|
libtool \
|
|
pkg-config \
|
|
zip \
|
|
${{ matrix.toolchain.packages }}
|
|
|
|
- name: Restore depends cache
|
|
run: |
|
|
CACHE_ROOT="${RUNNER_TOOL_CACHE:-/tmp}/peya-ci"
|
|
DEPENDS_ARCHIVE="${CACHE_ROOT}/depends-${{ matrix.toolchain.host }}-${DEPENDS_CACHE_KEY}.tar.zst"
|
|
if [ -f "${DEPENDS_ARCHIVE}" ]; then
|
|
echo "Restoring depends cache from ${DEPENDS_ARCHIVE}"
|
|
tar --zstd -xf "${DEPENDS_ARCHIVE}"
|
|
else
|
|
echo "No depends cache found"
|
|
fi
|
|
|
|
- name: Prepare MinGW alternatives
|
|
if: ${{ matrix.toolchain.host == 'x86_64-w64-mingw32' }}
|
|
run: |
|
|
sudo update-alternatives --set ${{ matrix.toolchain.host }}-g++ "$(which ${{ matrix.toolchain.host }}-g++-posix)"
|
|
sudo update-alternatives --set ${{ matrix.toolchain.host }}-gcc "$(which ${{ matrix.toolchain.host }}-gcc-posix)"
|
|
|
|
- name: Build
|
|
run: |
|
|
make depends target=${{ matrix.toolchain.host }} -j"$(nproc)"
|
|
|
|
- name: Save external cache
|
|
if: success()
|
|
run: |
|
|
CACHE_ROOT="${RUNNER_TOOL_CACHE:-/tmp}/peya-ci"
|
|
EXTERNAL_ARCHIVE="${CACHE_ROOT}/external-${EXTERNAL_CACHE_KEY}.tar.zst"
|
|
mkdir -p "${CACHE_ROOT}"
|
|
if [ ! -f "${EXTERNAL_ARCHIVE}" ]; then
|
|
tar --zstd -cf "${EXTERNAL_ARCHIVE}" external .git/modules/external
|
|
fi
|
|
|
|
- name: Save depends cache
|
|
if: success()
|
|
run: |
|
|
CACHE_ROOT="${RUNNER_TOOL_CACHE:-/tmp}/peya-ci"
|
|
DEPENDS_ARCHIVE="${CACHE_ROOT}/depends-${{ matrix.toolchain.host }}-${DEPENDS_CACHE_KEY}.tar.zst"
|
|
mkdir -p "${CACHE_ROOT}"
|
|
if [ ! -f "${DEPENDS_ARCHIVE}" ]; then
|
|
tar --zstd -cf "${DEPENDS_ARCHIVE}" \
|
|
contrib/depends/built \
|
|
contrib/depends/sources \
|
|
contrib/depends/work/build \
|
|
contrib/depends/${{ matrix.toolchain.host }}
|
|
fi
|
|
|
|
- name: Package release archive
|
|
run: |
|
|
REF_NAME="${{ inputs.tag_name }}"
|
|
if [ "${{ matrix.toolchain.host }}" = "x86_64-w64-mingw32" ]; then
|
|
ARCHIVE="/tmp/peya-${REF_NAME}-${{ matrix.toolchain.host }}.zip"
|
|
else
|
|
ARCHIVE="/tmp/peya-${REF_NAME}-${{ matrix.toolchain.host }}.tar.gz"
|
|
fi
|
|
|
|
cd "build/${{ matrix.toolchain.host }}/release/bin"
|
|
FILES=()
|
|
|
|
for pattern in peyad* peya-wallet-cli* peya-wallet-rpc* peya-gen-multisig*; do
|
|
for file in $pattern; do
|
|
if [ -e "$file" ]; then
|
|
FILES+=("$file")
|
|
fi
|
|
done
|
|
done
|
|
|
|
if [ "${#FILES[@]}" -eq 0 ]; then
|
|
echo "No release binaries found in $(pwd)"
|
|
exit 1
|
|
fi
|
|
|
|
if [ "${ARCHIVE##*.}" = "zip" ]; then
|
|
zip -ur "${ARCHIVE}" "${FILES[@]}"
|
|
else
|
|
tar -czf "${ARCHIVE}" "${FILES[@]}"
|
|
fi
|
|
ls -lh "${ARCHIVE}"
|
|
|
|
- name: Upload workflow artifact
|
|
uses: https://github.com/actions/upload-artifact@v3
|
|
with:
|
|
name: peya-${{ matrix.toolchain.host }}
|
|
path: |
|
|
/tmp/peya-*-${{ matrix.toolchain.host }}.zip
|
|
/tmp/peya-*-${{ matrix.toolchain.host }}.tar.gz
|
|
if-no-files-found: error
|
|
|
|
- name: Upload release asset
|
|
env:
|
|
GITEA_TOKEN: ${{ github.token }}
|
|
GITEA_API: ${{ github.server_url }}/api/v1
|
|
REPO: ${{ github.repository }}
|
|
RELEASE_ID: ${{ needs.create-release.outputs.release_id }}
|
|
run: |
|
|
set -euo pipefail
|
|
|
|
asset="$(find /tmp -maxdepth 1 \( -name 'peya-*-${{ matrix.toolchain.host }}.zip' -o -name 'peya-*-${{ matrix.toolchain.host }}.tar.gz' \) | head -n 1)"
|
|
if [ -z "${asset}" ]; then
|
|
echo "No packaged release asset found for ${{ matrix.toolchain.host }}"
|
|
exit 1
|
|
fi
|
|
asset_name="$(basename "${asset}")"
|
|
assets_url="${GITEA_API}/repos/${REPO}/releases/${RELEASE_ID}/assets"
|
|
|
|
curl -sS \
|
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
|
"${assets_url}" \
|
|
-o /tmp/release-assets.json
|
|
|
|
existing_id="$(ASSET_NAME="${asset_name}" python3 - <<'PY'
|
|
import json, os
|
|
name = os.environ["ASSET_NAME"]
|
|
with open('/tmp/release-assets.json', 'r', encoding='utf-8') as f:
|
|
assets = json.load(f)
|
|
for asset in assets:
|
|
if asset.get('name') == name:
|
|
print(asset['id'])
|
|
break
|
|
PY
|
|
)"
|
|
|
|
if [ -n "${existing_id}" ]; then
|
|
curl -sS \
|
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
|
-X DELETE \
|
|
"${assets_url}/${existing_id}" \
|
|
>/dev/null
|
|
fi
|
|
|
|
curl -sS \
|
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
|
-X POST \
|
|
-F "attachment=@${asset}" \
|
|
"${assets_url}?name=${asset_name}" \
|
|
>/dev/null
|