name: Release on: push: tags: - 'v*' workflow_dispatch: inputs: version: description: 'Version to release (e.g., v1.2.3)' required: true type: string prerelease: description: 'Mark as pre-release' type: boolean required: false default: false draft: description: 'Create as draft release' type: boolean required: false default: false env: CARGO_TERM_COLOR: always RUST_BACKTRACE: 1 jobs: # Validate release version and setup validate-release: name: Validate Release runs-on: ubuntu-latest outputs: version: ${{ steps.version.outputs.version }} tag: ${{ steps.version.outputs.tag }} nushell-version: ${{ steps.nushell.outputs.version }} steps: - name: Checkout repository uses: actions/checkout@v4 with: submodules: recursive fetch-depth: 0 - name: Determine version id: version run: | if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then VERSION="${{ github.event.inputs.version }}" else VERSION="${{ github.ref_name }}" fi echo "version=${VERSION#v}" >> $GITHUB_OUTPUT echo "tag=${VERSION}" >> $GITHUB_OUTPUT echo "Release version: ${VERSION}" - name: Install Nushell uses: hustcer/setup-nu@v3 with: version: '0.107.1' - name: Validate nushell version id: nushell 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 for existing release run: | if gh release view "${{ steps.version.outputs.tag }}" >/dev/null 2>&1; then echo "❌ Release ${{ steps.version.outputs.tag }} already exists" exit 1 fi echo "✅ Release tag is available" env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Validate changelog run: | if [ -f "CHANGELOG.md" ]; then if grep -q "${{ steps.version.outputs.version }}" CHANGELOG.md; then echo "✅ Changelog entry found for version ${{ steps.version.outputs.version }}" else echo "⚠️ No changelog entry found for version ${{ steps.version.outputs.version }}" fi else echo "⚠️ No CHANGELOG.md file found" fi # Cross-platform release builds build-release: name: Build Release (${{ matrix.target }}) runs-on: ${{ matrix.os }} needs: validate-release strategy: fail-fast: false matrix: include: # Linux builds - target: linux-amd64 os: ubuntu-latest rust-target: x86_64-unknown-linux-gnu cross-compile: false - target: linux-arm64 os: ubuntu-latest rust-target: aarch64-unknown-linux-gnu cross-compile: true # macOS builds - target: darwin-amd64 os: macos-13 rust-target: x86_64-apple-darwin cross-compile: false - target: darwin-arm64 os: macos-latest rust-target: aarch64-apple-darwin cross-compile: false # Windows builds - target: windows-amd64 os: windows-latest rust-target: x86_64-pc-windows-msvc cross-compile: false 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 }} components: rustfmt, clippy - name: Install Nushell uses: hustcer/setup-nu@v3 with: version: ${{ needs.validate-release.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: release-${{ runner.os }}-${{ matrix.target }}-cargo-${{ hashFiles('**/Cargo.lock') }} restore-keys: | release-${{ runner.os }}-${{ matrix.target }}-cargo- ${{ runner.os }}-${{ matrix.target }}-cargo- - name: Build release binaries run: | echo "Building release binaries for ${{ matrix.target }}..." if [ "${{ matrix.cross-compile }}" = "true" ]; then nu scripts/build_cross.nu --targets ${{ matrix.target }} --verbose else nu scripts/build_all.nu --target ${{ matrix.rust-target }} --verbose fi shell: bash - name: Run tests (native only) if: "!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 }} --release cd .. fi done shell: bash - name: Collect and package release artifacts run: | echo "Collecting release artifacts for ${{ matrix.target }}..." nu scripts/collect_install.nu --platform ${{ matrix.target }} --force echo "Creating release package..." nu scripts/pack_dist.nu --platform ${{ matrix.target }} --force --checksums shell: bash - name: Upload release artifacts uses: actions/upload-artifact@v4 with: name: release-${{ matrix.target }} path: | bin_archives/*${{ matrix.target }}* retention-days: 30 # Create GitHub release create-release: name: Create GitHub Release runs-on: ubuntu-latest needs: [validate-release, build-release] permissions: contents: write outputs: upload_url: ${{ steps.create_release.outputs.upload_url }} release_id: ${{ steps.create_release.outputs.id }} steps: - name: Checkout repository uses: actions/checkout@v4 with: fetch-depth: 0 - name: Install Nushell uses: hustcer/setup-nu@v3 with: version: ${{ needs.validate-release.outputs.nushell-version }} - name: Download all release artifacts uses: actions/download-artifact@v4 with: path: release-artifacts/ - name: Organize release assets run: | echo "Organizing release assets..." mkdir -p release-assets # Copy all archives to release assets find release-artifacts/ -name "*.tar.gz" -o -name "*.zip" | while read file; do cp "$file" release-assets/ done # Copy checksums find release-artifacts/ -name "checksums.txt" | head -1 | while read file; do cp "$file" release-assets/checksums.txt done echo "Release assets:" ls -la release-assets/ - name: Generate release notes id: release_notes run: | echo "Generating release notes..." # Extract changelog for this version if available RELEASE_NOTES="## Nushell Plugins ${{ needs.validate-release.outputs.version }} ### Changes in this Release " if [ -f "CHANGELOG.md" ]; then # Try to extract changelog section for this version awk "/^## \[?${{ needs.validate-release.outputs.version }}\]?/,/^## \[?[0-9]/" CHANGELOG.md | head -n -1 | tail -n +2 >> release_notes.md || true fi # Add generic content if no specific changelog found if [ ! -s release_notes.md ]; then cat >> release_notes.md << 'EOF' This release includes the latest versions of all nushell plugins with bug fixes and improvements. ### Installation #### Quick Install (Unix-like systems) ```bash curl -L https://github.com/${{ github.repository }}/releases/download/${{ needs.validate-release.outputs.tag }}/install.sh | sh ``` #### Manual Install 1. Download the appropriate archive for your platform 2. Extract the archive 3. Run the installation script: `nu install_nu_plugins.nu` ### Platform Support - **Linux**: x86_64 (amd64) and ARM64 - **macOS**: Intel (x86_64) and Apple Silicon (ARM64) - **Windows**: x86_64 (amd64) ### Available Plugins - `nu_plugin_clipboard` - Clipboard integration - `nu_plugin_desktop_notifications` - Desktop notifications - `nu_plugin_hashes` - Hashing utilities - `nu_plugin_highlight` - Syntax highlighting - `nu_plugin_image` - Image processing - `nu_plugin_kcl` - KCL configuration language support - `nu_plugin_port_extension` - Port utilities - `nu_plugin_qr_maker` - QR code generation - `nu_plugin_tera` - Tera templating ### Verification All release assets include SHA256 checksums. Verify downloads using: ```bash sha256sum -c checksums.txt ``` EOF fi cat release_notes.md # Set output for use in create-release step echo "RELEASE_NOTES<> $GITHUB_ENV cat release_notes.md >> $GITHUB_ENV echo "EOF" >> $GITHUB_ENV - name: Create GitHub release id: create_release uses: actions/create-release@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: tag_name: ${{ needs.validate-release.outputs.tag }} release_name: Nushell Plugins ${{ needs.validate-release.outputs.version }} body: ${{ env.RELEASE_NOTES }} draft: ${{ github.event.inputs.draft == 'true' }} prerelease: ${{ github.event.inputs.prerelease == 'true' }} - name: Upload release assets run: | echo "Uploading release assets..." for asset in release-assets/*; do if [ -f "$asset" ]; then echo "Uploading $(basename "$asset")..." gh release upload "${{ needs.validate-release.outputs.tag }}" "$asset" fi done env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Post-release actions post-release: name: Post-Release Actions runs-on: ubuntu-latest needs: [validate-release, create-release] if: always() && needs.create-release.result == 'success' steps: - name: Checkout repository uses: actions/checkout@v4 - name: Notify success run: | echo "🎉 Release ${{ needs.validate-release.outputs.version }} created successfully!" echo "📦 Release URL: https://github.com/${{ github.repository }}/releases/tag/${{ needs.validate-release.outputs.tag }}" - name: Update installation documentation run: | echo "Consider updating:" echo "- README.md with new version information" echo "- Installation instructions" echo "- Compatibility matrix" - name: Create follow-up issue for next release if: "!contains(needs.validate-release.outputs.version, 'rc') && !contains(needs.validate-release.outputs.version, 'beta')" run: | NEXT_VERSION=$(echo "${{ needs.validate-release.outputs.version }}" | awk -F. '{print $1"."($2+1)".0"}') echo "Consider creating planning issue for next release: v$NEXT_VERSION"