Terminal Markdown previewer — GUI-like experience.
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

chore: release workflows

RivoLink ceb0e90e 2205cdd4

+363
+129
.github/workflows/release-build.yml
··· 1 + name: Release Build 2 + 3 + on: 4 + push: 5 + tags: 6 + - "*.*.*" 7 + 8 + permissions: 9 + contents: write 10 + 11 + jobs: 12 + build: 13 + runs-on: ${{ matrix.os }} 14 + strategy: 15 + fail-fast: false 16 + matrix: 17 + include: 18 + - os: ubuntu-latest 19 + artifact_name: leaf-linux-x86_64 20 + binary_path: target/release/leaf 21 + target: "" 22 + - os: ubuntu-latest 23 + artifact_name: leaf-linux-arm64 24 + binary_path: target/aarch64-unknown-linux-gnu/release/leaf 25 + target: aarch64-unknown-linux-gnu 26 + - os: macos-latest 27 + artifact_name: leaf-macos-x86_64 28 + binary_path: target/x86_64-apple-darwin/release/leaf 29 + target: x86_64-apple-darwin 30 + - os: macos-latest 31 + artifact_name: leaf-macos-arm64 32 + binary_path: target/aarch64-apple-darwin/release/leaf 33 + target: aarch64-apple-darwin 34 + - os: windows-latest 35 + artifact_name: leaf-windows-x86_64.exe 36 + binary_path: target/release/leaf.exe 37 + target: "" 38 + - os: ubuntu-latest 39 + artifact_name: leaf-android-arm64 40 + binary_path: target/aarch64-linux-android/release/leaf 41 + target: aarch64-linux-android 42 + 43 + steps: 44 + - name: Checkout 45 + uses: actions/checkout@v4 46 + 47 + - name: Validate tag format 48 + shell: bash 49 + run: | 50 + [[ "${GITHUB_REF_NAME}" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] 51 + 52 + - name: Setup Rust toolchain 53 + uses: dtolnay/rust-toolchain@stable 54 + 55 + - name: Setup Rust target 56 + if: matrix.target != '' 57 + run: rustup target add ${{ matrix.target }} 58 + 59 + - name: Setup Android NDK 60 + if: matrix.target == 'aarch64-linux-android' 61 + uses: nttld/setup-ndk@v1 62 + with: 63 + ndk-version: r26d 64 + 65 + - name: Setup Linux ARM64 linker 66 + if: matrix.target == 'aarch64-unknown-linux-gnu' 67 + run: | 68 + sudo apt-get update 69 + sudo apt-get install -y gcc-aarch64-linux-gnu 70 + 71 + - name: Configure Android linker 72 + if: matrix.target == 'aarch64-linux-android' 73 + run: | 74 + echo "${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/bin" >> "$GITHUB_PATH" 75 + echo "CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER=aarch64-linux-android21-clang" >> "$GITHUB_ENV" 76 + 77 + - name: Configure Linux ARM64 linker 78 + if: matrix.target == 'aarch64-unknown-linux-gnu' 79 + run: | 80 + echo "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc" >> "$GITHUB_ENV" 81 + 82 + - name: Build release 83 + if: matrix.target == '' 84 + run: cargo build --release 85 + 86 + - name: Build Android release 87 + if: matrix.target == 'aarch64-linux-android' 88 + run: cargo build --release --target aarch64-linux-android 89 + 90 + - name: Build targeted release 91 + if: matrix.target != '' && matrix.target != 'aarch64-linux-android' 92 + run: cargo build --release --target ${{ matrix.target }} 93 + 94 + - name: Stage artifact 95 + shell: bash 96 + run: | 97 + mkdir -p dist 98 + cp "${{ matrix.binary_path }}" "dist/${{ matrix.artifact_name }}" 99 + 100 + - name: Upload artifact 101 + uses: actions/upload-artifact@v4 102 + with: 103 + name: ${{ matrix.artifact_name }} 104 + path: dist/${{ matrix.artifact_name }} 105 + 106 + publish: 107 + runs-on: ubuntu-latest 108 + needs: build 109 + 110 + steps: 111 + - name: Download artifacts 112 + uses: actions/download-artifact@v4 113 + with: 114 + path: dist 115 + merge-multiple: true 116 + 117 + - name: Ensure GitHub release exists 118 + env: 119 + GH_REPO: ${{ github.repository }} 120 + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 121 + run: | 122 + gh release view "${GITHUB_REF_NAME}" >/dev/null 2>&1 || 123 + gh release create "${GITHUB_REF_NAME}" --title "${GITHUB_REF_NAME}" --generate-notes 124 + 125 + - name: Publish release assets 126 + env: 127 + GH_REPO: ${{ github.repository }} 128 + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 129 + run: gh release upload "${GITHUB_REF_NAME}" dist/* --clobber
+65
.github/workflows/release-cut.yml
··· 1 + name: Release Cut 2 + 3 + on: 4 + workflow_dispatch: 5 + inputs: 6 + bump: 7 + description: Version bump type 8 + required: true 9 + default: patch 10 + type: choice 11 + options: 12 + - patch 13 + - minor 14 + - major 15 + branch: 16 + description: Branch to release from 17 + required: true 18 + default: main 19 + type: string 20 + 21 + permissions: 22 + contents: write 23 + 24 + jobs: 25 + cut-release: 26 + runs-on: ubuntu-latest 27 + 28 + steps: 29 + - name: Require release push token 30 + env: 31 + WORKFLOW_TOKEN: ${{ secrets.WORKFLOW_TOKEN }} 32 + run: | 33 + if [ -z "$WORKFLOW_TOKEN" ]; then 34 + echo "Missing secret WORKFLOW_TOKEN" >&2 35 + echo "Create this secret so the pushed tag can trigger Release Build." >&2 36 + exit 1 37 + fi 38 + 39 + - name: Checkout branch 40 + uses: actions/checkout@v4 41 + with: 42 + ref: ${{ inputs.branch }} 43 + fetch-depth: 0 44 + token: ${{ secrets.WORKFLOW_TOKEN }} 45 + 46 + - name: Setup Rust toolchain 47 + uses: dtolnay/rust-toolchain@stable 48 + 49 + - name: Configure git author 50 + run: | 51 + git config user.name "RivoLink" 52 + git config user.email "rivo.link@gmail.com" 53 + 54 + - name: Validate release candidate 55 + run: | 56 + cargo test 57 + cargo clippy --all-targets --all-features -- -D warnings 58 + 59 + - name: Restore clean working tree 60 + run: | 61 + git reset --hard HEAD 62 + git clean -fd 63 + 64 + - name: Cut release 65 + run: ./scripts/release-cut.sh "${{ inputs.bump }}" "${{ inputs.branch }}"
+169
scripts/release-cut.sh
··· 1 + #!/usr/bin/env sh 2 + set -eu 3 + 4 + usage() { 5 + echo "Usage: $0 <major|minor|patch> [branch]" >&2 6 + echo "Example: $0 patch main" >&2 7 + exit 1 8 + } 9 + 10 + BUMPTYPE="${1:-}" 11 + BRANCH="${2:-main}" 12 + 13 + [ -n "$BUMPTYPE" ] || usage 14 + 15 + case "$BUMPTYPE" in 16 + major | minor | patch) 17 + ;; 18 + *) 19 + echo "Invalid bump type: $BUMPTYPE" >&2 20 + usage 21 + ;; 22 + esac 23 + 24 + git rev-parse --is-inside-work-tree >/dev/null 2>&1 || { 25 + echo "Not inside a git repository" >&2 26 + exit 1 27 + } 28 + 29 + if ! git diff --quiet; then 30 + echo "Working tree has unstaged changes" >&2 31 + git status --short >&2 32 + exit 1 33 + fi 34 + 35 + if ! git diff --cached --quiet; then 36 + echo "Working tree has staged but uncommitted changes" >&2 37 + git status --short >&2 38 + exit 1 39 + fi 40 + 41 + tmp_file="$(mktemp)" 42 + trap 'rm -f "$tmp_file"' EXIT 43 + 44 + git fetch origin "$BRANCH" 45 + git fetch --tags origin 46 + 47 + if ! git merge-base --is-ancestor "refs/remotes/origin/$BRANCH" HEAD; then 48 + echo "Current HEAD is behind or diverged from origin/$BRANCH" >&2 49 + exit 1 50 + fi 51 + 52 + CURRENT_VERSION="$( 53 + awk ' 54 + /^\[package\]$/ { in_package = 1; next } 55 + /^\[/ && $0 != "[package]" { in_package = 0 } 56 + in_package && /^version = "/ { 57 + gsub(/^version = "/, "", $0) 58 + gsub(/"$/, "", $0) 59 + print 60 + exit 61 + } 62 + ' Cargo.toml 63 + )" 64 + 65 + case "$CURRENT_VERSION" in 66 + '' | *[!0-9.]* | *.*.*.* | .* | *.) 67 + echo "Invalid current version in Cargo.toml: $CURRENT_VERSION" >&2 68 + exit 1 69 + ;; 70 + esac 71 + 72 + IFS=. 73 + set -- $CURRENT_VERSION 74 + IFS=' ' 75 + 76 + CURRENT_MAJOR="${1:-}" 77 + CURRENT_MINOR="${2:-}" 78 + CURRENT_PATCH="${3:-}" 79 + 80 + [ -n "$CURRENT_MAJOR" ] || { 81 + echo "Invalid current version in Cargo.toml: $CURRENT_VERSION" >&2 82 + exit 1 83 + } 84 + [ -n "$CURRENT_MINOR" ] || { 85 + echo "Invalid current version in Cargo.toml: $CURRENT_VERSION" >&2 86 + exit 1 87 + } 88 + [ -n "$CURRENT_PATCH" ] || { 89 + echo "Invalid current version in Cargo.toml: $CURRENT_VERSION" >&2 90 + exit 1 91 + } 92 + 93 + case "$CURRENT_MAJOR:$CURRENT_MINOR:$CURRENT_PATCH" in 94 + *[!0-9:]*) 95 + echo "Invalid current version in Cargo.toml: $CURRENT_VERSION" >&2 96 + exit 1 97 + ;; 98 + esac 99 + 100 + case "$BUMPTYPE" in 101 + major) 102 + NEXT_MAJOR=$((CURRENT_MAJOR + 1)) 103 + NEXT_MINOR=0 104 + NEXT_PATCH=0 105 + ;; 106 + minor) 107 + NEXT_MAJOR=$CURRENT_MAJOR 108 + NEXT_MINOR=$((CURRENT_MINOR + 1)) 109 + NEXT_PATCH=0 110 + ;; 111 + patch) 112 + NEXT_MAJOR=$CURRENT_MAJOR 113 + NEXT_MINOR=$CURRENT_MINOR 114 + NEXT_PATCH=$((CURRENT_PATCH + 1)) 115 + ;; 116 + esac 117 + 118 + VERSION="$NEXT_MAJOR.$NEXT_MINOR.$NEXT_PATCH" 119 + TAG="$VERSION" 120 + 121 + if git rev-parse -q --verify "refs/tags/$TAG" >/dev/null 2>&1; then 122 + echo "Tag already exists: $TAG" >&2 123 + exit 1 124 + fi 125 + 126 + if git ls-remote --tags --exit-code origin "refs/tags/$TAG" >/dev/null 2>&1; then 127 + echo "Remote tag already exists on origin: $TAG" >&2 128 + exit 1 129 + fi 130 + 131 + awk -v version="$VERSION" ' 132 + BEGIN { 133 + in_package = 0 134 + replaced = 0 135 + } 136 + /^\[package\]$/ { 137 + in_package = 1 138 + print 139 + next 140 + } 141 + /^\[/ && $0 != "[package]" { 142 + in_package = 0 143 + } 144 + in_package && !replaced && /^version = "/ { 145 + print "version = \"" version "\"" 146 + replaced = 1 147 + next 148 + } 149 + { 150 + print 151 + } 152 + END { 153 + if (!replaced) { 154 + exit 1 155 + } 156 + } 157 + ' Cargo.toml > "$tmp_file" 158 + mv "$tmp_file" Cargo.toml 159 + 160 + if git diff --quiet -- Cargo.toml; then 161 + echo "Cargo.toml already set to version $VERSION" >&2 162 + exit 1 163 + fi 164 + 165 + git add Cargo.toml 166 + git commit -m "$VERSION" 167 + git tag "$TAG" 168 + git push origin "HEAD:$BRANCH" 169 + git push origin "$TAG"