Skip to content

Nightly Release

Nightly Release #51

name: Nightly Release
on:
schedule:
- cron: "0 0 * * *" # Daily at 00:00 UTC
workflow_dispatch:
push:
branches:
- main
env:
cache_nonce: 0
pinned_branch: master
jobs:
# Run tests
test:
name: Run tests
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Install mise
uses: jdx/mise-action@v3
with:
enable: true
cache: true
- name: Create virtual environment
run: |
python -m venv venv
- name: Install test dependencies
run: |
source venv/bin/activate
pip install -r requirements-test.txt
- name: Run tests with coverage
run: |
source venv/bin/activate
pytest tests/ -v --cov=src --cov-report=xml --cov-report=term
- name: Upload coverage reports
if: github.event_name != 'workflow_dispatch'
uses: codecov/codecov-action@v5
continue-on-error: true
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./coverage.xml
flags: unittests
name: codecov-umbrella
fail_ci_if_error: false
# Check for new commits
check-updates:
runs-on: ubuntu-latest
needs: test
outputs:
should_build: ${{ steps.check.outputs.should_build }}
commit_hash: ${{ steps.check.outputs.commit_hash }}
commit_short: ${{ steps.check.outputs.commit_short }}
commit_date: ${{ steps.check.outputs.commit_date }}
branch_name: ${{ steps.check.outputs.branch_name }}
previous_commit: ${{ steps.check.outputs.previous_commit }}
steps:
- name: Check for new commits
id: check
run: |
# Use pinned commit/branch if set, otherwise fetch latest from pinned_branch
if [ -n "${{ env.pinned_commit }}" ]; then
# Validate that both pinned_branch and pinned_commit are set
if [ -z "${{ env.pinned_branch }}" ]; then
echo "Error: pinned_commit is set but pinned_branch is not set. Both must be provided together."
exit 1
fi
LATEST_COMMIT="${{ env.pinned_commit }}"
LATEST_SHORT=$(echo $LATEST_COMMIT | cut -c1-7)
BRANCH_NAME="${{ env.pinned_branch }}"
echo "Using pinned commit: $LATEST_SHORT from branch: $BRANCH_NAME"
else
# Fetch latest commit from logos-storage-nim
BRANCH_NAME="${{ env.pinned_branch }}"
git ls-remote https://github.com/logos-storage/logos-storage-nim.git refs/heads/$BRANCH_NAME > latest.txt
LATEST_COMMIT=$(awk '{print $1}' latest.txt)
LATEST_SHORT=$(echo $LATEST_COMMIT | cut -c1-7)
echo "Using latest commit from $BRANCH_NAME: $LATEST_SHORT"
fi
# Fetch commit date using GitHub API
API_URL="https://api.github.com/repos/logos-storage/logos-storage-nim/commits/$LATEST_COMMIT"
COMMIT_DATE=$(curl -s "$API_URL" | python3 -c "import sys, json; data=json.load(sys.stdin); print(data['commit']['committer']['date'])" 2>/dev/null || echo "Unknown")
# Get latest prerelease release from this repository
LATEST_PRERELEASE=$(curl -s "https://api.github.com/repos/${{ github.repository }}/releases?per_page=10" | python3 -c "import sys, json; data=json.load(sys.stdin); prereleases=[r for r in data if r.get('prerelease')]; print(prereleases[0]['body'] if prereleases else '')" 2>/dev/null || echo "")
# Extract previous commit hash from prerelease release body
PREVIOUS_COMMIT=$(echo "$LATEST_PRERELEASE" | grep -oP 'Commit: \K[a-f0-9]{40}' || echo "")
# If no prerelease exists, we should build
if [ -z "$LATEST_PRERELEASE" ]; then
echo "should_build=true" >> $GITHUB_OUTPUT
echo "commit_hash=$LATEST_COMMIT" >> $GITHUB_OUTPUT
echo "commit_short=$LATEST_SHORT" >> $GITHUB_OUTPUT
echo "commit_date=$COMMIT_DATE" >> $GITHUB_OUTPUT
echo "branch_name=$BRANCH_NAME" >> $GITHUB_OUTPUT
echo "previous_commit=" >> $GITHUB_OUTPUT
echo "No previous prerelease found, building for commit: $LATEST_SHORT"
exit 0
fi
# Check if the prerelease body contains the full commit hash
if echo "$LATEST_PRERELEASE" | grep -q "$LATEST_COMMIT"; then
echo "should_build=false" >> $GITHUB_OUTPUT
echo "Latest commit $LATEST_SHORT is already released"
else
echo "should_build=true" >> $GITHUB_OUTPUT
echo "commit_hash=$LATEST_COMMIT" >> $GITHUB_OUTPUT
echo "commit_short=$LATEST_SHORT" >> $GITHUB_OUTPUT
echo "commit_date=$COMMIT_DATE" >> $GITHUB_OUTPUT
echo "branch_name=$BRANCH_NAME" >> $GITHUB_OUTPUT
echo "previous_commit=$PREVIOUS_COMMIT" >> $GITHUB_OUTPUT
echo "New commit detected: $LATEST_SHORT"
fi
# Matrix build
build:
needs: [test, check-updates]
if: needs.check-updates.outputs.should_build == 'true'
strategy:
fail-fast: false
matrix:
include:
- os: linux
cpu: amd64
builder: ubuntu-latest
- os: linux
cpu: arm64
builder: ubuntu-22.04-arm
- os: macos
cpu: arm64
builder: macos-latest
- os: windows
cpu: amd64
builder: windows-latest
name: ${{ matrix.os }}-${{ matrix.cpu }}
runs-on: ${{ matrix.builder }}
timeout-minutes: 120
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Install mise
uses: jdx/mise-action@v3
with:
enable: true
cache: true
- name: Setup MSYS2 (Windows)
if: runner.os == 'Windows'
uses: msys2/setup-msys2@v2
with:
msystem: MINGW64
update: true
path-type: inherit
install: >-
base-devel
mingw-w64-x86_64-gcc
mingw-w64-x86_64-cmake
mingw-w64-x86_64-make
git
- name: Install build dependencies (Linux)
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y git make gcc binutils cmake
shell: bash
- name: Build (Windows)
if: runner.os == 'Windows'
shell: msys2 {0}
run: |
make clean
make
env:
BRANCH: ${{ env.pinned_branch }}
COMMIT: ${{ env.pinned_commit }}
- name: Build (Unix)
if: runner.os != 'Windows'
run: |
make clean
make
env:
BRANCH: ${{ env.pinned_branch }}
COMMIT: ${{ env.pinned_commit }}
shell: bash
- name: Upload artifacts
if: env.ACT != 'true'
uses: actions/upload-artifact@v6
continue-on-error: true
with:
name: libstorage-${{ matrix.os }}-${{ matrix.cpu }}
path: dist/*/
retention-days: 90
- name: Verify artifacts (Windows)
if: runner.os == 'Windows'
shell: msys2 {0}
run: |
echo "Verifying artifacts..."
if [ -d "dist" ]; then
# List all library files
find dist -name "*.a" -type f | while read lib; do
echo "Found: $lib"
ls -lh "$lib"
done
# Verify SHA256SUMS.txt
find dist -name "SHA256SUMS.txt" -type f | while read checksum_file; do
echo "Verifying checksums in: $checksum_file"
# Change to the directory containing the checksum file before verification
checksum_dir=$(dirname "$checksum_file")
(cd "$checksum_dir" && sha256sum -c "SHA256SUMS.txt")
done
echo ""
echo "Artifacts are available in: $(pwd)/dist/"
else
echo "No dist directory found"
fi
- name: Verify artifacts (Unix)
if: runner.os != 'Windows'
shell: bash
run: |
echo "Verifying artifacts..."
if [ -d "dist" ]; then
# List all library files
find dist -name "*.a" -type f | while read lib; do
echo "Found: $lib"
ls -lh "$lib"
done
# Verify SHA256SUMS.txt
find dist -name "SHA256SUMS.txt" -type f | while read checksum_file; do
echo "Verifying checksums in: $checksum_file"
# Change to the directory containing the checksum file before verification
checksum_dir=$(dirname "$checksum_file")
(cd "$checksum_dir" && sha256sum -c "SHA256SUMS.txt")
done
echo ""
echo "Artifacts are available in: $(pwd)/dist/"
else
echo "No dist directory found"
fi
# Fetch commit changes
fetch-commits:
runs-on: ubuntu-latest
needs: [test, check-updates]
if: needs.check-updates.outputs.should_build == 'true'
outputs:
commit_changes: ${{ steps.fetch.outputs.changes }}
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Install mise
uses: jdx/mise-action@v3
with:
enable: true
cache: true
- name: Create virtual environment
run: |
python -m venv venv
- name: Install dependencies
run: |
source venv/bin/activate
pip install -r requirements-test.txt
- name: Fetch commit changes
id: fetch
run: |
source venv/bin/activate
PREVIOUS_COMMIT="${{ needs.check-updates.outputs.previous_commit }}"
CURRENT_COMMIT="${{ needs.check-updates.outputs.commit_hash }}"
if [ -z "$PREVIOUS_COMMIT" ]; then
echo "No previous commit found, this is the first release"
echo "changes=First release - no previous commit to compare" >> $GITHUB_OUTPUT
exit 0
fi
echo "Fetching commits between $PREVIOUS_COMMIT and $CURRENT_COMMIT"
# Clone the upstream repository
git clone --depth 100 https://github.com/logos-storage/logos-storage-nim.git /tmp/logos-storage-nim
# Generate release notes using Python script
CHANGES=$(python src/release_notes.py \
--repo-path /tmp/logos-storage-nim \
--previous-commit "$PREVIOUS_COMMIT" \
--current-commit "$CURRENT_COMMIT")
if [ -z "$CHANGES" ] || [ "$CHANGES" = "No commits found between releases" ]; then
echo "No commits found between releases"
echo "changes=No commits found between releases" >> $GITHUB_OUTPUT
else
# Count commits
COMMIT_COUNT=$(echo "$CHANGES" | wc -l)
echo "Found $COMMIT_COUNT commits"
# Escape for YAML - only escape quotes, keep newlines as-is
CHANGES_ESCAPED=$(echo "$CHANGES" | sed 's/"/\\"/g')
# Use a delimiter to preserve newlines in the output
echo "changes<<EOF" >> $GITHUB_OUTPUT
echo "$CHANGES_ESCAPED" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
fi
# Create release
release:
needs: [check-updates, build, fetch-commits]
if: needs.check-updates.outputs.should_build == 'true'
runs-on: ubuntu-latest
steps:
- name: Download artifacts
if: env.ACT != 'true'
uses: actions/download-artifact@v7
continue-on-error: true
with:
pattern: libstorage-*
merge-multiple: true
path: /tmp/release
- name: Compress and checksum
if: env.ACT != 'true'
run: |
cd /tmp/release
# Find all directories and create archives
for dir in */; do
dir_name=$(basename "$dir")
# Directory name is already in the correct format: {branch}-{commit_short}-{platform}
# Use it directly to create the archive name
archive="logos-storage-nim-${dir_name}.tar.gz"
cd "$dir"
tar cfz "/tmp/release/${archive}" *.a libstorage.h SHA256SUMS.txt
cd /tmp/release
done
# Create SHA256SUMS.txt for all archives
sha256sum *.tar.gz > SHA256SUMS.txt
- name: Create release
if: env.ACT != 'true'
uses: softprops/action-gh-release@v2
continue-on-error: true
with:
tag_name: ${{ needs.check-updates.outputs.branch_name }}-${{ needs.check-updates.outputs.commit_short }}
name: ${{ needs.check-updates.outputs.branch_name }}-${{ needs.check-updates.outputs.commit_short }}
body: |
## Nightly pre-built static librairies of logos-storage-nim
_⚠️ Nightly builds are not suitable for production use._
Commit: ${{ needs.check-updates.outputs.commit_hash }}
Branch: ${{ needs.check-updates.outputs.branch_name }}
Date: ${{ needs.check-updates.outputs.commit_date }}
Artifacts:
- Linux x86_64: logos-storage-nim-${{ needs.check-updates.outputs.branch_name }}-${{ needs.check-updates.outputs.commit_short }}-linux-amd64.tar.gz
- Linux AArch64: logos-storage-nim-${{ needs.check-updates.outputs.branch_name }}-${{ needs.check-updates.outputs.commit_short }}-linux-arm64.tar.gz
- macOS Apple Silicon: logos-storage-nim-${{ needs.check-updates.outputs.branch_name }}-${{ needs.check-updates.outputs.commit_short }}-darwin-arm64.tar.gz
- Windows x86_64: logos-storage-nim-${{ needs.check-updates.outputs.branch_name }}-${{ needs.check-updates.outputs.commit_short }}-windows-amd64.tar.gz
Each archive contains:
- libstorage.a: Main storage library
- libnatpmp.a: NAT-PMP library
- libminiupnpc.a: MiniUPnP library
- libbacktrace.a: Backtrace library
- libstorage.h: C header file
- SHA256SUMS.txt: Checksums for all files
Archive checksums: SHA256SUMS.txt
---
### Changes since last nightly release
${{ needs.fetch-commits.outputs.commit_changes }}
files: |
/tmp/release/*.tar.gz
/tmp/release/SHA256SUMS.txt
draft: false
prerelease: true
env:
GITHUB_TOKEN: ${{ secrets.GH_PAT }}