mirror of
https://github.com/Lissy93/dashy.git
synced 2026-06-06 00:34:30 -04:00
👷 Smoother releases, with built app and checksum
This commit is contained in:
87
.github/workflows/build-release-assets.yml
vendored
87
.github/workflows/build-release-assets.yml
vendored
@@ -1,87 +0,0 @@
|
||||
name: 📦 Build & Upload Release Assets
|
||||
|
||||
# Builds Dashy and uploads a pre-built tarball to the GitHub release.
|
||||
# This allows non-Docker installs (e.g. Proxmox VE community scripts) to
|
||||
# download a ready-to-run package without having to build from source.
|
||||
#
|
||||
# The tarball contains the compiled frontend (dist/) plus all server-side
|
||||
# files. Users extract it and run `yarn install --production` + `node server`.
|
||||
#
|
||||
# Triggered whenever a new release is created, or when manually dispatched
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [created]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: 'Tag to build assets for (must already exist as a release)'
|
||||
required: true
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.release.tag_name || github.event.inputs.tag }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build-release-assets:
|
||||
name: Build app & upload tarball
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
TAG: ${{ github.event.release.tag_name || github.event.inputs.tag }}
|
||||
|
||||
steps:
|
||||
- name: Checkout code 🛎️
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: refs/tags/${{ env.TAG }}
|
||||
|
||||
- name: Setup Node.js ⚙️
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
cache: 'yarn'
|
||||
|
||||
- name: Install dependencies 📥
|
||||
run: yarn install --frozen-lockfile --ignore-engines --network-timeout 300000
|
||||
|
||||
- name: Build app 🏗️
|
||||
run: NODE_OPTIONS=--openssl-legacy-provider yarn build --mode production
|
||||
|
||||
- name: Package release artifact 📦
|
||||
run: |
|
||||
STAGING="dashy-release-staging"
|
||||
mkdir -p "$STAGING"
|
||||
|
||||
# Runtime files
|
||||
cp -r dist "$STAGING/"
|
||||
cp -r services "$STAGING/"
|
||||
cp -r public "$STAGING/"
|
||||
cp -r user-data "$STAGING/"
|
||||
cp server.js "$STAGING/"
|
||||
cp yarn.lock "$STAGING/"
|
||||
|
||||
# src/utils/ files referenced directly by the server at runtime
|
||||
mkdir -p "$STAGING/src/utils/config"
|
||||
cp src/utils/config/ConfigSchema.json "$STAGING/src/utils/config/"
|
||||
|
||||
# Strip devDependencies so `yarn install --production` stays lean
|
||||
node -e "
|
||||
const pkg = JSON.parse(require('fs').readFileSync('package.json', 'utf8'));
|
||||
delete pkg.devDependencies;
|
||||
require('fs').writeFileSync('$STAGING/package.json', JSON.stringify(pkg, null, 2));
|
||||
"
|
||||
|
||||
TARBALL="dashy-${TAG}.tar.gz"
|
||||
tar -czf "${TARBALL}" -C "${STAGING}" .
|
||||
echo "TARBALL=${TARBALL}" >> "$GITHUB_ENV"
|
||||
echo "Size: $(du -sh ${TARBALL} | cut -f1)"
|
||||
|
||||
- name: Upload tarball to GitHub Release 🚀
|
||||
uses: softprops/action-gh-release@v3
|
||||
with:
|
||||
tag_name: ${{ env.TAG }}
|
||||
files: ${{ env.TARBALL }}
|
||||
token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
103
.github/workflows/draft-release.yml
vendored
103
.github/workflows/draft-release.yml
vendored
@@ -1,103 +0,0 @@
|
||||
name: 🏗️ Draft New Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '*.*.*'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: 'Tag to draft a release for (must already exist)'
|
||||
required: true
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
create-draft-release:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
TAG: ${{ github.event.inputs.tag || github.ref_name }}
|
||||
steps:
|
||||
- name: Checkout code 🛎️
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Check if major or minor version changed 🔍
|
||||
id: version_check
|
||||
env:
|
||||
CURRENT_TAG: ${{ github.event.inputs.tag || github.ref_name }}
|
||||
run: |
|
||||
git fetch --tags --force
|
||||
CURRENT_MM=$(echo "$CURRENT_TAG" | sed 's/^v//; s/\([0-9]*\.[0-9]*\)\..*/\1/')
|
||||
|
||||
# Find the immediately previous tag (to detect patch-only bumps)
|
||||
PREVIOUS_TAG=$(git tag --sort=-version:refname \
|
||||
| grep -v "^${CURRENT_TAG}$" | head -1)
|
||||
|
||||
if [ -z "$PREVIOUS_TAG" ]; then
|
||||
echo "No previous tag found, creating release"
|
||||
echo "should_release=true" >> $GITHUB_OUTPUT
|
||||
echo "previous_tag=" >> $GITHUB_OUTPUT
|
||||
exit 0
|
||||
fi
|
||||
|
||||
PREVIOUS_MM=$(echo "$PREVIOUS_TAG" | sed 's/^v//; s/\([0-9]*\.[0-9]*\)\..*/\1/')
|
||||
if [ "$CURRENT_MM" = "$PREVIOUS_MM" ]; then
|
||||
echo "Patch-only bump ($PREVIOUS_TAG -> $CURRENT_TAG), skipping"
|
||||
echo "should_release=false" >> $GITHUB_OUTPUT
|
||||
echo "previous_tag=" >> $GITHUB_OUTPUT
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Minor/major bump — find the last tag from the previous release
|
||||
PREV_RELEASE_TAG=$(git tag --sort=-version:refname | while read -r t; do
|
||||
[ "$t" = "$CURRENT_TAG" ] && continue
|
||||
t_mm=$(echo "$t" | sed 's/^v//; s/\([0-9]*\.[0-9]*\)\..*/\1/')
|
||||
if [ "$t_mm" != "$CURRENT_MM" ]; then echo "$t"; break; fi
|
||||
done)
|
||||
echo "Minor/major bump, comparing against ${PREV_RELEASE_TAG:-$PREVIOUS_TAG}"
|
||||
echo "should_release=true" >> $GITHUB_OUTPUT
|
||||
echo "previous_tag=${PREV_RELEASE_TAG:-$PREVIOUS_TAG}" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Create draft release 📝
|
||||
if: steps.version_check.outputs.should_release == 'true' || github.event_name == 'workflow_dispatch'
|
||||
id: create_release
|
||||
uses: softprops/action-gh-release@v3
|
||||
with:
|
||||
tag_name: ${{ env.TAG }}
|
||||
name: Release ${{ env.TAG }}
|
||||
draft: true
|
||||
prerelease: false
|
||||
generate_release_notes: true
|
||||
previous_tag: ${{ steps.version_check.outputs.previous_tag }}
|
||||
token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Job summary 📋
|
||||
if: always()
|
||||
env:
|
||||
REPO_URL: ${{ github.server_url }}/${{ github.repository }}
|
||||
SHOULD_RELEASE: ${{ steps.version_check.outputs.should_release }}
|
||||
RELEASE_URL: ${{ steps.create_release.outputs.url }}
|
||||
PREV_TAG: ${{ steps.version_check.outputs.previous_tag }}
|
||||
run: |
|
||||
{
|
||||
echo "## 🏗️ Draft Release"
|
||||
echo ""
|
||||
echo "| Step | Result |"
|
||||
echo "|------|--------|"
|
||||
echo "| Tag | [\`${TAG}\`](${REPO_URL}/releases/tag/${TAG}) |"
|
||||
|
||||
if [ -n "$PREV_TAG" ]; then
|
||||
echo "| Compared against | [\`${PREV_TAG}\`](${REPO_URL}/releases/tag/${PREV_TAG}) |"
|
||||
fi
|
||||
|
||||
if [ -n "$RELEASE_URL" ]; then
|
||||
echo "| Draft release | ✅ [Review and publish](${RELEASE_URL}) |"
|
||||
elif [ "$SHOULD_RELEASE" = "false" ]; then
|
||||
echo "| Draft release | ⏭️ Skipped (patch-only bump) |"
|
||||
else
|
||||
echo "| Draft release | ❌ Failed |"
|
||||
fi
|
||||
} >> "$GITHUB_STEP_SUMMARY"
|
||||
170
.github/workflows/release.yml
vendored
Normal file
170
.github/workflows/release.yml
vendored
Normal file
@@ -0,0 +1,170 @@
|
||||
# Builds Dashy and drafts a GitHub release with the compiled tarball,
|
||||
# along with SHA256 checksum and SLSA build-provenance attestation
|
||||
#
|
||||
# Triggered by:
|
||||
# - Push of any major/minor (X.Y.0) git tag
|
||||
# - Manual dispatch with any existing tag (any version)
|
||||
|
||||
name: 🚀 Build & Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags: ['*.*.0']
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: 'Existing git tag to release (e.g. 4.2.0)'
|
||||
required: true
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ inputs.tag || github.ref_name }}
|
||||
cancel-in-progress: false
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
release:
|
||||
name: 🚀 Build & Draft Release
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 20
|
||||
permissions:
|
||||
contents: write
|
||||
id-token: write
|
||||
attestations: write
|
||||
env:
|
||||
TAG: ${{ inputs.tag || github.ref_name }}
|
||||
steps:
|
||||
- name: 🛎️ Checkout tag
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: refs/tags/${{ env.TAG }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: 🔧 Setup Node.js
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: '20'
|
||||
cache: 'yarn'
|
||||
|
||||
- name: 📥 Install dependencies
|
||||
run: yarn install --frozen-lockfile --ignore-engines --network-timeout 300000
|
||||
|
||||
- name: 🏗️ Build app
|
||||
run: NODE_OPTIONS=--openssl-legacy-provider yarn build --mode production
|
||||
|
||||
- name: 📦 Package release tarball
|
||||
id: package
|
||||
run: |
|
||||
set -euo pipefail
|
||||
STAGING="dashy-release-staging"
|
||||
mkdir -p "$STAGING"
|
||||
cp -r dist "$STAGING/"
|
||||
cp -r services "$STAGING/"
|
||||
cp -r public "$STAGING/"
|
||||
cp -r user-data "$STAGING/"
|
||||
cp server.js "$STAGING/"
|
||||
cp yarn.lock "$STAGING/"
|
||||
mkdir -p "$STAGING/src/utils/config"
|
||||
cp src/utils/config/ConfigSchema.json "$STAGING/src/utils/config/"
|
||||
node -e "
|
||||
const fs = require('fs');
|
||||
const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8'));
|
||||
delete pkg.devDependencies;
|
||||
fs.writeFileSync('$STAGING/package.json', JSON.stringify(pkg, null, 2));
|
||||
"
|
||||
TARBALL="dashy-${TAG}.tar.gz"
|
||||
tar -czf "$TARBALL" -C "$STAGING" .
|
||||
echo "tarball=$TARBALL" >> "$GITHUB_OUTPUT"
|
||||
echo "size=$(du -h "$TARBALL" | cut -f1)" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: 🔢 Generate SHA256 checksum
|
||||
id: checksum
|
||||
env:
|
||||
TARBALL: ${{ steps.package.outputs.tarball }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
CHECKSUM="${TARBALL}.sha256"
|
||||
sha256sum "$TARBALL" > "$CHECKSUM"
|
||||
echo "file=$CHECKSUM" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: 🪪 Generate build provenance attestation
|
||||
id: attest
|
||||
uses: actions/attest-build-provenance@v4
|
||||
with:
|
||||
subject-path: ${{ steps.package.outputs.tarball }}
|
||||
|
||||
- name: 📤 Rename attestation bundle
|
||||
id: attest_asset
|
||||
env:
|
||||
TARBALL: ${{ steps.package.outputs.tarball }}
|
||||
BUNDLE: ${{ steps.attest.outputs.bundle-path }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
OUT="${TARBALL}.intoto.jsonl"
|
||||
cp "$BUNDLE" "$OUT"
|
||||
echo "file=$OUT" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: 🔎 Find previous release tag
|
||||
id: prev
|
||||
env:
|
||||
CURRENT_TAG: ${{ env.TAG }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
git fetch --tags --force
|
||||
PREV=$({ echo "$CURRENT_TAG"; git tag | grep -E '^[0-9]+\.[0-9]+\.0$'; } \
|
||||
| sort -uV \
|
||||
| awk -v cur="$CURRENT_TAG" '$0 == cur { print prev; exit } { prev = $0 }')
|
||||
echo "tag=$PREV" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: 📝 Create draft release
|
||||
id: release
|
||||
uses: softprops/action-gh-release@v3
|
||||
with:
|
||||
tag_name: ${{ env.TAG }}
|
||||
name: Release ${{ env.TAG }}
|
||||
draft: true
|
||||
prerelease: false
|
||||
generate_release_notes: true
|
||||
previous_tag: ${{ steps.prev.outputs.tag }}
|
||||
fail_on_unmatched_files: true
|
||||
files: |
|
||||
${{ steps.package.outputs.tarball }}
|
||||
${{ steps.checksum.outputs.file }}
|
||||
${{ steps.attest_asset.outputs.file }}
|
||||
token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: 📋 Job summary
|
||||
if: always()
|
||||
env:
|
||||
REPO_URL: ${{ github.server_url }}/${{ github.repository }}
|
||||
PREV_TAG: ${{ steps.prev.outputs.tag }}
|
||||
RELEASE_URL: ${{ steps.release.outputs.url }}
|
||||
TARBALL: ${{ steps.package.outputs.tarball }}
|
||||
SIZE: ${{ steps.package.outputs.size }}
|
||||
ATTEST_URL: ${{ steps.attest.outputs.attestation-url }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
{
|
||||
echo "## 🚀 Release Draft"
|
||||
echo ""
|
||||
echo "| Item | Value |"
|
||||
echo "|------|-------|"
|
||||
echo "| Tag | [\`${TAG}\`](${REPO_URL}/releases/tag/${TAG}) |"
|
||||
if [ -n "$PREV_TAG" ]; then
|
||||
echo "| Notes since | [\`${PREV_TAG}\`](${REPO_URL}/releases/tag/${PREV_TAG}) |"
|
||||
fi
|
||||
if [ -n "$TARBALL" ]; then
|
||||
echo "| Tarball | \`${TARBALL}\` (${SIZE:-?}) |"
|
||||
fi
|
||||
if [ -n "$ATTEST_URL" ]; then
|
||||
echo "| Attestation | ✅ [View](${ATTEST_URL}) |"
|
||||
else
|
||||
echo "| Attestation | ❌ Failed |"
|
||||
fi
|
||||
if [ -n "$RELEASE_URL" ]; then
|
||||
echo "| Draft release | ✅ [Review and publish](${RELEASE_URL}) |"
|
||||
else
|
||||
echo "| Draft release | ❌ Failed |"
|
||||
fi
|
||||
} >> "$GITHUB_STEP_SUMMARY"
|
||||
Reference in New Issue
Block a user