Skip to content

Scheduled Release

Scheduled Release #63

name: Scheduled Release
on:
schedule:
- cron: "0 3 * * *"
workflow_dispatch:
inputs:
force:
description: "Force release (ignore time + PR checks)"
required: false
default: "false"
skip_binaries:
description: "Skip building static binaries (manual release only)"
required: false
default: "false"
jobs:
release:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Get last release info
id: last_release
uses: actions/github-script@v7
with:
script: |
const releases = await github.rest.repos.listReleases({
owner: context.repo.owner,
repo: context.repo.repo,
per_page: 1
});
if (!releases.data.length) {
core.setOutput("days", "9999");
core.setOutput("since", new Date(0).toISOString());
return;
}
const last = new Date(releases.data[0].published_at);
const now = new Date();
const diffDays = Math.floor((now - last) / (1000 * 60 * 60 * 24));
core.setOutput("days", String(diffDays));
core.setOutput("since", last.toISOString());
- name: Get ship PRs since last release
id: prs
uses: actions/github-script@v7
with:
script: |
const since = new Date("${{ steps.last_release.outputs.since }}");
const pulls = await github.rest.pulls.list({
owner: context.repo.owner,
repo: context.repo.repo,
state: "closed",
sort: "updated",
direction: "desc",
per_page: 100
});
const shipPRs = pulls.data.filter(pr =>
pr.merged_at &&
new Date(pr.merged_at) > since &&
pr.labels.some(l => l.name === "ship")
);
const titles = shipPRs.map(pr => pr.title);
core.setOutput("count", String(shipPRs.length));
core.setOutput("titles", titles.join("\n"));
- name: Decide release
id: decide
run: |
DAYS=${{ steps.last_release.outputs.days }}
PR_COUNT=${{ steps.prs.outputs.count }}
FORCE="${{ github.event.inputs.force }}"
echo "Days since release: $DAYS"
echo "Ship PRs: $PR_COUNT"
echo "Force mode: $FORCE"
if [ "$FORCE" = "true" ]; then
echo "release=true" >> $GITHUB_OUTPUT
exit 0
fi
if [ "$DAYS" -ge 14 ] && [ "$PR_COUNT" -gt 0 ]; then
echo "release=true" >> $GITHUB_OUTPUT
else
echo "release=false" >> $GITHUB_OUTPUT
fi
- name: Install Nim
if: steps.decide.outputs.release == 'true'
uses: iffy/install-nim@v5
- name: Build versionctl
if: steps.decide.outputs.release == 'true'
run: nim generate_versionctl
- name: Get version
id: version
if: steps.decide.outputs.release == 'true'
run: |
VERSION="v$(./versionctl print 2>/dev/null)"
if [ -z "$VERSION" ]; then
echo "ERROR: versionctl failed"
exit 1
fi
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "Using version: $VERSION"
- name: Generate changelog
if: steps.decide.outputs.release == 'true'
run: |
echo "## What has Changed (${{ steps.version.outputs.version }})" > CHANGELOG.md
echo "" >> CHANGELOG.md
if [ -z "${{ steps.prs.outputs.titles }}" ]; then
echo "- No changes found" >> CHANGELOG.md
else
echo "${{ steps.prs.outputs.titles }}" | while read line; do
echo "- $line" >> CHANGELOG.md
done
fi
- name: Package config files
if: steps.decide.outputs.release == 'true'
run: |
VERSION="${{ steps.version.outputs.version }}"
tar -czf "catnap-${VERSION}-config.tar.gz" config/
- name: Create Release
if: steps.decide.outputs.release == 'true'
id: create_release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ steps.version.outputs.version }}
name: ${{ steps.version.outputs.version }}
body_path: CHANGELOG.md
files: catnap-${{ steps.version.outputs.version }}-config.tar.gz
build-binaries:
needs: release
if: |
needs.release.result == 'success' &&
needs.release.outputs.version != '' &&
github.event.inputs.skip_binaries != 'true'
uses: ./.github/workflows/build-static.yml
attach-binaries:
needs: [release, build-binaries]
if: |
needs.release.outputs.version != '' &&
needs.build-binaries.result == 'success'
runs-on: ubuntu-latest
steps:
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts/
- name: Rename binaries with target suffix
run: |
VERSION="${{ needs.release.outputs.version }}"
mkdir -p release-files
for dir in artifacts/catnap-linux-*/; do
arch=$(basename "$dir" | sed 's/catnap-linux-//')
cp "$dir/catnap" "release-files/catnap-${VERSION}-${arch}"
done
ls -la release-files/
- name: Attach binaries to release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ needs.release.outputs.version }}
files: release-files/*