name: CD
on:
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+'
env:
CARGO_TERM_COLOR: always
BINARY_NAME: shuire
jobs:
build:
name: Build ${{ matrix.target }}
runs-on: ${{ matrix.os }}
permissions:
contents: write
strategy:
fail-fast: false
matrix:
include:
- os: macos-latest
os-name: macos
target: x86_64-apple-darwin
architecture: x86_64
binary-postfix: ""
use-cross: false
npm-package: shuire-darwin-x64
- os: macos-latest
os-name: macos
target: aarch64-apple-darwin
architecture: arm64
binary-postfix: ""
use-cross: false
npm-package: shuire-darwin-arm64
- os: ubuntu-latest
os-name: linux
target: x86_64-unknown-linux-gnu
architecture: x86_64
binary-postfix: ""
use-cross: false
npm-package: shuire-linux-x64
- os: windows-latest
os-name: windows
target: x86_64-pc-windows-msvc
architecture: x86_64
binary-postfix: ".exe"
use-cross: false
npm-package: shuire-win32-x64
- os: ubuntu-latest
os-name: linux
target: aarch64-unknown-linux-gnu
architecture: arm64
binary-postfix: ""
use-cross: true
npm-package: shuire-linux-arm64
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- uses: Swatinem/rust-cache@v2
with:
key: ${{ matrix.target }}
- name: Install cross
if: matrix.use-cross
uses: taiki-e/install-action@v2
with:
tool: cross
- name: Build
shell: bash
run: |
if [[ "${{ matrix.use-cross }}" == "true" ]]; then
cross build --release --locked --target ${{ matrix.target }}
else
cargo build --release --locked --target ${{ matrix.target }}
fi
- name: Strip binary
if: runner.os != 'Windows'
shell: bash
run: |
BIN=target/${{ matrix.target }}/release/${BINARY_NAME}${{ matrix.binary-postfix }}
if [[ "${{ matrix.target }}" == aarch64-unknown-linux-gnu ]]; then
sudo apt-get update && sudo apt-get install -y binutils-aarch64-linux-gnu
aarch64-linux-gnu-strip "$BIN" || true
else
strip "$BIN" || true
fi
- name: Package tarball
shell: bash
run: |
cd target/${{ matrix.target }}/release
BIN=${BINARY_NAME}${{ matrix.binary-postfix }}
VERSION=${GITHUB_REF#refs/tags/}
RELEASE_NAME=${BINARY_NAME}-${VERSION}-${{ matrix.os-name }}-${{ matrix.architecture }}
tar czvf "${RELEASE_NAME}.tar.gz" "$BIN"
if [[ "${{ runner.os }}" == "Windows" ]]; then
certutil -hashfile "${RELEASE_NAME}.tar.gz" sha256 | grep -E "[A-Fa-f0-9]{64}" > "${RELEASE_NAME}.sha256"
else
shasum -a 256 "${RELEASE_NAME}.tar.gz" > "${RELEASE_NAME}.sha256"
fi
- name: Upload to GitHub Release
uses: softprops/action-gh-release@v2
with:
files: |
target/${{ matrix.target }}/release/${{ env.BINARY_NAME }}-*.tar.gz
target/${{ matrix.target }}/release/${{ env.BINARY_NAME }}-*.sha256
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Stage binary into npm platform package
shell: bash
env:
VERSION: ${{ github.ref_name }}
PKG_DIR: npm/${{ matrix.npm-package }}
TARGET: ${{ matrix.target }}
BIN_POSTFIX: ${{ matrix.binary-postfix }}
IS_WINDOWS: ${{ runner.os == 'Windows' }}
run: |
VERSION=${VERSION#v}
BIN=${BINARY_NAME}${BIN_POSTFIX}
cp "target/${TARGET}/release/${BIN}" "${PKG_DIR}/bin/${BIN}"
if [[ "${IS_WINDOWS}" != "true" ]]; then
chmod +x "${PKG_DIR}/bin/${BIN}"
fi
node -e "
const fs=require('fs');
const p=process.env.PKG_DIR + '/package.json';
const j=JSON.parse(fs.readFileSync(p));
j.version = process.env.VERSION;
fs.writeFileSync(p, JSON.stringify(j, null, 2) + '\n');
"
- uses: actions/setup-node@v4
with:
node-version: "20"
registry-url: "https://registry.npmjs.org"
- name: Publish platform package
shell: bash
working-directory: npm/${{ matrix.npm-package }}
run: npm publish --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
publish-npm-meta:
name: Publish shuire (npm meta)
runs-on: ubuntu-latest
needs: build
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
registry-url: "https://registry.npmjs.org"
- name: Set version in meta package
shell: bash
run: |
VERSION=${GITHUB_REF#refs/tags/v}
node -e "
const fs=require('fs');
const p='npm/shuire/package.json';
const j=JSON.parse(fs.readFileSync(p));
j.version='${VERSION}';
for (const k of Object.keys(j.optionalDependencies||{})) {
j.optionalDependencies[k] = '${VERSION}';
}
fs.writeFileSync(p, JSON.stringify(j, null, 2)+'\n');
"
- name: Publish meta package
working-directory: npm/shuire
run: npm publish --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
publish-cargo:
name: Publish to crates.io
runs-on: ubuntu-latest
needs: build
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- run: cargo publish --locked
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
update-homebrew-tap:
name: Update Homebrew tap
runs-on: ubuntu-latest
needs: build
permissions:
contents: read
steps:
- name: Download sha256 files from release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
VERSION: ${{ github.ref_name }}
run: |
for suffix in macos-arm64 macos-x86_64 linux-x86_64 linux-arm64; do
gh release download "$VERSION" \
--repo sachaos/shuire \
--pattern "shuire-${VERSION}-${suffix}.sha256" \
--output "${suffix}.sha256"
echo "SHA_${suffix//-/_}=$(awk '{print $1}' ${suffix}.sha256)" >> "$GITHUB_ENV"
done
- name: Clone homebrew-tap
env:
HOMEBREW_TAP_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }}
run: |
git clone https://x-access-token:${HOMEBREW_TAP_TOKEN}@github.com/sachaos/homebrew-tap.git tap
- name: Generate formula
env:
VERSION: ${{ github.ref_name }}
run: |
python3 - <<'PYEOF'
import os
version = os.environ['VERSION']
ver_num = version.lstrip('v')
sha_macos_arm64 = os.environ['SHA_macos_arm64']
sha_macos_x64 = os.environ['SHA_macos_x86_64']
sha_linux_x64 = os.environ['SHA_linux_x86_64']
sha_linux_arm64 = os.environ['SHA_linux_arm64']
formula = f"""# typed: false
# frozen_string_literal: true
# This file is updated automatically by shuire's release CI. DO NOT EDIT by hand.
class Shuire < Formula
desc "Vim-like TUI git diff viewer"
homepage "https://github.com/sachaos/shuire"
version "{ver_num}"
on_macos do
if Hardware::CPU.arm?
url "https://github.com/sachaos/shuire/releases/download/{version}/shuire-{version}-macos-arm64.tar.gz"
sha256 "{sha_macos_arm64}"
def install
bin.install "shuire"
end
end
if Hardware::CPU.intel?
url "https://github.com/sachaos/shuire/releases/download/{version}/shuire-{version}-macos-x86_64.tar.gz"
sha256 "{sha_macos_x64}"
def install
bin.install "shuire"
end
end
end
on_linux do
if Hardware::CPU.intel?
url "https://github.com/sachaos/shuire/releases/download/{version}/shuire-{version}-linux-x86_64.tar.gz"
sha256 "{sha_linux_x64}"
def install
bin.install "shuire"
end
end
if Hardware::CPU.arm? && Hardware::CPU.is_64_bit?
url "https://github.com/sachaos/shuire/releases/download/{version}/shuire-{version}-linux-arm64.tar.gz"
sha256 "{sha_linux_arm64}"
def install
bin.install "shuire"
end
end
end
test do
system "#{{bin}}/shuire", "--version"
end
end
"""
# Strip the common leading indentation introduced by the heredoc
import textwrap
formula = textwrap.dedent(formula).lstrip('\n')
with open('tap/Formula/shuire.rb', 'w') as f:
f.write(formula)
PYEOF
- name: Commit and push
env:
VERSION: ${{ github.ref_name }}
run: |
cd tap
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add Formula/shuire.rb
git commit -m "Update shuire to ${VERSION}"
git push