diff --git a/.github/workflows/build-and-integration-tests.yml b/.github/workflows/build-and-integration-tests.yml index e94bd47c..280efa7e 100644 --- a/.github/workflows/build-and-integration-tests.yml +++ b/.github/workflows/build-and-integration-tests.yml @@ -13,7 +13,6 @@ env: jobs: build: name: Build and Test - runs-on: ${{ matrix.os }} strategy: fail-fast: false @@ -22,45 +21,39 @@ jobs: - target: x86_64-unknown-linux-gnu os: ubuntu-latest output: cargo-binstall - archive: tgz use-cross: false test: true - target: x86_64-apple-darwin os: macos-latest output: cargo-binstall - archive: zip use-cross: false test: true - target: aarch64-apple-darwin os: macos-latest output: cargo-binstall - archive: zip use-cross: false test: false - target: x86_64-pc-windows-msvc os: windows-latest output: cargo-binstall.exe - archive: zip use-cross: false test: false - target: x86_64-unknown-linux-musl os: ubuntu-latest output: cargo-binstall - archive: tgz use-cross: false test: true - target: armv7-unknown-linux-musleabihf os: ubuntu-20.04 output: cargo-binstall - archive: tgz use-cross: true test: false - target: aarch64-unknown-linux-musl os: ubuntu-latest output: cargo-binstall - archive: tgz use-cross: true test: false + runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v2 @@ -122,30 +115,74 @@ jobs: ./${{ matrix.output }} binstall --manifest-path . --no-confirm cargo-binstall cargo binstall --help - - name: Create archive (tgz, linux) - if: ${{ matrix.os != 'macos-latest' && matrix.os != 'windows-latest' }} - run: tar -czvf cargo-binstall-${{ matrix.target }}.tgz ${{ matrix.output }} - - - name: Create archive (zip, windows) - if: ${{ matrix.os == 'windows-latest' }} - run: tar.exe -a -c -f cargo-binstall-${{ matrix.target }}.zip ${{ matrix.output }} - - - name: Create archive (zip, macos) - if: ${{ matrix.os == 'macos-latest' }} - run: zip cargo-binstall-${{ matrix.target }}.zip ${{ matrix.output }} - - - name: Upload artifacts - uses: actions/upload-artifact@v1 + - name: Upload output + uses: actions/upload-artifact@v3 with: - name: cargo-binstall-${{ matrix.target }}.${{ matrix.archive }} - path: cargo-binstall-${{ matrix.target }}.${{ matrix.archive }} + retention-days: 1 + name: "${{ matrix.target }}.${{ matrix.output }}" + path: "${{ matrix.output }}" - - name: Upload binary to release - if: ${{ startsWith(github.ref, 'refs/tags/v') }} - uses: svenstaro/upload-release-action@v2 + release: + name: Package and release + needs: build + if: ${{ startsWith(github.ref, 'refs/tags/v') }} + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Get outputs + uses: actions/download-artifact@v3 with: - repo_token: ${{ secrets.GITHUB_TOKEN }} - file: cargo-binstall-${{ matrix.target }}.${{ matrix.archive }} - asset_name: cargo-binstall-${{ matrix.target }}.${{ matrix.archive }} - tag: ${{ github.ref }} - overwrite: true + path: outputs/ + + - name: Create archives + shell: bash + run: | + set -euxo pipefail + for o in outputs/*; do + pushd "$o" + + cp ../../LICENSE.txt ../../README.md . + + target=$(basename "$o" | cut -d. -f1) + if grep -qE '(apple|windows)' <<< "$target"; then + zip "../cargo-binstall-${target}.zip" * + else + tar cvf "../cargo-binstall-${target}.tgz" * + fi + + popd + done + + - name: Extract release notes + id: notes + shell: bash + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_REPO: ${{ github.repository }} + release_commit: ${{ github.event.head_commit.message }} + run: | + set -euxo pipefail + release_pr=$(head -n1 <<< "${release_commit:-}" | jq -Rr 'split("[()]"; "")[1] // ""') + if [[ -z "$release_pr" ]]; then + echo "::set-output name=notes_json::null" + exit + fi + + gh \ + pr --repo "$GITHUB_REPO" \ + view "$release_pr" \ + --json body \ + --jq '"::set-output name=notes_json::\((.body | split("### Release notes")[1] // "") | tojson)"' + + - name: Publish release + uses: softprops/action-gh-release@50195ba7f6f93d1ac97ba8332a178e008ad176aa + with: + tag_name: ${{ github.ref }} + name: ${{ github.ref }} + body: ${{ fromJSON(steps.notes.outputs.notes_json) }} + append_body: true + files: | + outputs/cargo-binstall-*.zip + outputs/cargo-binstall-*.tgz + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release-pr.yml b/.github/workflows/release-pr.yml new file mode 100644 index 00000000..cf7e3305 --- /dev/null +++ b/.github/workflows/release-pr.yml @@ -0,0 +1,74 @@ +name: Open a release PR +on: + workflow_dispatch: + inputs: + version: + description: Version to release + required: true + type: string + +jobs: + make-release-pr: + runs-on: ubuntu-latest + steps: + - name: Install cargo-release + uses: taiki-e/install-action@v1 + with: + tool: cargo-release + + - uses: actions/checkout@v2 + with: + ref: main + + - name: Extract info + run: | + set -euxo pipefail + + branch_name="release-${{ inputs.version }}" + echo "branch_name=${branch_name}" >> $GITHUB_ENV + + - name: Make release branch + run: git switch -c "${{ env.branch_name }}" + + - name: Do release + run: | + set -euxo pipefail + git config user.name github-actions + git config user.email github-actions@github.com + cargo release \ + --execute \ + --no-push \ + --no-tag \ + --no-publish \ + --no-confirm \ + --verbose \ + --config release.toml \ + --allow-branch "${{ env.branch_name }}" \ + --dependent-version upgrade \ + "${{ inputs.version }}" + + - name: Push new branch + run: | + set -euxo pipefail + git push origin "${{ env.branch_name }}" + + - name: Create PR + run: | + set -euxo pipefail + + nl=$'\n' + br=$'\n\n' + fence=$'```\n' + ecnef=$'\n```' + + title="release: v${{ inputs.version }}" + body_intro="This is a release PR for version **${{ inputs.version }}**." + body_merge="**Use squash merge.** Upon merging, this will automatically build the CLI and create a GitHub release. You still need to manually publish the cargo crate." + body_pub="${fence}$ cd ${{ env.crate_path }}${nl}$ cargo publish${ecnef}" + body_notes="---${br}_Edit release notes into the section below:_${br}${nl}### Release notes" + + body="${body_intro}${br}${body_merge}${br}${body_pub}${br}${body_notes}${br}" + + gh pr create --title "$title" --body "$body" --base main --head "${{ env.branch_name }}" --label "release" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release-tag.yml b/.github/workflows/release-tag.yml new file mode 100644 index 00000000..14aa604a --- /dev/null +++ b/.github/workflows/release-tag.yml @@ -0,0 +1,32 @@ +name: Tag a release +on: + push: + branches: + - main + tags-ignore: + - "*" + +jobs: + make-tag: + runs-on: ubuntu-latest + # the commit message will look like: `release: v{version} (#{pr-number})` + if: "startsWith(github.event.head_commit.message, 'release: v')" + steps: + - name: Extract tag from commit message + env: + COMMIT_MESSAGE: ${{ github.event.head_commit.message }} + run: | + set -euxo pipefail + + message="$(head -n1 <<< "$COMMIT_MESSAGE")" + version="$(cut -d ' ' -f 2 <<< "${message}")" + echo "CUSTOM_TAG=${version}" >> $GITHUB_ENV + + - uses: actions/checkout@v2 + - name: Push release tag + id: tag_version + uses: mathieudutour/github-tag-action@v6.0 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + custom_tag: ${{ env.CUSTOM_TAG }} + tag_prefix: '' diff --git a/Cargo.toml b/Cargo.toml index 5706941e..2656b7ff 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -75,6 +75,9 @@ mimalloc = ["dep:mimalloc"] [dev-dependencies] env_logger = "0.9.0" +[build-dependencies] +embed-resource = "1.6.1" + [profile.release] opt-level = "z" lto = true diff --git a/build.rs b/build.rs index a6f29869..961d0241 100644 --- a/build.rs +++ b/build.rs @@ -1,5 +1,7 @@ -// Fetch build target and define this for the compiler fn main() { + embed_resource::compile("manifest.rc"); + + // Fetch build target and define this for the compiler println!( "cargo:rustc-env=TARGET={}", std::env::var("TARGET").unwrap() diff --git a/manifest.rc b/manifest.rc new file mode 100644 index 00000000..d648a5c7 --- /dev/null +++ b/manifest.rc @@ -0,0 +1,2 @@ +#define RT_MANIFEST 24 +1 RT_MANIFEST "windows.manifest" diff --git a/release.toml b/release.toml new file mode 100644 index 00000000..4c308c4a --- /dev/null +++ b/release.toml @@ -0,0 +1,16 @@ +pre-release-commit-message = "release: v{{version}}" +tag-prefix = "cli-" +tag-message = "cargo-binstall {{version}}" + +# We wait until the release CI is done before publishing, +# because publishing is irreversible, but a release can be +# reverted a lot more easily. +publish = false + +[[pre-release-replacements]] +file = "windows.manifest" +search = "^ version=\"[\\d.]+[.]0\"" +replace = " version=\"{{version}}.0\"" +prerelease = false +max = 1 + diff --git a/windows.manifest b/windows.manifest new file mode 100644 index 00000000..d72ab3ca --- /dev/null +++ b/windows.manifest @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + true + UTF-8 + SegmentHeap + + +