Nightly Build #61
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Nightly Build | |
| on: | |
| schedule: | |
| - cron: "0 6 * * *" # 06:00 UTC nightly | |
| workflow_dispatch: | |
| concurrency: | |
| group: nightly | |
| cancel-in-progress: true | |
| jobs: | |
| nightly-build: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| build_date: ${{ steps.capture.outputs.build_date }} | |
| git_hash: ${{ steps.capture.outputs.git_hash }} | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Capture metadata | |
| id: capture | |
| run: | | |
| echo "build_date=$(date -u +"%Y-%m-%dT%H:%M:%SZ")" >> $GITHUB_OUTPUT | |
| echo "git_hash=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.12' | |
| - name: Install build dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y pandoc rpm dpkg-dev | |
| sudo apt-get install -y libarchive-zip-perl | |
| - name: Install Python build dependencies | |
| run: | | |
| python3 -m pip install --upgrade pip | |
| python3 -m pip install pyinstaller | |
| - name: Install PythonTools | |
| run: | | |
| if [ ! -d PythonTools ]; then | |
| git clone https://github.com/linktech-engineering-llc/PythonTools.git | |
| fi | |
| python3 -m pip install PythonTools/ | |
| - name: Make scripts executable | |
| run: chmod +x packaging/*.sh | |
| - name: Build all artifacts | |
| run: ./packaging/build_all.sh | |
| - name: Normalize RPM filename | |
| run: | | |
| OUT=packaging/output | |
| RPM_SRC=$(find packaging/rpmbuild/RPMS/x86_64 -type f -name "*.rpm" | head -n 1) | |
| if [[ -n "$RPM_SRC" ]]; then | |
| ARCH=$(echo "$RPM_SRC" | sed -n 's/.*\.\(.*\)\.rpm/\1/p') | |
| VERSION=$(basename "$RPM_SRC" | sed -n 's/RunUpdates-\(.*\)-.*\.rpm/\1/p') | |
| mv "$RPM_SRC" "$OUT/RunUpdates_${VERSION}.${ARCH}.rpm" | |
| fi | |
| - name: Collect artifacts | |
| run: | | |
| mkdir -p artifacts | |
| cp packaging/output/RunUpdates_* artifacts/ | |
| - name: Generate metadata.json | |
| run: | | |
| mkdir -p artifacts | |
| # Detect toolchain versions | |
| PYTHON_VERSION=$(python3 --version | awk '{print $2}') | |
| PYINSTALLER_VERSION=$(pyinstaller --version 2>/dev/null || echo "unknown") | |
| BUILDER_OS="ubuntu-latest" | |
| # Start metadata.json | |
| cat > artifacts/metadata.json <<EOF | |
| { | |
| "meta_version": 2, | |
| "build": { | |
| "date": "${{ steps.capture.outputs.build_date }}", | |
| "commit": "${{ steps.capture.outputs.git_hash }}", | |
| "branch": "nightly", | |
| "workflow_run_id": $GITHUB_RUN_ID | |
| }, | |
| "toolchain": { | |
| "python": "$PYTHON_VERSION", | |
| "pyinstaller": "$PYINSTALLER_VERSION", | |
| "builder_os": "$BUILDER_OS" | |
| }, | |
| "artifacts": [ | |
| EOF | |
| FIRST=1 | |
| for f in artifacts/RunUpdates_*; do | |
| NAME=$(basename "$f") | |
| SIZE=$(stat -c%s "$f") | |
| SHA=$(sha256sum "$f" | awk '{print $1}') | |
| CRC=$(crc32 "$f") | |
| # Detect type, OS, arch | |
| case "$NAME" in | |
| *.deb) | |
| TYPE="deb" | |
| OS="linux" | |
| ARCH="amd64" | |
| ;; | |
| *.rpm) | |
| TYPE="rpm" | |
| OS="linux" | |
| ARCH="x86_64" | |
| ;; | |
| *.zip) | |
| TYPE="zip" | |
| OS="windows" | |
| ARCH="x86_64" | |
| ;; | |
| *.tgz|*.tar.gz) | |
| TYPE="tgz" | |
| OS="linux" | |
| ARCH="amd64" | |
| ;; | |
| *) | |
| TYPE="unknown" | |
| OS="unknown" | |
| ARCH="unknown" | |
| ;; | |
| esac | |
| if [ $FIRST -eq 0 ]; then | |
| echo "," >> artifacts/metadata.json | |
| fi | |
| FIRST=0 | |
| cat >> artifacts/metadata.json <<EOF | |
| { | |
| "name": "$NAME", | |
| "type": "$TYPE", | |
| "os": "$OS", | |
| "arch": "$ARCH", | |
| "size": $SIZE, | |
| "sha256": "$SHA", | |
| "crc32": "$CRC" | |
| } | |
| EOF | |
| done | |
| # Close JSON | |
| cat >> artifacts/metadata.json <<EOF | |
| ] | |
| } | |
| EOF | |
| - name: Upload nightly artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: nightly-runupdates | |
| path: artifacts | |
| - name: Validate metadata.json | |
| run: | | |
| pip install jsonschema | |
| python3 packaging/metadata/validate.py artifacts/metadata.json | |
| - name: Remove existing nightly assets | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| ASSETS=$(gh release view nightly --json assets --jq '.assets[].name') | |
| for asset in $ASSETS; do | |
| if [[ "$asset" == RunUpdates* ]]; then | |
| echo "Deleting asset: $asset" | |
| gh release delete-asset nightly "$asset" --yes | |
| fi | |
| done | |
| - name: Upload artifacts to nightly release | |
| uses: softprops/action-gh-release@v1 | |
| with: | |
| tag_name: nightly | |
| files: packaging/output/* | |
| publish-dashboard: | |
| runs-on: ubuntu-latest | |
| needs: nightly-build | |
| steps: | |
| - name: Checkout gh-pages branch | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: gh-pages | |
| - name: Preserve existing dashboard files | |
| run: | | |
| mkdir -p dashboard | |
| cp dashboard.js dashboard.js.bak 2>/dev/null || true | |
| - name: Download nightly artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: nightly-runupdates | |
| path: artifacts | |
| - name: Copy metadata.json to dashboard root | |
| run: | | |
| cp artifacts/metadata.json . | |
| - name: Generate dashboard HTML | |
| run: | | |
| META=artifacts/metadata.json | |
| RELEASE_URL="https://github.com/Linktech-Engineering-LLC/RunUpdates/releases/download/nightly" | |
| mkdir -p dashboard | |
| rm -f dashboard/* | |
| curl -s -o dashboard/qr.png \ | |
| "https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=https://linktech-engineering-llc.github.io/RunUpdates/" | |
| cat > dashboard/index.html <<EOF | |
| <html> | |
| <head> | |
| <title>RunUpdates Nightly Dashboard</title> | |
| <style> | |
| body { font-family: Arial; margin: 20px; } | |
| table { border-collapse: collapse; margin-top: 10px; width: 100%; } | |
| th, td { padding: 8px 12px; border: 1px solid #ccc; } | |
| th { background: #f0f0f0; } | |
| .badge-row img { margin-right: 8px; } | |
| .download-btn { | |
| background: #0078d4; | |
| color: white; | |
| padding: 6px 12px; | |
| border-radius: 4px; | |
| text-decoration: none; | |
| } | |
| .download-btn:hover { | |
| background: #005a9e; | |
| } | |
| .qr { margin-top: 20px; } | |
| </style> | |
| </head> | |
| <body> | |
| <h1>RunUpdates Nightly Dashboard</h1> | |
| <div class="badge-row"> | |
| <img src="https://img.shields.io/badge/version-loading-blue" id="version-badge"> | |
| <img src="https://img.shields.io/badge/date-loading-lightgrey" id="date-badge"> | |
| <img src="https://img.shields.io/badge/python-loading-yellow" id="python-badge"> | |
| <img src="https://img.shields.io/badge/pyinstaller-loading-orange" id="pyi-badge"> | |
| </div> | |
| <h2>Build Metadata</h2> | |
| <div id="build-info"></div> | |
| <h2>Artifacts</h2> | |
| <div id="artifact-table"></div> | |
| <div class="qr"> | |
| <h2>QR Code</h2> | |
| <img src="qr.png" alt="QR Code"> | |
| </div> | |
| <script src="dashboard.js"></script> | |
| </body> | |
| </html> | |
| - name: Restore dashboard.js | |
| run: | | |
| if [ -f dashboard.js.bak ]; then | |
| mv dashboard.js.bak dashboard.js | |
| fi | |
| - name: Publish dashboard to gh-pages | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| cp -r dashboard/* . | |
| git add . | |
| git commit -m "Update nightly dashboard" || echo "No changes" | |
| git push origin gh-pages |