From 6c07bc10e2cf3445e098089d184b86463c0a330a Mon Sep 17 00:00:00 2001 From: Justin Ma Date: Sat, 28 May 2022 10:41:47 +0800 Subject: [PATCH] feat: Refactor and optimize the github release workflow: deliver binary package for more targets (#5649) --- .github/workflows/release-pkg.nu | 155 +++++++++ .github/workflows/release.yml | 517 ++++++------------------------- 2 files changed, 243 insertions(+), 429 deletions(-) create mode 100755 .github/workflows/release-pkg.nu diff --git a/.github/workflows/release-pkg.nu b/.github/workflows/release-pkg.nu new file mode 100755 index 000000000..1aa397e24 --- /dev/null +++ b/.github/workflows/release-pkg.nu @@ -0,0 +1,155 @@ +#!/usr/bin/env nu + +# Created: 2022/05/26 19:05:20 +# Description: +# A script to do the github release task, need nushell to be installed. +# REF: +# 1. https://github.com/volks73/cargo-wix + +# The main binary file to be released +let bin = 'nu' +let os = $env.OS +let target = $env.TARGET +# Repo source dir like `/home/runner/work/nushell/nushell` +let src = $env.GITHUB_WORKSPACE +let flags = $env.TARGET_RUSTFLAGS +let dist = $'($env.GITHUB_WORKSPACE)/output' +let version = (open Cargo.toml | get package.version) + +# $env + +$'(char nl)Packaging ($bin) v($version) for ($target) in ($src)...'; hr-line -b +if not ('Cargo.lock' | path exists) { cargo generate-lockfile } + +$'Start building ($bin)...'; hr-line + +# ---------------------------------------------------------------------------- +# Build for Ubuntu and macOS +# ---------------------------------------------------------------------------- +if $os in ['ubuntu-latest', 'macos-latest'] { + if $os == 'ubuntu-latest' { + sudo apt-get install libxcb-composite0-dev -y + } + if $target == 'aarch64-unknown-linux-gnu' { + sudo apt-get install gcc-aarch64-linux-gnu -y + let-env CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER = 'aarch64-linux-gnu-gcc' + cargo-build-nu $flags + } else if $target == 'armv7-unknown-linux-gnueabihf' { + sudo apt-get install pkg-config gcc-arm-linux-gnueabihf -y + let-env CARGO_TARGET_ARMV7_UNKNOWN_LINUX_GNUEABIHF_LINKER = 'arm-linux-gnueabihf-gcc' + cargo-build-nu $flags + } else { + # musl-tools to fix 'Failed to find tool. Is `musl-gcc` installed?' + # Actually just for x86_64-unknown-linux-musl target + sudo apt install musl-tools -y + cargo-build-nu $flags + } +} + +# ---------------------------------------------------------------------------- +# Build for Windows without static-link-openssl feature +# ---------------------------------------------------------------------------- +if $os in ['windows-latest'] { + if ($flags | str trim | empty?) { + cargo build --release --all --target $target --features=extra + } else { + cargo build --release --all --target $target --features=extra $flags + } +} + +# ---------------------------------------------------------------------------- +# Prepare for the release archive +# ---------------------------------------------------------------------------- +let suffix = if $os == 'windows-latest' { '.exe' } +# nu, nu_plugin_* were all included +let executable = $'target/($target)/release/($bin)*($suffix)' +$'Current executable file: ($executable)' + +cd $src; mkdir $dist; +rm -rf $'target/($target)/release/*.d' $'target/($target)/release/nu_pretty_hex*' +$'(char nl)All executable files:'; hr-line +ls -f $executable + +$'(char nl)Copying release files...'; hr-line +cp -v README.release.txt $'($dist)/README.txt' +[LICENSE $executable] | each {|it| cp -rv $it $dist } | flatten + +$'(char nl)Check binary release version detail:'; hr-line +let ver = if $os == 'windows-latest' { + (do -i { ./output/nu.exe -c 'version' }) | str collect +} else { + (do -i { ./output/nu -c 'version' }) | str collect +} +if ($ver | str trim | empty?) { + $'(ansi r)Incompatible nu binary...(ansi reset)' +} else { $ver } + +# ---------------------------------------------------------------------------- +# Create a release archive and send it to output for the following steps +# ---------------------------------------------------------------------------- +cd $dist; $'(char nl)Creating release archive...'; hr-line +if $os in ['ubuntu-latest', 'macos-latest'] { + + $'(char nl)(ansi g)Archive contents:(ansi reset)'; hr-line; ls + + let archive = $'($dist)/($bin)-($version)-($target).tar.gz' + tar czf $archive * + print $'archive: ---> ($archive)'; ls $archive + echo $'::set-output name=archive::($archive)' + +} else if $os == 'windows-latest' { + + let releaseStem = $'($bin)-($version)-($target)' + + $'(char nl)Download less related stuffs...'; hr-line + curl https://github.com/jftuga/less-Windows/releases/download/less-v590/less.exe -o $'($dist)\less.exe' + curl https://raw.githubusercontent.com/jftuga/less-Windows/master/LICENSE -o $'($dist)\LICENSE-for-less.txt' + + # Create Windows msi release package + if (get-env _EXTRA_) == 'msi' { + + let wixRelease = $'($src)/target/wix/($releaseStem).msi' + $'(char nl)Start creating Windows msi package...' + cd $src; hr-line + # Wix need the binaries be stored in target/release/ + cp -r $'($dist)/*' target/release/ + cargo install cargo-wix --version 0.3.2 + cargo wix --no-build --nocapture --package nu --output $wixRelease + echo $'::set-output name=archive::($wixRelease)' + + } else { + + $'(char nl)(ansi g)Archive contents:(ansi reset)'; hr-line; ls + let archive = $'($dist)/($releaseStem).zip' + 7z a $archive * + print $'archive: ---> ($archive)'; + let pkg = (ls -f $archive | get name) + if not ($pkg | empty?) { + echo $'::set-output name=archive::($pkg | get 0)' + } + } +} + +def 'cargo-build-nu' [ options: string ] { + if ($options | str trim | empty?) { + cargo build --release --all --target $target --features=extra,static-link-openssl + } else { + cargo build --release --all --target $target --features=extra,static-link-openssl $options + } +} + +# Print a horizontal line marker +def 'hr-line' [ + --blank-line(-b): bool +] { + print $'(ansi g)---------------------------------------------------------------------------->(ansi reset)' + if $blank-line { char nl } +} + +# Get the specified env key's value or '' +def 'get-env' [ + key: string # The key to get it's env value + default: string = '' # The default value for an empty env +] { + $env | get -i $key | default $default +} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index adc3f8fca..d8553495d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,3 +1,7 @@ +# +# REF: +# 1. https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstrategymatrixinclude +# name: Create Release Draft on: @@ -5,434 +9,89 @@ on: push: tags: ["[0-9]+.[0-9]+.[0-9]+*"] +defaults: + run: + shell: bash + jobs: - linux: - name: Build Linux - runs-on: ubuntu-latest + all: + name: All + + strategy: + matrix: + target: + - aarch64-apple-darwin + - x86_64-apple-darwin + - x86_64-pc-windows-msvc + - x86_64-unknown-linux-gnu + - x86_64-unknown-linux-musl + - aarch64-unknown-linux-gnu + - armv7-unknown-linux-gnueabihf + extra: ['bin'] + include: + - target: aarch64-apple-darwin + os: macos-latest + target_rustflags: '' + - target: x86_64-apple-darwin + os: macos-latest + target_rustflags: '' + - target: x86_64-pc-windows-msvc + extra: 'bin' + os: windows-latest + target_rustflags: '' + - target: x86_64-pc-windows-msvc + extra: msi + os: windows-latest + target_rustflags: '' + - target: x86_64-unknown-linux-gnu + os: ubuntu-latest + target_rustflags: '' + - target: x86_64-unknown-linux-musl + os: ubuntu-latest + target_rustflags: '' + - target: aarch64-unknown-linux-gnu + os: ubuntu-latest + target_rustflags: '' + - target: armv7-unknown-linux-gnueabihf + os: ubuntu-latest + target_rustflags: '' + + runs-on: ${{matrix.os}} + steps: - - name: Check out code - uses: actions/checkout@v2 - - - name: Install libxcb - run: sudo apt-get install libxcb-composite0-dev - - - name: Set up cargo - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - override: true - - - name: Build - uses: actions-rs/cargo@v1 - with: - command: build - args: --release --all --features=extra,static-link-openssl - - # - name: Strip binaries (nu) - # run: strip target/release/nu - - # - name: Strip binaries (nu_plugin_inc) - # run: strip target/release/nu_plugin_inc - - # - name: Strip binaries (nu_plugin_match) - # run: strip target/release/nu_plugin_match - - # - name: Strip binaries (nu_plugin_textview) - # run: strip target/release/nu_plugin_textview - - # - name: Strip binaries (nu_plugin_binaryview) - # run: strip target/release/nu_plugin_binaryview - - # - name: Strip binaries (nu_plugin_chart_bar) - # run: strip target/release/nu_plugin_chart_bar - - # - name: Strip binaries (nu_plugin_chart_line) - # run: strip target/release/nu_plugin_chart_line - - # - name: Strip binaries (nu_plugin_from_bson) - # run: strip target/release/nu_plugin_from_bson - - # - name: Strip binaries (nu_plugin_from_sqlite) - # run: strip target/release/nu_plugin_from_sqlite - - # - name: Strip binaries (nu_plugin_from_mp4) - # run: strip target/release/nu_plugin_from_mp4 - - # - name: Strip binaries (nu_plugin_query_json) - # run: strip target/release/nu_plugin_query_json - - # - name: Strip binaries (nu_plugin_s3) - # run: strip target/release/nu_plugin_s3 - - # - name: Strip binaries (nu_plugin_selector) - # run: strip target/release/nu_plugin_selector - - # - name: Strip binaries (nu_plugin_start) - # run: strip target/release/nu_plugin_start - - # - name: Strip binaries (nu_plugin_to_bson) - # run: strip target/release/nu_plugin_to_bson - - # - name: Strip binaries (nu_plugin_to_sqlite) - # run: strip target/release/nu_plugin_to_sqlite - - # - name: Strip binaries (nu_plugin_tree) - # run: strip target/release/nu_plugin_tree - - # - name: Strip binaries (nu_plugin_xpath) - # run: strip target/release/nu_plugin_xpath - - - name: Create output directory - run: mkdir output - - - name: Copy files to output - run: | - cp target/release/nu target/release/nu_plugin_* output/ - cp README.release.txt output/README.txt - cp LICENSE output/LICENSE - rm output/*.d - - - name: Upload artifact - uses: actions/upload-artifact@v2 - with: - name: linux - path: output/* - - macos: - name: Build macOS - runs-on: macos-latest - steps: - - name: Check out code - uses: actions/checkout@v2 - - - name: Set up cargo - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - override: true - - - name: Build - uses: actions-rs/cargo@v1 - with: - command: build - args: --release --all --features=extra,static-link-openssl - - # - name: Strip binaries (nu) - # run: strip target/release/nu - - # - name: Strip binaries (nu_plugin_inc) - # run: strip target/release/nu_plugin_inc - - # - name: Strip binaries (nu_plugin_match) - # run: strip target/release/nu_plugin_match - - # - name: Strip binaries (nu_plugin_textview) - # run: strip target/release/nu_plugin_textview - - # - name: Strip binaries (nu_plugin_binaryview) - # run: strip target/release/nu_plugin_binaryview - - # - name: Strip binaries (nu_plugin_chart_bar) - # run: strip target/release/nu_plugin_chart_bar - - # - name: Strip binaries (nu_plugin_chart_line) - # run: strip target/release/nu_plugin_chart_line - - # - name: Strip binaries (nu_plugin_from_bson) - # run: strip target/release/nu_plugin_from_bson - - # - name: Strip binaries (nu_plugin_from_sqlite) - # run: strip target/release/nu_plugin_from_sqlite - - # - name: Strip binaries (nu_plugin_from_mp4) - # run: strip target/release/nu_plugin_from_mp4 - - # - name: Strip binaries (nu_plugin_query_json) - # run: strip target/release/nu_plugin_query_json - - # - name: Strip binaries (nu_plugin_s3) - # run: strip target/release/nu_plugin_s3 - - # - name: Strip binaries (nu_plugin_selector) - # run: strip target/release/nu_plugin_selector - - # - name: Strip binaries (nu_plugin_start) - # run: strip target/release/nu_plugin_start - - # - name: Strip binaries (nu_plugin_to_bson) - # run: strip target/release/nu_plugin_to_bson - - # - name: Strip binaries (nu_plugin_to_sqlite) - # run: strip target/release/nu_plugin_to_sqlite - - # - name: Strip binaries (nu_plugin_tree) - # run: strip target/release/nu_plugin_tree - - # - name: Strip binaries (nu_plugin_xpath) - # run: strip target/release/nu_plugin_xpath - - - name: Create output directory - run: mkdir output - - - name: Copy files to output - run: | - cp target/release/nu target/release/nu_plugin_* output/ - cp README.release.txt output/README.txt - cp LICENSE output/LICENSE - rm output/*.d - - - name: Upload artifact - uses: actions/upload-artifact@v2 - with: - name: macos - path: output/* - - windows: - name: Build Windows - runs-on: windows-latest - steps: - - name: Check out code - uses: actions/checkout@v2 - - - name: Set up cargo - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - override: true - - - name: Add cargo-wix subcommand - uses: actions-rs/cargo@v1 - with: - command: install - args: cargo-wix --version 0.3.1 - - - name: Build - uses: actions-rs/cargo@v1 - with: - command: build - args: --release --all --features=extra,static-link-openssl - - # - name: Strip binaries (nu.exe) - # run: strip target/release/nu.exe - - # - name: Strip binaries (nu_plugin_inc.exe) - # run: strip target/release/nu_plugin_inc.exe - - # - name: Strip binaries (nu_plugin_match.exe) - # run: strip target/release/nu_plugin_match.exe - - # - name: Strip binaries (nu_plugin_textview.exe) - # run: strip target/release/nu_plugin_textview.exe - - # - name: Strip binaries (nu_plugin_binaryview.exe) - # run: strip target/release/nu_plugin_binaryview.exe - - # - name: Strip binaries (nu_plugin_chart_bar.exe) - # run: strip target/release/nu_plugin_chart_bar.exe - - # - name: Strip binaries (nu_plugin_chart_line.exe) - # run: strip target/release/nu_plugin_chart_line.exe - - # - name: Strip binaries (nu_plugin_from_bson.exe) - # run: strip target/release/nu_plugin_from_bson.exe - - # - name: Strip binaries (nu_plugin_from_sqlite.exe) - # run: strip target/release/nu_plugin_from_sqlite.exe - - # - name: Strip binaries (nu_plugin_from_mp4.exe) - # run: strip target/release/nu_plugin_from_mp4.exe - - # - name: Strip binaries (nu_plugin_query_json.exe) - # run: strip target/release/nu_plugin_query_json.exe - - # - name: Strip binaries (nu_plugin_s3.exe) - # run: strip target/release/nu_plugin_s3.exe - - # - name: Strip binaries (nu_plugin_selector.exe) - # run: strip target/release/nu_plugin_selector.exe - - # - name: Strip binaries (nu_plugin_start.exe) - # run: strip target/release/nu_plugin_start.exe - - # - name: Strip binaries (nu_plugin_to_bson.exe) - # run: strip target/release/nu_plugin_to_bson.exe - - # - name: Strip binaries (nu_plugin_to_sqlite.exe) - # run: strip target/release/nu_plugin_to_sqlite.exe - - # - name: Strip binaries (nu_plugin_tree.exe) - # run: strip target/release/nu_plugin_tree.exe - - # - name: Strip binaries (nu_plugin_xpath.exe) - # run: strip target/release/nu_plugin_xpath.exe - - - name: Create output directory - run: mkdir output - - - name: Download Less Binary - run: Invoke-WebRequest -Uri "https://github.com/jftuga/less-Windows/releases/download/less-v562.0/less.exe" -OutFile "target\release\less.exe" - - - name: Download Less License - run: Invoke-WebRequest -Uri "https://raw.githubusercontent.com/jftuga/less-Windows/master/LICENSE" -OutFile "target\release\LICENSE-for-less.txt" - - - name: Copy files to output - run: | - cp target\release\nu.exe output\ - cp LICENSE output\ - cp target\release\LICENSE-for-less.txt output\ - cp target\release\nu_plugin_*.exe output\ - cp README.release.txt output\README.txt - cp target\release\less.exe output\ - # Note: If the version of `less.exe` needs to be changed, update this URL - # Similarly, if `less.exe` is checked into the repo, copy from the local path here - # moved this stuff down to create wix after we download less - - - name: Create msi with wix - uses: actions-rs/cargo@v1 - with: - command: wix - args: --no-build --nocapture --output target\wix\nushell-windows.msi - - - name: Upload installer - uses: actions/upload-artifact@v2 - with: - name: windows-installer - path: target\wix\nushell-windows.msi - - - name: Upload zip - uses: actions/upload-artifact@v2 - with: - name: windows-zip - path: output\* - - release: - name: Publish Release - runs-on: ubuntu-latest - needs: - - linux - - macos - - windows - steps: - - name: Check out code - uses: actions/checkout@v2 - - - name: Determine Release Info - id: info - env: - GITHUB_REF: ${{ github.ref }} - run: | - VERSION=${GITHUB_REF##*/} - MAJOR=${VERSION%%.*} - MINOR=${VERSION%.*} - MINOR=${MINOR#*.} - PATCH=${VERSION##*.} - echo "::set-output name=version::${VERSION}" - echo "::set-output name=linuxdir::nu_${MAJOR}_${MINOR}_${PATCH}_linux" - echo "::set-output name=macosdir::nu_${MAJOR}_${MINOR}_${PATCH}_macOS" - echo "::set-output name=windowsdir::nu_${MAJOR}_${MINOR}_${PATCH}_windows" - echo "::set-output name=innerdir::nushell-${VERSION}" - - - name: Create Release Draft - id: create_release - uses: actions/create-release@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - tag_name: ${{ github.ref }} - release_name: ${{ steps.info.outputs.version }} Release - draft: true - - - name: Create Linux Directory - run: mkdir -p ${{ steps.info.outputs.linuxdir }}/${{ steps.info.outputs.innerdir }} - - - name: Download Linux Artifacts - uses: actions/download-artifact@v2 - with: - name: linux - path: ${{ steps.info.outputs.linuxdir }}/${{ steps.info.outputs.innerdir }} - - - name: Restore Linux File Modes - run: | - chmod 755 ${{ steps.info.outputs.linuxdir }}/${{ steps.info.outputs.innerdir }}/nu* - - - name: Create Linux tarball - run: tar -zcvf ${{ steps.info.outputs.linuxdir }}.tar.gz ${{ steps.info.outputs.linuxdir }} - - - name: Upload Linux Artifact - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: ./${{ steps.info.outputs.linuxdir }}.tar.gz - asset_name: ${{ steps.info.outputs.linuxdir }}.tar.gz - asset_content_type: application/gzip - - - name: Create macOS Directory - run: mkdir -p ${{ steps.info.outputs.macosdir }}/${{ steps.info.outputs.innerdir }} - - - name: Download macOS Artifacts - uses: actions/download-artifact@v2 - with: - name: macos - path: ${{ steps.info.outputs.macosdir }}/${{ steps.info.outputs.innerdir }} - - - name: Restore macOS File Modes - run: chmod 755 ${{ steps.info.outputs.macosdir }}/${{ steps.info.outputs.innerdir }}/nu* - - - name: Create macOS Archive - run: zip -r ${{ steps.info.outputs.macosdir }}.zip ${{ steps.info.outputs.macosdir }} - - - name: Upload macOS Artifact - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: ./${{ steps.info.outputs.macosdir }}.zip - asset_name: ${{ steps.info.outputs.macosdir }}.zip - asset_content_type: application/zip - - - name: Create Windows Directory - run: mkdir -p ${{ steps.info.outputs.windowsdir }}/${{ steps.info.outputs.innerdir }} - - - name: Download Windows zip - uses: actions/download-artifact@v2 - with: - name: windows-zip - path: ${{ steps.info.outputs.windowsdir }}/${{ steps.info.outputs.innerdir }} - - - name: Show Windows Artifacts - run: ls -la ${{ steps.info.outputs.windowsdir }}/${{ steps.info.outputs.innerdir }} - - - name: Create macOS Archive - run: zip -r ${{ steps.info.outputs.windowsdir }}.zip ${{ steps.info.outputs.windowsdir }} - - - name: Upload Windows zip - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: ./${{ steps.info.outputs.windowsdir }}.zip - asset_name: ${{ steps.info.outputs.windowsdir }}.zip - asset_content_type: application/zip - - - name: Download Windows installer - uses: actions/download-artifact@v2 - with: - name: windows-installer - path: ./ - - - name: Upload Windows installer - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: ./nushell-windows.msi - asset_name: ${{ steps.info.outputs.windowsdir }}.msi - asset_content_type: application/x-msi + - uses: actions/checkout@v3.0.2 + + - name: Install Rust Toolchain Components + uses: actions-rs/toolchain@v1.0.6 + with: + override: true + profile: minimal + toolchain: stable + target: ${{ matrix.target }} + + - name: Setup Nushell + uses: hustcer/setup-nu@v1 + with: + version: 0.63.0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Release Nu Binary + id: nu + run: nu .github/workflows/release-pkg.nu + env: + OS: ${{ matrix.os }} + REF: ${{ github.ref }} + TARGET: ${{ matrix.target }} + _EXTRA_: ${{ matrix.extra }} + TARGET_RUSTFLAGS: ${{ matrix.target_rustflags }} + + # REF: https://github.com/marketplace/actions/gh-release + - name: Publish Archive + uses: softprops/action-gh-release@v1 + if: ${{ startsWith(github.ref, 'refs/tags/') }} + with: + draft: true + files: ${{ steps.nu.outputs.archive }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}