name: Nightly Build on: schedule: # Run every day at 2 AM UTC - cron: '0 2 * * *' workflow_dispatch: inputs: targets: description: 'Comma-separated list of targets to build (leave empty for all)' required: false default: '' skip_tests: description: 'Skip running tests' type: boolean required: false default: false create_prerelease: description: 'Create pre-release with nightly builds' type: boolean required: false default: false env: CARGO_TERM_COLOR: always RUST_BACKTRACE: 1 jobs: # Check if we should skip nightly (no changes since last nightly) check-changes: name: Check for Changes runs-on: ubuntu-latest outputs: should_build: ${{ steps.changes.outputs.should_build }} commit_sha: ${{ steps.changes.outputs.commit_sha }} commit_message: ${{ steps.changes.outputs.commit_message }} steps: - name: Checkout repository uses: actions/checkout@v4 with: fetch-depth: 0 - name: Check for changes since last nightly id: changes run: | # Get the last nightly tag or fall back to a week ago LAST_NIGHTLY=$(git tag -l "nightly-*" | sort -V | tail -1) if [ -z "$LAST_NIGHTLY" ]; then # No previous nightly, check for changes in the last week SINCE="$(date -d '7 days ago' '+%Y-%m-%d')" echo "No previous nightly found, checking changes since $SINCE" CHANGES=$(git log --since="$SINCE" --oneline | wc -l) else echo "Last nightly: $LAST_NIGHTLY" CHANGES=$(git rev-list --count "$LAST_NIGHTLY"..HEAD) fi echo "Changes found: $CHANGES" if [ "$CHANGES" -gt 0 ] || [ "${{ github.event_name }}" = "workflow_dispatch" ]; then echo "should_build=true" >> $GITHUB_OUTPUT echo "commit_sha=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT echo "commit_message=$(git log -1 --pretty=format:'%s')" >> $GITHUB_OUTPUT echo "✅ Changes detected, will build nightly" else echo "should_build=false" >> $GITHUB_OUTPUT echo "❌ No changes since last nightly, skipping build" fi # Validate setup validate: name: Validate Setup runs-on: ubuntu-latest needs: check-changes if: needs.check-changes.outputs.should_build == 'true' outputs: nushell-version: ${{ steps.version.outputs.version }} nightly-tag: ${{ steps.tag.outputs.tag }} steps: - name: Checkout repository uses: actions/checkout@v4 with: submodules: recursive - name: Install Nushell uses: hustcer/setup-nu@v3 with: version: '0.107.1' - name: Generate nightly tag id: tag run: | NIGHTLY_TAG="nightly-$(date '+%Y%m%d')" echo "tag=$NIGHTLY_TAG" >> $GITHUB_OUTPUT echo "Nightly tag: $NIGHTLY_TAG" - name: Validate nushell version id: version run: | echo "Validating nushell version consistency..." nu scripts/check_version.nu --quiet || { echo "Version mismatch detected, attempting fix..." nu scripts/check_version.nu --fix } echo "version=0.107.1" >> $GITHUB_OUTPUT - name: Check upstream changes run: | echo "Checking for upstream changes..." nu scripts/check_upstream_changes.nu || { echo "⚠️ Upstream changes detected but not failing nightly build" echo "Consider reviewing and merging upstream changes" } # Build matrix for nightly builds build-nightly: name: Nightly Build (${{ matrix.target }}) runs-on: ${{ matrix.os }} needs: [check-changes, validate] if: needs.check-changes.outputs.should_build == 'true' strategy: fail-fast: false matrix: include: # Core platforms for nightly - target: linux-amd64 os: ubuntu-latest rust-target: x86_64-unknown-linux-gnu cross-compile: false priority: high - target: darwin-arm64 os: macos-latest rust-target: aarch64-apple-darwin cross-compile: false priority: high - target: windows-amd64 os: windows-latest rust-target: x86_64-pc-windows-msvc cross-compile: false priority: medium # Additional targets (can be disabled for faster nightly) - target: linux-arm64 os: ubuntu-latest rust-target: aarch64-unknown-linux-gnu cross-compile: true priority: low - target: darwin-amd64 os: macos-13 rust-target: x86_64-apple-darwin cross-compile: false priority: low steps: - name: Checkout repository uses: actions/checkout@v4 with: submodules: recursive - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable with: targets: ${{ matrix.rust-target }} - name: Install Nushell uses: hustcer/setup-nu@v3 with: version: ${{ needs.validate.outputs.nushell-version }} - name: Set up cross-compilation (Linux ARM64) if: matrix.cross-compile && matrix.target == 'linux-arm64' run: | sudo apt-get update sudo apt-get install -y gcc-aarch64-linux-gnu echo "CC_aarch64_unknown_linux_gnu=aarch64-linux-gnu-gcc" >> $GITHUB_ENV echo "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc" >> $GITHUB_ENV - name: Cache Cargo dependencies uses: actions/cache@v4 with: path: | ~/.cargo/registry ~/.cargo/git target key: nightly-${{ runner.os }}-${{ matrix.target }}-cargo-${{ hashFiles('**/Cargo.lock') }} restore-keys: | nightly-${{ runner.os }}-${{ matrix.target }}-cargo- ${{ runner.os }}-${{ matrix.target }}-cargo- - name: Build nightly binaries run: | echo "Building nightly binaries for ${{ matrix.target }}..." if [ "${{ matrix.cross-compile }}" = "true" ]; then nu scripts/build_cross.nu --targets ${{ matrix.target }} else nu scripts/build_all.nu --target ${{ matrix.rust-target }} fi shell: bash - name: Run tests if: github.event.inputs.skip_tests != 'true' && !matrix.cross-compile run: | echo "Running tests for ${{ matrix.target }}..." for plugin in nu_plugin_*; do if [ -d "$plugin" ]; then echo "Testing $plugin..." cd "$plugin" cargo test --target ${{ matrix.rust-target }} || { echo "⚠️ Tests failed for $plugin but continuing nightly build" } cd .. fi done shell: bash - name: Collect nightly artifacts run: | echo "Collecting nightly artifacts..." nu scripts/collect_install.nu --platform ${{ matrix.target }} --force - name: Package nightly build run: | echo "Creating nightly package..." nu scripts/pack_dist.nu --platform ${{ matrix.target }} --force shell: bash - name: Upload nightly artifacts uses: actions/upload-artifact@v4 with: name: nightly-${{ matrix.target }} path: | bin_archives/*${{ matrix.target }}* retention-days: 7 # Create nightly pre-release create-nightly-release: name: Create Nightly Pre-release runs-on: ubuntu-latest needs: [check-changes, validate, build-nightly] if: needs.check-changes.outputs.should_build == 'true' && (github.event.inputs.create_prerelease == 'true' || github.event_name == 'schedule') permissions: contents: write steps: - name: Checkout repository uses: actions/checkout@v4 - name: Install Nushell uses: hustcer/setup-nu@v3 with: version: ${{ needs.validate.outputs.nushell-version }} - name: Download nightly artifacts uses: actions/download-artifact@v4 with: path: nightly-artifacts/ - name: Organize nightly assets run: | echo "Organizing nightly assets..." mkdir -p nightly-assets # Copy all archives find nightly-artifacts/ -name "*.tar.gz" -o -name "*.zip" | while read file; do # Rename to include nightly tag basename=$(basename "$file") nightly_name=$(echo "$basename" | sed "s/nushell-plugins/${{ needs.validate.outputs.nightly-tag }}-nushell-plugins/") cp "$file" "nightly-assets/$nightly_name" done echo "Nightly assets:" ls -la nightly-assets/ - name: Generate checksums for nightly run: | cd nightly-assets sha256sum * > checksums.txt echo "Generated checksums:" cat checksums.txt - name: Delete previous nightly release run: | # Delete previous nightly release if it exists if gh release view "${{ needs.validate.outputs.nightly-tag }}" >/dev/null 2>&1; then echo "Deleting previous nightly release..." gh release delete "${{ needs.validate.outputs.nightly-tag }}" --yes fi env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} continue-on-error: true - name: Create nightly pre-release run: | cat > nightly_notes.md << 'EOF' ## Nightly Build - ${{ needs.validate.outputs.nightly-tag }} **⚠️ This is an automated nightly build and may be unstable.** ### Build Information - **Commit**: ${{ needs.check-changes.outputs.commit_sha }} - **Commit Message**: ${{ needs.check-changes.outputs.commit_message }} - **Build Date**: $(date -u '+%Y-%m-%d %H:%M:%S UTC') - **Nushell Version**: ${{ needs.validate.outputs.nushell-version }} ### Installation ```bash # Quick install (replace PLATFORM with your platform) curl -L https://github.com/${{ github.repository }}/releases/download/${{ needs.validate.outputs.nightly-tag }}/PLATFORM-${{ needs.validate.outputs.nightly-tag }}-nushell-plugins.tar.gz | tar -xz cd PLATFORM-${{ needs.validate.outputs.nightly-tag }}-nushell-plugins nu install_nu_plugins.nu ``` ### Available Platforms $(ls nightly-assets/*.tar.gz nightly-assets/*.zip 2>/dev/null | sed 's/nightly-assets\///g' | sed 's/^/- /' || echo "- Check release assets below") ### Notes - Nightly builds are automatically created when changes are detected - Previous nightly builds are automatically cleaned up - For stable releases, see [Releases](https://github.com/${{ github.repository }}/releases) - Report issues with nightly builds in [Issues](https://github.com/${{ github.repository }}/issues) ### Verification All nightly assets include SHA256 checksums: ```bash sha256sum -c checksums.txt ``` EOF gh release create "${{ needs.validate.outputs.nightly-tag }}" \ --title "Nightly Build - ${{ needs.validate.outputs.nightly-tag }}" \ --notes-file nightly_notes.md \ --prerelease \ nightly-assets/* env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Clean up old nightly releases run: | echo "Cleaning up old nightly releases (keeping last 7)..." gh release list --limit 50 | grep "nightly-" | tail -n +8 | while read line; do tag=$(echo "$line" | awk '{print $1}') echo "Deleting old nightly release: $tag" gh release delete "$tag" --yes || echo "Failed to delete $tag" done env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Notification and status notify: name: Notify Build Status runs-on: ubuntu-latest needs: [check-changes, build-nightly] if: always() && needs.check-changes.outputs.should_build == 'true' steps: - name: Report nightly build status run: | echo "Nightly Build Status Report" echo "=========================" echo "Commit: ${{ needs.check-changes.outputs.commit_sha }}" echo "Message: ${{ needs.check-changes.outputs.commit_message }}" echo "Build Status: ${{ needs.build-nightly.result }}" if [ "${{ needs.build-nightly.result }}" = "success" ]; then echo "✅ Nightly build completed successfully" elif [ "${{ needs.build-nightly.result }}" = "failure" ]; then echo "❌ Nightly build failed" echo "Check the build logs for details" else echo "⚠️ Nightly build status: ${{ needs.build-nightly.result }}" fi # Could add webhook notifications here for Discord/Slack etc. # Maintenance tasks during nightly maintenance: name: Nightly Maintenance runs-on: ubuntu-latest needs: [check-changes, validate] if: needs.check-changes.outputs.should_build == 'true' steps: - name: Checkout repository uses: actions/checkout@v4 with: submodules: recursive - name: Install Nushell uses: hustcer/setup-nu@v3 with: version: ${{ needs.validate.outputs.nushell-version }} - name: Check for dependency updates run: | echo "Checking for outdated dependencies..." for plugin in nu_plugin_*; do if [ -d "$plugin" ]; then echo "Checking $plugin..." cd "$plugin" cargo outdated || echo "⚠️ cargo-outdated not available" cd .. fi done continue-on-error: true - name: Generate dependency report run: | echo "Generating dependency report..." echo "# Dependency Status Report - $(date)" > dependency_report.md echo "" >> dependency_report.md for plugin in nu_plugin_*; do if [ -d "$plugin" ]; then echo "## $plugin" >> dependency_report.md echo "" >> dependency_report.md cd "$plugin" echo "\`\`\`" >> ../dependency_report.md cargo tree --depth 1 >> ../dependency_report.md || echo "Failed to generate tree" >> ../dependency_report.md echo "\`\`\`" >> ../dependency_report.md echo "" >> ../dependency_report.md cd .. fi done continue-on-error: true - name: Upload dependency report uses: actions/upload-artifact@v4 with: name: nightly-dependency-report path: dependency_report.md continue-on-error: true