Skip to content

Build all cryptad packages + draft upstream release (v2) #56

Build all cryptad packages + draft upstream release (v2)

Build all cryptad packages + draft upstream release (v2) #56

name: Build all cryptad packages + draft upstream release (v2)
on:
workflow_dispatch:
inputs:
version:
description: "Version number (e.g. 1.2.3). If set, checks out release/<version>"
required: false
default: ""
branch:
description: "Branch or tag to build when version is empty"
required: false
default: "main"
permissions:
contents: read
env:
UPSTREAM_REPO: crypta-network/cryptad
jobs:
snap:
name: Snap (amd64/arm64)
uses: ./.github/workflows/build-cryptad-snap.yml
secrets: inherit
with:
version: ${{ inputs.version }}
branch: ${{ inputs.branch }}
flatpak:
name: Flatpak (x86_64/aarch64)
uses: ./.github/workflows/build-cryptad-flatpak.yml
secrets: inherit
with:
version: ${{ inputs.version }}
branch: ${{ inputs.branch }}
linux:
name: Linux packages (deb/rpm)
uses: ./.github/workflows/build-cryptad-linux-packages.yml
secrets: inherit
with:
version: ${{ inputs.version }}
branch: ${{ inputs.branch }}
macos:
name: macOS DMG (arm64)
uses: ./.github/workflows/build-cryptad-macos.yml
secrets: inherit
with:
version: ${{ inputs.version }}
branch: ${{ inputs.branch }}
windows:
name: Windows installers (amd64/arm64)
uses: ./.github/workflows/build-cryptad-windows.yml
secrets: inherit
with:
version: ${{ inputs.version }}
branch: ${{ inputs.branch }}
jar:
name: JAR
uses: ./.github/workflows/build-cryptad-jar.yml
secrets: inherit
with:
version: ${{ inputs.version }}
branch: ${{ inputs.branch }}
release:
name: Draft upstream release
needs: [snap, flatpak, linux, macos, windows, jar]
runs-on: ubuntu-latest
steps:
- name: Checkout release-ops repo
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Resolve release version
id: resolve
shell: bash
env:
INPUT_VERSION: ${{ inputs.version }}
SNAP_VERSION: ${{ needs.snap.outputs.version }}
FLATPAK_VERSION: ${{ needs.flatpak.outputs.version }}
LINUX_VERSION: ${{ needs.linux.outputs.version }}
MACOS_VERSION: ${{ needs.macos.outputs.version }}
WINDOWS_VERSION: ${{ needs.windows.outputs.version }}
JAR_VERSION: ${{ needs.jar.outputs.version }}
run: |
set -euo pipefail
pick_first() {
for v in "$@"; do
if [ -n "$v" ]; then echo "$v"; return 0; fi
done
return 1
}
VERSION=$(pick_first "$INPUT_VERSION" "$SNAP_VERSION" "$FLATPAK_VERSION" "$LINUX_VERSION" "$MACOS_VERSION" "$WINDOWS_VERSION" "$JAR_VERSION" || true)
if [ -z "$VERSION" ]; then
echo "::error::Could not resolve version from inputs or child workflows"
exit 1
fi
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "::notice::Resolved release version: $VERSION (tag v$VERSION)"
- name: Remove existing draft release for this tag (upstream)
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
env:
TAG: v${{ steps.resolve.outputs.version }}
with:
github-token: ${{ secrets.UPSTREAM_REPO_TOKEN }}
script: |
const [owner, repo] = process.env.UPSTREAM_REPO.split('/');
const tag = process.env.TAG;
try {
const rel = await github.rest.repos.getReleaseByTag({ owner, repo, tag });
if (rel && rel.data && rel.data.draft) {
core.notice(`Deleting existing draft release id=${rel.data.id} tag=${rel.data.tag_name}`);
await github.rest.repos.deleteRelease({ owner, repo, release_id: rel.data.id });
} else if (rel && rel.data) {
core.notice(`Release for ${tag} exists and is not draft; leaving intact.`);
}
} catch (e) {
if (e.status === 404) {
core.notice(`No existing release found for tag ${tag}.`);
} else {
throw e;
}
}
- name: Download all artifacts from child builds
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
path: dist
merge-multiple: true
- name: Filter release files (standardized names only)
id: filter
shell: bash
run: |
set -euo pipefail
mkdir -p dist-release
echo "::group::All downloaded artifacts"
find dist -type f -print | sed 's/^/::debug::[artifact] /' || true
echo "::endgroup::"
echo "::group::Selecting standardized files"
# Only include files that match our normalized naming scheme
# cryptad-v<version>-<arch>.(snap|flatpak|deb|rpm|dmg) and CryptaInstaller-v<version>-(amd64|arm64).exe
mapfile -t FILES < <(find dist -type f \( \
-iname 'cryptad-v*-*.snap' -o \
-iname 'cryptad-v*-*.flatpak' -o \
-iname 'cryptad-v*-*.deb' -o \
-iname 'cryptad-v*-*.rpm' -o \
-iname 'cryptad-v*-*.dmg' -o \
-iname 'CryptaInstaller-v*-amd64.exe' -o \
-iname 'CryptaInstaller-v*-arm64.exe' -o \
-iname 'cryptad.jar' \
\) -print)
if [ ${#FILES[@]} -eq 0 ]; then
echo "::error::No release files found in dist/"
exit 1
fi
for f in "${FILES[@]}"; do
cp -f "$f" dist-release/
echo "::debug::Kept $(basename "$f")"
done
echo "::endgroup::"
echo "count=${#FILES[@]}" >> "$GITHUB_OUTPUT"
# Ensure macOS DMG is included and normalized even if child workflow didn't standardize name
VERSION='${{ steps.resolve.outputs.version }}'
TARGET="dist-release/cryptad-v${VERSION}-arm64.dmg"
if [ ! -f "$TARGET" ]; then
# Try to locate any DMG under the downloaded artifacts
SRC=$(find dist -type f -iname '*.dmg' -print | head -n1 || true)
if [ -n "$SRC" ]; then
cp -f "$SRC" "$TARGET"
echo "::debug::Copied $(basename "$SRC") -> $(basename "$TARGET")"
fi
fi
# Remove any extra DMGs that don't match the normalized name
if ls dist-release/*.dmg >/dev/null 2>&1; then
find dist-release -type f -iname '*.dmg' ! -name "$(basename "$TARGET")" -delete
fi
# Ensure the JAR has the canonical filename
if ls dist-release/cryptad.jar >/dev/null 2>&1; then
echo "::debug::JAR present: cryptad.jar"
else
# If a jar exists with any other name under dist, force-copy it as cryptad.jar
JAR_SRC=$(find dist -type f -iname '*.jar' -print | head -n1 || true)
if [ -n "$JAR_SRC" ]; then
cp -f "$JAR_SRC" dist-release/cryptad.jar
echo "::debug::Copied $(basename "$JAR_SRC") -> cryptad.jar"
fi
fi
- name: Generate SHA256 checksums (and upsert body section)
id: checksums
shell: bash
env:
GH_TOKEN: ${{ secrets.UPSTREAM_REPO_TOKEN }}
UPSTREAM_REPO: ${{ env.UPSTREAM_REPO }}
VERSION: ${{ steps.resolve.outputs.version }}
run: |
set -euo pipefail
# Use GitHub-provided workspace path; requires actions/checkout earlier in this job
REPO_ROOT="${GITHUB_WORKSPACE}"
echo "::group::Compute SHA256 over dist-release/**"
cd dist-release
# Create sorted, portable checksums file
find . -type f -print0 | sort -z | xargs -0 shasum -a 256 > SHA256SUMS.txt
echo "::debug::$(wc -l < SHA256SUMS.txt) checksum entries"
echo "::endgroup::"
# Compose the checksums section as a standalone fragment
{
echo "## SHA256 Checksums"
echo
echo '```text'
cat SHA256SUMS.txt
echo '```'
} > RELEASE_BODY_CHECKSUMS.md
# Try to fetch existing release body for tag v$VERSION (if it exists)
# We deliberately do not fail if it can't be fetched.
EXISTING_BODY_FILE=EXISTING_BODY.md
EXISTING_BODY=""
if [ -n "${VERSION:-}" ] && [ -n "${UPSTREAM_REPO:-}" ]; then
echo "::group::Fetch existing release body (if any)"
if gh release view "v${VERSION}" --repo "${UPSTREAM_REPO}" --json body --jq '.body' > "$EXISTING_BODY_FILE" 2>/dev/null; then
echo "::debug::Fetched existing release body for v${VERSION}"
EXISTING_BODY=$(cat "$EXISTING_BODY_FILE")
else
echo "::notice::No existing release body retrieved for v${VERSION}; will merge checksums into fresh body"
: > "$EXISTING_BODY_FILE"
fi
echo "::endgroup::"
else
: > "$EXISTING_BODY_FILE"
fi
# Upsert/replace the "## SHA256 Checksums" section within the existing body
# - If section exists, replace its content with our new fragment
# - If not, append the section to the end (preserving existing body)
NEW_SECTION_FILE=RELEASE_BODY_CHECKSUMS.md
MERGED_FILE=RELEASE_BODY.md
python3 "$REPO_ROOT/.github/scripts/upsert_sha256_section.py" \
"$EXISTING_BODY_FILE" \
"$NEW_SECTION_FILE" \
"$MERGED_FILE"
- name: Create draft release in upstream repo
uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0
if: ${{ steps.resolve.outputs.version != '' }}
with:
token: ${{ secrets.UPSTREAM_REPO_TOKEN }}
repository: ${{ env.UPSTREAM_REPO }}
draft: true
tag_name: v${{ steps.resolve.outputs.version }}
name: Crypta v${{ steps.resolve.outputs.version }}
generate_release_notes: true
body_path: dist-release/RELEASE_BODY.md
files: |
dist-release/*.snap
dist-release/*.flatpak
dist-release/*.deb
dist-release/*.rpm
dist-release/*.dmg
dist-release/CryptaInstaller-*.exe
dist-release/cryptad.jar
dist-release/SHA256SUMS.txt