Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8f8f637c81 | ||
|
|
2c9164b7fb | ||
|
|
b0e252c871 | ||
|
|
dc0cff220b | ||
|
|
10cbb8a5f1 | ||
|
|
0894206a9f | ||
|
|
086c3debe0 | ||
|
|
2bfcc72443 | ||
|
|
c5bcc035ca | ||
|
|
e352631791 | ||
|
|
47e5cb862f | ||
|
|
c0da2bd1e2 | ||
|
|
d8e0046ad6
|
||
|
|
ce792f180d
|
||
|
|
a848b8f06c
|
||
|
|
a21cb266c5
|
No files matched your search
@@ -1,375 +0,0 @@
|
||||
name: Release
|
||||
|
||||
# PRD F8, Gitea edition. On a v* tag push, build the single-file kigi binary
|
||||
# for the five supported targets, package kigi-<version>-<target-triple>.
|
||||
# {tar.gz|zip} (binary + LICENSE + NOTICE + THIRD-PARTY-NOTICES), and publish
|
||||
# them as a Gitea Release alongside SHA256SUMS. install.sh, install.ps1 and
|
||||
# auto_update::release_asset_name() all resolve these exact names — keep the
|
||||
# naming in lockstep with them.
|
||||
#
|
||||
# RUNNERS. Gitea has no hosted runners; every label below must be a runner you
|
||||
# registered yourself (docs/RELEASE.md has the register commands):
|
||||
#
|
||||
# ubuntu-latest Linux x86_64, container mode — the label the Linux server's
|
||||
# runner already advertises. Builds both Linux targets;
|
||||
# aarch64 is a cross-compile, so this leg installs the
|
||||
# aarch64 GNU toolchain. Because the image is a bare
|
||||
# runner-image, the Linux legs provision their own apt
|
||||
# packages and rustup (see the provision steps below).
|
||||
# Registering a dedicated `linux-x86_64:docker://...` runner
|
||||
# instead is fine — swap the three labels back if you do.
|
||||
# macos-arm64 Apple Silicon Mac, host mode. Builds both Darwin targets;
|
||||
# x86_64 is a cross-compile against the same SDK. macOS
|
||||
# CANNOT be built anywhere else — Apple's SDK licence
|
||||
# restricts it to Apple hardware.
|
||||
# windows-amd64 Windows x86_64, host mode, with VS 2022 Build Tools
|
||||
# (C++ workload). Needed because the tree links ring,
|
||||
# mimalloc, zstd-sys and libz-sys against a static MSVC CRT
|
||||
# (-C target-feature=+crt-static).
|
||||
#
|
||||
# SHELLS. Every step names its shell explicitly and the Windows leg never uses
|
||||
# bash. On a normal Windows box `bash` resolves to WSL (not Git Bash), and
|
||||
# `pwsh` (PowerShell 7) is usually absent — so Windows steps use `powershell`,
|
||||
# which is the built-in 5.1. Keep those steps 5.1-compatible: no `&&`, no
|
||||
# ternary, no null-coalescing.
|
||||
#
|
||||
# Note: because this file exists, Gitea ignores .github/workflows entirely.
|
||||
#
|
||||
# PUBLISH ORDER. The release is created as a draft and only made public once
|
||||
# SHA256SUMS is attached, so `releases/latest` never hands the installer a
|
||||
# release whose checksum manifest is still missing.
|
||||
|
||||
on:
|
||||
push:
|
||||
tags: ["v*"]
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
# Matches the version pinned by the dotslash launcher in bin/protoc. That
|
||||
# launcher is not used here: it has no Windows entry and needs a `cargo
|
||||
# install dotslash` first, so every platform fetches protoc directly.
|
||||
PROTOC_VERSION: "29.3"
|
||||
|
||||
jobs:
|
||||
prepare:
|
||||
name: prepare draft release
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
release_id: ${{ steps.draft.outputs.release_id }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Check tag matches workspace version
|
||||
shell: bash
|
||||
run: |
|
||||
tag_version="${GITHUB_REF_NAME#v}"
|
||||
cargo_version="$(sed -n 's/^version = "\(.*\)"$/\1/p' Cargo.toml | head -n 1)"
|
||||
if [ "$tag_version" != "$cargo_version" ]; then
|
||||
echo "Tag $GITHUB_REF_NAME does not match workspace version $cargo_version" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Create or reuse draft release
|
||||
id: draft
|
||||
shell: bash
|
||||
env:
|
||||
TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
API: ${{ github.server_url }}/api/v1/repos/${{ github.repository }}
|
||||
run: |
|
||||
set -eu
|
||||
# The runner-image is bare; jq and curl are both used below.
|
||||
if ! command -v jq >/dev/null || ! command -v curl >/dev/null; then
|
||||
SUDO=""; command -v sudo >/dev/null && SUDO=sudo
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
$SUDO apt-get update -qq
|
||||
$SUDO apt-get install -y -qq --no-install-recommends jq curl ca-certificates
|
||||
fi
|
||||
|
||||
# Idempotent so a re-run of a failed tag build reuses the same draft
|
||||
# instead of erroring on a duplicate tag_name.
|
||||
existing="$(curl -sS -H "Authorization: token $TOKEN" \
|
||||
"$API/releases/tags/$GITHUB_REF_NAME")"
|
||||
release_id="$(printf '%s' "$existing" | jq -r '.id // empty')"
|
||||
|
||||
if [ -z "$release_id" ]; then
|
||||
prerelease=false
|
||||
case "$GITHUB_REF_NAME" in *-*) prerelease=true ;; esac
|
||||
created="$(curl -fsS -X POST \
|
||||
-H "Authorization: token $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"tag_name\":\"$GITHUB_REF_NAME\",\"name\":\"$GITHUB_REF_NAME\",\"draft\":true,\"prerelease\":$prerelease}" \
|
||||
"$API/releases")"
|
||||
release_id="$(printf '%s' "$created" | jq -r '.id')"
|
||||
echo "Created draft release $release_id (prerelease=$prerelease)"
|
||||
else
|
||||
echo "Reusing release $release_id for $GITHUB_REF_NAME"
|
||||
fi
|
||||
|
||||
echo "release_id=$release_id" >> "$GITHUB_OUTPUT"
|
||||
|
||||
build:
|
||||
name: build (${{ matrix.target }})
|
||||
needs: prepare
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- target: x86_64-unknown-linux-gnu
|
||||
runner: ubuntu-latest
|
||||
protoc: linux-x86_64
|
||||
ext: tar.gz
|
||||
linux: true
|
||||
- target: aarch64-unknown-linux-gnu
|
||||
runner: ubuntu-latest
|
||||
protoc: linux-x86_64
|
||||
ext: tar.gz
|
||||
linux: true
|
||||
cross_gnu: true
|
||||
- target: aarch64-apple-darwin
|
||||
runner: macos-arm64
|
||||
protoc: osx-aarch_64
|
||||
ext: tar.gz
|
||||
- target: x86_64-apple-darwin
|
||||
runner: macos-arm64
|
||||
protoc: osx-aarch_64
|
||||
ext: tar.gz
|
||||
- target: x86_64-pc-windows-msvc
|
||||
runner: windows-amd64
|
||||
protoc: win64
|
||||
ext: zip
|
||||
runs-on: ${{ matrix.runner }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
# ── linux container provisioning ──────────────────────────────────────
|
||||
# The Linux legs run in a bare gitea runner-image, which ships git and
|
||||
# node for the JavaScript actions but no compiler, no unzip (protoc) and
|
||||
# no rustup. Host-mode macOS and Windows already have their toolchains
|
||||
# installed, so this step is Linux-only.
|
||||
- name: Provision Linux build deps
|
||||
if: matrix.linux
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
SUDO=""; command -v sudo >/dev/null && SUDO=sudo
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
$SUDO apt-get update -qq
|
||||
$SUDO apt-get install -y -qq --no-install-recommends \
|
||||
build-essential pkg-config ca-certificates curl unzip tar jq
|
||||
|
||||
# ── protoc ────────────────────────────────────────────────────────────
|
||||
- name: Install protoc (unix)
|
||||
if: matrix.ext == 'tar.gz'
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
url="https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-${{ matrix.protoc }}.zip"
|
||||
curl -fsSL -o protoc.zip "$url"
|
||||
rm -rf "$HOME/protoc"
|
||||
unzip -q -o protoc.zip -d "$HOME/protoc"
|
||||
chmod +x "$HOME/protoc/bin/protoc"
|
||||
echo "$HOME/protoc/bin" >> "$GITHUB_PATH"
|
||||
|
||||
- name: Install protoc (windows)
|
||||
if: matrix.ext == 'zip'
|
||||
shell: powershell
|
||||
run: |
|
||||
$ErrorActionPreference = "Stop"
|
||||
$url = "https://github.com/protocolbuffers/protobuf/releases/download/v$env:PROTOC_VERSION/protoc-$env:PROTOC_VERSION-${{ matrix.protoc }}.zip"
|
||||
Invoke-WebRequest -Uri $url -OutFile protoc.zip
|
||||
$dest = Join-Path $env:USERPROFILE "protoc"
|
||||
if (Test-Path $dest) { Remove-Item $dest -Recurse -Force }
|
||||
Expand-Archive protoc.zip -DestinationPath $dest -Force
|
||||
Add-Content -Path $env:GITHUB_PATH -Value (Join-Path $dest "bin")
|
||||
|
||||
# ── toolchain ─────────────────────────────────────────────────────────
|
||||
# rust-toolchain.toml pins the channel (1.97.0) and preinstalls both
|
||||
# Linux targets; `rustup show` materialises exactly that.
|
||||
- name: Install toolchain (unix)
|
||||
if: matrix.ext == 'tar.gz'
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# No-op on the macOS host runner, which has rustup installed already.
|
||||
# `--default-toolchain none` leaves the channel choice to
|
||||
# rust-toolchain.toml, which `rustup show` then materialises.
|
||||
if ! command -v rustup >/dev/null; then
|
||||
curl --proto '=https' --tlsv1.2 -fsSL https://sh.rustup.rs \
|
||||
| sh -s -- -y --no-modify-path --profile minimal --default-toolchain none
|
||||
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
|
||||
export PATH="$HOME/.cargo/bin:$PATH"
|
||||
fi
|
||||
rustup show
|
||||
rustup target add ${{ matrix.target }}
|
||||
|
||||
- name: Install toolchain (windows)
|
||||
if: matrix.ext == 'zip'
|
||||
shell: powershell
|
||||
run: |
|
||||
$ErrorActionPreference = "Stop"
|
||||
rustup show
|
||||
rustup target add ${{ matrix.target }}
|
||||
|
||||
# ring, mimalloc, zstd-sys and libz-sys are all cc-rs builds, so the
|
||||
# cross target needs its own C toolchain — cc-rs picks these up from the
|
||||
# target-suffixed vars.
|
||||
- name: Install aarch64 cross toolchain
|
||||
if: matrix.cross_gnu
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
SUDO=""; command -v sudo >/dev/null && SUDO=sudo
|
||||
$SUDO apt-get update -qq
|
||||
$SUDO apt-get install -y -qq gcc-aarch64-linux-gnu g++-aarch64-linux-gnu
|
||||
{
|
||||
echo "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc"
|
||||
echo "CC_aarch64_unknown_linux_gnu=aarch64-linux-gnu-gcc"
|
||||
echo "CXX_aarch64_unknown_linux_gnu=aarch64-linux-gnu-g++"
|
||||
echo "AR_aarch64_unknown_linux_gnu=aarch64-linux-gnu-ar"
|
||||
} >> "$GITHUB_ENV"
|
||||
|
||||
# ── build ─────────────────────────────────────────────────────────────
|
||||
- name: Build kigi (unix)
|
||||
if: matrix.ext == 'tar.gz'
|
||||
shell: bash
|
||||
run: cargo build --profile release-dist -p kigi-bin --locked --target ${{ matrix.target }}
|
||||
|
||||
- name: Build kigi (windows)
|
||||
if: matrix.ext == 'zip'
|
||||
shell: powershell
|
||||
run: |
|
||||
$ErrorActionPreference = "Stop"
|
||||
cargo build --profile release-dist -p kigi-bin --locked --target ${{ matrix.target }}
|
||||
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
|
||||
|
||||
# ── package, upload, checksum ─────────────────────────────────────────
|
||||
# Archives go straight to the release rather than through the artifact
|
||||
# store: they are large, and the release is the only place install.sh
|
||||
# can read them from anyway. Only the checksum line travels as an
|
||||
# artifact, for the publish job to concatenate.
|
||||
- name: Package and upload (unix)
|
||||
if: matrix.ext == 'tar.gz'
|
||||
shell: bash
|
||||
env:
|
||||
TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
API: ${{ github.server_url }}/api/v1/repos/${{ github.repository }}
|
||||
RELEASE_ID: ${{ needs.prepare.outputs.release_id }}
|
||||
run: |
|
||||
set -eu
|
||||
version="${GITHUB_REF_NAME#v}"
|
||||
archive="kigi-${version}-${{ matrix.target }}.tar.gz"
|
||||
staging="$(mktemp -d)"
|
||||
cp "target/${{ matrix.target }}/release-dist/kigi" "$staging/kigi"
|
||||
cp LICENSE "$staging/"
|
||||
[ -f NOTICE ] && cp NOTICE "$staging/"
|
||||
for f in THIRD-PARTY-NOTICES THIRD-PARTY-NOTICES.md; do
|
||||
[ -f "$f" ] && cp "$f" "$staging/"
|
||||
done
|
||||
tar -C "$staging" -czf "$archive" .
|
||||
|
||||
curl -fsS -X POST \
|
||||
-H "Authorization: token $TOKEN" \
|
||||
-F "attachment=@${archive}" \
|
||||
"$API/releases/$RELEASE_ID/assets?name=${archive}" > /dev/null
|
||||
echo "Uploaded $archive"
|
||||
|
||||
if command -v sha256sum >/dev/null; then
|
||||
sha256sum "$archive" > "checksum-${{ matrix.target }}.txt"
|
||||
else
|
||||
shasum -a 256 "$archive" > "checksum-${{ matrix.target }}.txt"
|
||||
fi
|
||||
cat "checksum-${{ matrix.target }}.txt"
|
||||
|
||||
- name: Package and upload (windows)
|
||||
if: matrix.ext == 'zip'
|
||||
shell: powershell
|
||||
env:
|
||||
TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
API: ${{ github.server_url }}/api/v1/repos/${{ github.repository }}
|
||||
RELEASE_ID: ${{ needs.prepare.outputs.release_id }}
|
||||
run: |
|
||||
$ErrorActionPreference = "Stop"
|
||||
$version = $env:GITHUB_REF_NAME.TrimStart("v")
|
||||
$archive = "kigi-$version-${{ matrix.target }}.zip"
|
||||
$staging = Join-Path $env:RUNNER_TEMP "staging"
|
||||
if (Test-Path $staging) { Remove-Item $staging -Recurse -Force }
|
||||
New-Item -ItemType Directory -Force -Path $staging | Out-Null
|
||||
Copy-Item "target/${{ matrix.target }}/release-dist/kigi.exe" (Join-Path $staging "kigi.exe")
|
||||
Copy-Item LICENSE $staging
|
||||
if (Test-Path NOTICE) { Copy-Item NOTICE $staging }
|
||||
foreach ($f in @("THIRD-PARTY-NOTICES", "THIRD-PARTY-NOTICES.md")) {
|
||||
if (Test-Path $f) { Copy-Item $f $staging }
|
||||
}
|
||||
Compress-Archive -Path (Join-Path $staging "*") -DestinationPath $archive -Force
|
||||
|
||||
# System32\curl.exe, not PowerShell's `curl` alias for
|
||||
# Invoke-WebRequest, which cannot do multipart uploads.
|
||||
$api = "$env:API/releases/$env:RELEASE_ID/assets?name=$archive"
|
||||
& "$env:SystemRoot\System32\curl.exe" -fsS -X POST `
|
||||
-H "Authorization: token $env:TOKEN" `
|
||||
-F "attachment=@$archive" $api
|
||||
if ($LASTEXITCODE -ne 0) { throw "asset upload failed ($LASTEXITCODE)" }
|
||||
Write-Host "Uploaded $archive"
|
||||
|
||||
# sha256sum's exact format, so the publish job can just concatenate.
|
||||
# ASCII keeps the BOM out — a BOM would corrupt the first hash.
|
||||
$hash = (Get-FileHash -Algorithm SHA256 -Path $archive).Hash.ToLowerInvariant()
|
||||
"$hash $archive" | Out-File -FilePath "checksum-${{ matrix.target }}.txt" -Encoding ascii
|
||||
Get-Content "checksum-${{ matrix.target }}.txt"
|
||||
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: checksum-${{ matrix.target }}
|
||||
path: checksum-${{ matrix.target }}.txt
|
||||
if-no-files-found: error
|
||||
|
||||
publish:
|
||||
name: publish release
|
||||
needs: [prepare, build]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
path: checksums
|
||||
|
||||
- name: Assemble SHA256SUMS
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# download-artifact v3 nests each artifact in its own directory. The
|
||||
# Windows line arrives CRLF-terminated; strip CR so every line is LF
|
||||
# for install.sh's `read -r hash name`.
|
||||
find checksums -name 'checksum-*.txt' -exec cat {} + \
|
||||
| tr -d '\r' | grep -v '^$' | sort -k2 > SHA256SUMS
|
||||
lines="$(wc -l < SHA256SUMS)"
|
||||
if [ "$lines" -ne 5 ]; then
|
||||
echo "expected 5 checksum lines, got $lines" >&2
|
||||
cat SHA256SUMS >&2
|
||||
exit 1
|
||||
fi
|
||||
cat SHA256SUMS
|
||||
|
||||
- name: Attach SHA256SUMS and publish
|
||||
shell: bash
|
||||
env:
|
||||
TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
API: ${{ github.server_url }}/api/v1/repos/${{ github.repository }}
|
||||
RELEASE_ID: ${{ needs.prepare.outputs.release_id }}
|
||||
run: |
|
||||
set -eu
|
||||
curl -fsS -X POST \
|
||||
-H "Authorization: token $TOKEN" \
|
||||
-F "attachment=@SHA256SUMS" \
|
||||
"$API/releases/$RELEASE_ID/assets?name=SHA256SUMS" > /dev/null
|
||||
|
||||
# Flip the draft public only now that every asset install.sh looks
|
||||
# for is attached.
|
||||
curl -fsS -X PATCH \
|
||||
-H "Authorization: token $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"draft":false}' \
|
||||
"$API/releases/$RELEASE_ID" > /dev/null
|
||||
echo "Published $GITHUB_REF_NAME"
|
||||
@@ -0,0 +1,49 @@
|
||||
name: Bug Report
|
||||
description: Something behaves, draws or builds wrong.
|
||||
title: "[BUG REPORT] "
|
||||
labels: [bug]
|
||||
body:
|
||||
- type: dropdown
|
||||
id: where
|
||||
attributes:
|
||||
label: Where
|
||||
options:
|
||||
- macOS
|
||||
- Windows
|
||||
- Linux
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: what
|
||||
attributes:
|
||||
label: What happened
|
||||
description: A screenshot or a short recording helps most.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: steps
|
||||
attributes:
|
||||
label: Steps to reproduce
|
||||
placeholder: |
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: expected
|
||||
attributes:
|
||||
label: What you expected
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: version
|
||||
attributes:
|
||||
label: "Version (`kigi --version`)"
|
||||
placeholder: "0.1.21"
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Logs
|
||||
description: Terminal output or error messages.
|
||||
render: shell
|
||||
@@ -0,0 +1,5 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Kigi
|
||||
url: https://kigicli.dev
|
||||
about: "Install steps and docs."
|
||||
@@ -0,0 +1,28 @@
|
||||
name: Feature Request
|
||||
description: Something new, or something that should do more.
|
||||
title: "[FEATURE REQUEST] "
|
||||
labels: [enhancement]
|
||||
body:
|
||||
- type: textarea
|
||||
id: use
|
||||
attributes:
|
||||
label: What it is for
|
||||
description: The problem, and the moment you need it in.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: behavior
|
||||
attributes:
|
||||
label: How it should work
|
||||
- type: textarea
|
||||
id: references
|
||||
attributes:
|
||||
label: References
|
||||
description: Links or screenshots of it elsewhere.
|
||||
- type: checkboxes
|
||||
id: searched
|
||||
attributes:
|
||||
label: Checked
|
||||
options:
|
||||
- label: I searched the open issues for the same request.
|
||||
required: true
|
||||
@@ -0,0 +1,11 @@
|
||||
name: Other
|
||||
description: Questions, docs, ideas, anything else.
|
||||
title: "[Other] "
|
||||
labels: [question]
|
||||
body:
|
||||
- type: textarea
|
||||
id: what
|
||||
attributes:
|
||||
label: What's on your mind
|
||||
validations:
|
||||
required: true
|
||||
@@ -0,0 +1,35 @@
|
||||
<!--
|
||||
Title: start with the type, for example
|
||||
[FEATURE REQUEST] Add dark mode to the settings page
|
||||
[BUG REPORT] Fix a crash when opening an empty file
|
||||
[Other] Update the README install steps
|
||||
-->
|
||||
|
||||
## Type
|
||||
|
||||
- [ ] **[FEATURE REQUEST]**: a new feature or an improvement
|
||||
- [ ] **[BUG REPORT]**: a bug fix
|
||||
- [ ] **[Other]**: docs, refactoring, CI, dependencies or chores
|
||||
|
||||
## What and why
|
||||
|
||||
<!-- One or two sentences. Link the issue: Closes #123 -->
|
||||
|
||||
## Bug details
|
||||
|
||||
<!-- [BUG REPORT] only; delete this section otherwise. -->
|
||||
|
||||
- Steps to reproduce:
|
||||
- Expected:
|
||||
- Actual:
|
||||
- Cause and fix:
|
||||
|
||||
## How it was tested
|
||||
|
||||
<!-- Commands you ran, and what you checked by hand. -->
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] The title starts with `[FEATURE REQUEST]`, `[BUG REPORT]` or `[Other]`
|
||||
- [ ] Tests and the build pass locally
|
||||
- [ ] Docs are updated if behaviour changed
|
||||
@@ -0,0 +1,255 @@
|
||||
name: Release
|
||||
|
||||
# PRD F8. On a v* tag push, build the single-file kigi binary for the five
|
||||
# supported targets, package kigi-<version>-<target-triple>.{tar.gz|zip}
|
||||
# (binary + LICENSE + NOTICE + THIRD-PARTY-NOTICES), and publish them as a
|
||||
# GitHub Release alongside SHA256SUMS. install.sh, install.ps1 and
|
||||
# auto_update::release_asset_name() all resolve these exact names — keep the
|
||||
# naming in lockstep with them.
|
||||
#
|
||||
# RUNNERS. GitHub-hosted only; no job needs local state, and the repo is
|
||||
# public, so nothing here may move to a self-hosted runner.
|
||||
#
|
||||
# ubuntu-latest x86_64-unknown-linux-gnu
|
||||
# ubuntu-24.04-arm aarch64-unknown-linux-gnu, built natively (no cross C
|
||||
# toolchain for ring, mimalloc, zstd-sys, libz-sys)
|
||||
# macos-latest both Darwin targets; the runner is arm64, so x86_64 is
|
||||
# a cross-compile against the same SDK
|
||||
# windows-latest x86_64-pc-windows-msvc (VS Build Tools preinstalled,
|
||||
# needed for the static MSVC CRT link)
|
||||
#
|
||||
# PUBLISH ORDER. The release is created as a draft and only made public once
|
||||
# SHA256SUMS is attached, so `releases/latest` never hands the installer a
|
||||
# release whose checksum manifest is still missing.
|
||||
|
||||
on:
|
||||
push:
|
||||
tags: ["v*"]
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GH_REPO: ${{ github.repository }}
|
||||
# Matches the version pinned by the dotslash launcher in bin/protoc. That
|
||||
# launcher is not used here: it has no Windows entry and needs a `cargo
|
||||
# install dotslash` first, so every platform fetches protoc directly.
|
||||
PROTOC_VERSION: "29.3"
|
||||
|
||||
jobs:
|
||||
prepare:
|
||||
name: prepare draft release
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Check tag matches workspace version
|
||||
shell: bash
|
||||
run: |
|
||||
tag_version="${GITHUB_REF_NAME#v}"
|
||||
cargo_version="$(sed -n 's/^version = "\(.*\)"$/\1/p' Cargo.toml | head -n 1)"
|
||||
if [ "$tag_version" != "$cargo_version" ]; then
|
||||
echo "Tag $GITHUB_REF_NAME does not match workspace version $cargo_version" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Idempotent so a re-run of a failed tag build reuses the same draft
|
||||
# instead of erroring on a duplicate tag_name.
|
||||
- name: Create or reuse draft release
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
if gh release view "$GITHUB_REF_NAME" > /dev/null 2>&1; then
|
||||
echo "Reusing release $GITHUB_REF_NAME"
|
||||
exit 0
|
||||
fi
|
||||
prerelease=""
|
||||
case "$GITHUB_REF_NAME" in *-*) prerelease="--prerelease" ;; esac
|
||||
gh release create "$GITHUB_REF_NAME" --draft --verify-tag \
|
||||
--title "$GITHUB_REF_NAME" --generate-notes $prerelease
|
||||
echo "Created draft release $GITHUB_REF_NAME ${prerelease}"
|
||||
|
||||
build:
|
||||
name: build (${{ matrix.target }})
|
||||
needs: prepare
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- target: x86_64-unknown-linux-gnu
|
||||
runner: ubuntu-latest
|
||||
protoc: linux-x86_64
|
||||
ext: tar.gz
|
||||
- target: aarch64-unknown-linux-gnu
|
||||
runner: ubuntu-24.04-arm
|
||||
protoc: linux-aarch_64
|
||||
ext: tar.gz
|
||||
- target: aarch64-apple-darwin
|
||||
runner: macos-latest
|
||||
protoc: osx-aarch_64
|
||||
ext: tar.gz
|
||||
- target: x86_64-apple-darwin
|
||||
runner: macos-latest
|
||||
protoc: osx-aarch_64
|
||||
ext: tar.gz
|
||||
- target: x86_64-pc-windows-msvc
|
||||
runner: windows-latest
|
||||
protoc: win64
|
||||
ext: zip
|
||||
runs-on: ${{ matrix.runner }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
# ── protoc ────────────────────────────────────────────────────────────
|
||||
- name: Install protoc (unix)
|
||||
if: matrix.ext == 'tar.gz'
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
url="https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-${{ matrix.protoc }}.zip"
|
||||
curl -fsSL -o protoc.zip "$url"
|
||||
rm -rf "$HOME/protoc"
|
||||
unzip -q -o protoc.zip -d "$HOME/protoc"
|
||||
chmod +x "$HOME/protoc/bin/protoc"
|
||||
echo "$HOME/protoc/bin" >> "$GITHUB_PATH"
|
||||
|
||||
- name: Install protoc (windows)
|
||||
if: matrix.ext == 'zip'
|
||||
shell: pwsh
|
||||
run: |
|
||||
$ErrorActionPreference = "Stop"
|
||||
$url = "https://github.com/protocolbuffers/protobuf/releases/download/v$env:PROTOC_VERSION/protoc-$env:PROTOC_VERSION-${{ matrix.protoc }}.zip"
|
||||
Invoke-WebRequest -Uri $url -OutFile protoc.zip
|
||||
$dest = Join-Path $env:USERPROFILE "protoc"
|
||||
if (Test-Path $dest) { Remove-Item $dest -Recurse -Force }
|
||||
Expand-Archive protoc.zip -DestinationPath $dest -Force
|
||||
Add-Content -Path $env:GITHUB_PATH -Value (Join-Path $dest "bin")
|
||||
|
||||
# ── toolchain ─────────────────────────────────────────────────────────
|
||||
# rust-toolchain.toml pins the channel (1.97.0); `rustup show`
|
||||
# materialises exactly that.
|
||||
- name: Install toolchain
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# The arm64 Linux image is not guaranteed to ship rustup.
|
||||
# `--default-toolchain none` leaves the channel choice to
|
||||
# rust-toolchain.toml.
|
||||
if ! command -v rustup >/dev/null; then
|
||||
curl --proto '=https' --tlsv1.2 -fsSL https://sh.rustup.rs \
|
||||
| sh -s -- -y --no-modify-path --profile minimal --default-toolchain none
|
||||
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
|
||||
export PATH="$HOME/.cargo/bin:$PATH"
|
||||
fi
|
||||
rustup show
|
||||
rustup target add ${{ matrix.target }}
|
||||
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
key: ${{ matrix.target }}
|
||||
|
||||
# ── build ─────────────────────────────────────────────────────────────
|
||||
- name: Build kigi
|
||||
shell: bash
|
||||
run: cargo build --profile release-dist -p kigi-bin --locked --target ${{ matrix.target }}
|
||||
|
||||
# ── package, upload, checksum ─────────────────────────────────────────
|
||||
# Archives go straight to the release rather than through the artifact
|
||||
# store: they are large, and the release is the only place install.sh
|
||||
# can read them from anyway. Only the checksum line travels as an
|
||||
# artifact, for the publish job to concatenate.
|
||||
- name: Package (unix)
|
||||
if: matrix.ext == 'tar.gz'
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
version="${GITHUB_REF_NAME#v}"
|
||||
archive="kigi-${version}-${{ matrix.target }}.tar.gz"
|
||||
staging="$(mktemp -d)"
|
||||
cp "target/${{ matrix.target }}/release-dist/kigi" "$staging/kigi"
|
||||
cp LICENSE "$staging/"
|
||||
[ -f NOTICE ] && cp NOTICE "$staging/"
|
||||
for f in THIRD-PARTY-NOTICES THIRD-PARTY-NOTICES.md; do
|
||||
[ -f "$f" ] && cp "$f" "$staging/"
|
||||
done
|
||||
tar -C "$staging" -czf "$archive" .
|
||||
echo "ARCHIVE=$archive" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Package (windows)
|
||||
if: matrix.ext == 'zip'
|
||||
shell: pwsh
|
||||
run: |
|
||||
$ErrorActionPreference = "Stop"
|
||||
$version = $env:GITHUB_REF_NAME.TrimStart("v")
|
||||
$archive = "kigi-$version-${{ matrix.target }}.zip"
|
||||
$staging = Join-Path $env:RUNNER_TEMP "staging"
|
||||
if (Test-Path $staging) { Remove-Item $staging -Recurse -Force }
|
||||
New-Item -ItemType Directory -Force -Path $staging | Out-Null
|
||||
Copy-Item "target/${{ matrix.target }}/release-dist/kigi.exe" (Join-Path $staging "kigi.exe")
|
||||
Copy-Item LICENSE $staging
|
||||
if (Test-Path NOTICE) { Copy-Item NOTICE $staging }
|
||||
foreach ($f in @("THIRD-PARTY-NOTICES", "THIRD-PARTY-NOTICES.md")) {
|
||||
if (Test-Path $f) { Copy-Item $f $staging }
|
||||
}
|
||||
Compress-Archive -Path (Join-Path $staging "*") -DestinationPath $archive -Force
|
||||
Add-Content -Path $env:GITHUB_ENV -Value "ARCHIVE=$archive"
|
||||
|
||||
# Git Bash on Windows; sha256sum is available on every runner except
|
||||
# macOS, which has shasum.
|
||||
- name: Upload and checksum
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
gh release upload "$GITHUB_REF_NAME" "$ARCHIVE" --clobber
|
||||
echo "Uploaded $ARCHIVE"
|
||||
if command -v sha256sum >/dev/null; then
|
||||
sha256sum "$ARCHIVE" > "checksum-${{ matrix.target }}.txt"
|
||||
else
|
||||
shasum -a 256 "$ARCHIVE" > "checksum-${{ matrix.target }}.txt"
|
||||
fi
|
||||
cat "checksum-${{ matrix.target }}.txt"
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: checksum-${{ matrix.target }}
|
||||
path: checksum-${{ matrix.target }}.txt
|
||||
if-no-files-found: error
|
||||
|
||||
publish:
|
||||
name: publish release
|
||||
needs: [prepare, build]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: checksums
|
||||
pattern: checksum-*
|
||||
merge-multiple: true
|
||||
|
||||
- name: Assemble SHA256SUMS
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
# Strip CR (Git Bash may emit CRLF) and the binary-mode `*` marker
|
||||
# so every line is `<hash> <name>` for install.sh.
|
||||
cat checksums/checksum-*.txt \
|
||||
| tr -d '\r' | sed 's/ \*/ /' | grep -v '^$' | sort -k2 > SHA256SUMS
|
||||
lines="$(wc -l < SHA256SUMS)"
|
||||
if [ "$lines" -ne 5 ]; then
|
||||
echo "expected 5 checksum lines, got $lines" >&2
|
||||
cat SHA256SUMS >&2
|
||||
exit 1
|
||||
fi
|
||||
cat SHA256SUMS
|
||||
|
||||
# Flip the draft public only now that every asset install.sh looks for
|
||||
# is attached.
|
||||
- name: Attach SHA256SUMS and publish
|
||||
shell: bash
|
||||
run: |
|
||||
set -eu
|
||||
gh release upload "$GITHUB_REF_NAME" SHA256SUMS --clobber
|
||||
gh release edit "$GITHUB_REF_NAME" --draft=false
|
||||
echo "Published $GITHUB_REF_NAME"
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
.wrangler/
|
||||
node_modules/
|
||||
|
||||
# Runner-setup prompt; holds a Gitea registration token once filled in.
|
||||
# Runner-setup prompt; may hold a runner registration token once filled in.
|
||||
/prompt.txt
|
||||
|
||||
# Local test credentials
|
||||
|
||||
@@ -19,9 +19,13 @@ snapshot `8adf901` (2026-07-16, ≈v0.2.102); bug fixes evaluated and
|
||||
selectively ported through upstream `77cd7eb` (2026-08-25, ≈v1.0.10) in
|
||||
the 0.1.13 cycle, through `3794978` (2026-09-09, ≈v1.0.24) in the 0.1.15
|
||||
cycle, through `a28ee2b` (2026-09-17, ≈v1.0.35) in the 0.1.16 cycle, and
|
||||
through `2bdd1d6` (2026-09-29, ≈v1.0.45) in the 0.1.19 cycle.
|
||||
The local release is 0.1.20; it adds custom providers declared by base
|
||||
URL (`[platforms.<name>]`, see CUSTOM PROVIDERS below).
|
||||
through `2bdd1d6` (2026-09-29, ≈v1.0.45) in the 0.1.19 cycle. The
|
||||
0.1.22 check (2026-10-31) found upstream still at `2bdd1d6`: nothing new
|
||||
to port.
|
||||
The local release is 0.1.22; it self-updates from
|
||||
`ELY-Open-Source/Kigi-CLI` on GitHub (0.1.21 read Gitea). Custom
|
||||
providers declared by base URL (`[platforms.<name>]`, see CUSTOM
|
||||
PROVIDERS below) arrived in 0.1.19.
|
||||
Every upstream reference comes from the local clone at `./grok-build`
|
||||
(gitignored, never committed): `git -C grok-build pull` before a sync,
|
||||
then read upstream code and history there, not from the web.
|
||||
@@ -68,7 +72,7 @@ a design against the 0.1.15 teardown), MCP servers on protocol 2026-07-28
|
||||
## Hard constraints
|
||||
|
||||
- **Zero egress**: only `auth.kimi.com`, `api.kimi.com`, `api.moonshot.cn`,
|
||||
`api.moonshot.ai`, Gitea Releases (`git.zacharyzhang.com`), user-configured MCP servers, credentialed
|
||||
`api.moonshot.ai`, GitHub Releases, user-configured MCP servers, credentialed
|
||||
provider endpoints, and `models.dev` (metadata refresh, ONLY when an enabled
|
||||
platform's `/models` lacks it — `wire_serves_metadata=false`, never
|
||||
Kimi/Moonshot, `KIGI_MODELS_DEV_URL=0` disables). No telemetry, no analytics,
|
||||
@@ -640,4 +644,4 @@ client-side, no backend surface.
|
||||
grok.com references live only there and in `kigi-sampler`/proxy types.
|
||||
- M2: server-side search/fetch (F5), command parity with kimi-cli 1.49.0
|
||||
(F6), one-time `~/.kimi/config.toml` import (F7), F9 smoke list, perf CI.
|
||||
- M3: Gitea Releases distribution, install scripts, self-update (F8).
|
||||
- M3: GitHub Releases distribution, install scripts, self-update (F8).
|
||||
+5
-12
@@ -21,16 +21,9 @@ cargo deny check advisories
|
||||
- Upstream syncs are evaluated commit-by-commit and cherry-picked manually;
|
||||
see the PRD §8.1 policy (`git range-diff` records the adopted set).
|
||||
|
||||
## Opening a pull request on git.zacharyzhang.com
|
||||
## Opening a pull request
|
||||
|
||||
Forking is disabled on this server. Open pull requests with AGit instead:
|
||||
|
||||
1. Register an account at https://git.zacharyzhang.com
|
||||
2. Clone, commit your changes, then push to a `refs/for/<target-branch>` ref:
|
||||
|
||||
```bash
|
||||
git clone https://git.zacharyzhang.com/ZacharyZhang-NY/Kigi-CLI.git
|
||||
git push origin HEAD:refs/for/main -o topic=<short-name> -o title="<PR title>" -o description="<PR body>"
|
||||
```
|
||||
|
||||
3. To update the pull request, push again with the same `topic`.
|
||||
Fork [ELY-Open-Source/Kigi-CLI](https://github.com/ELY-Open-Source/Kigi-CLI),
|
||||
push your branch to the fork, and open a pull request against `main`. Report
|
||||
bugs and request features on the
|
||||
[issue tracker](https://github.com/ELY-Open-Source/Kigi-CLI/issues).
|
||||
Generated
+119
-449
File diff suppressed because it is too large.
Load diff
+3
-4
@@ -76,7 +76,7 @@ members = [
|
||||
]
|
||||
|
||||
[workspace.package]
|
||||
version = "0.1.21"
|
||||
version = "0.1.22"
|
||||
edition = "2024"
|
||||
license = "Apache-2.0"
|
||||
|
||||
@@ -191,7 +191,6 @@ reqwest = { version = "0.12", features = ["rustls-tls", "stream", "json", "multi
|
||||
reqwest-middleware = { version = "0.4.1", features = ["json", "multipart"] }
|
||||
resvg = { version = "0.47", default-features = false, features = ["text"] }
|
||||
ring = "0.17"
|
||||
rsa = "0.9"
|
||||
runfiles = "0.1"
|
||||
rustc-hash = "2"
|
||||
schemars = "1"
|
||||
@@ -295,8 +294,8 @@ kigi-tool-runtime = { path = "crates/common/kigi-tool-runtime" }
|
||||
kigi-tool-types = { path = "crates/common/kigi-tool-types" }
|
||||
kigi-tty-utils = { path = "crates/codegen/kigi-tty-utils" }
|
||||
zbus = { version = "5" }
|
||||
zip = { version = "8", default-features = false, features = ["deflate"] }
|
||||
zstd = "0.13"
|
||||
zip = { version = "9", default-features = false, features = ["deflate"] }
|
||||
zstd = "0.14"
|
||||
|
||||
[profile.release]
|
||||
incremental = true
|
||||
|
||||
@@ -14,7 +14,7 @@ Modifications relative to the upstream work (Apache License 2.0 §4(b) notice):
|
||||
subscription-proxy endpoints.
|
||||
- Endpoints re-targeted at the Kimi Code subscription API
|
||||
(api.kimi.com/coding/v1), the Moonshot open platform (api.moonshot.cn/v1,
|
||||
api.moonshot.ai/v1), and Gitea Releases (git.zacharyzhang.com) for self-update.
|
||||
api.moonshot.ai/v1), and GitHub Releases for self-update.
|
||||
|
||||
This product includes code ported from openai/codex and sst/opencode; see
|
||||
crates/codegen/kigi-tools/THIRD_PARTY_NOTICES.md for the license terms and
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
# Security Policy
|
||||
|
||||
Kigi is a community build; report vulnerabilities on the
|
||||
[Kigi issue tracker](https://git.zacharyzhang.com/ZacharyZhang-NY/Kigi-CLI/issues).
|
||||
[Kigi issue tracker](https://github.com/ELY-Open-Source/Kigi-CLI/issues).
|
||||
Issues there are public, so please leave out any detail that would make a
|
||||
report directly exploitable — open with the affected area and impact, and a
|
||||
maintainer will follow up for the rest.
|
||||
|
||||
+261
-876
File diff suppressed because it is too large.
Load diff
@@ -43,3 +43,11 @@ targets = [
|
||||
# SPDX expression parsing cannot classify on its own.
|
||||
[ring]
|
||||
accepted = ["ISC", "MIT", "OpenSSL"]
|
||||
|
||||
# tonic 0.14.9 sources carry MIT headers; take only LICENSE.
|
||||
[tonic.clarify]
|
||||
license = "MIT"
|
||||
|
||||
[[tonic.clarify.files]]
|
||||
path = "LICENSE"
|
||||
checksum = "5c686e0f7978412b49187ae0e9f77e9b52eea9d8d2e6c0de8694b35817d873b1"
|
||||
@@ -21,7 +21,7 @@ pub struct KigiEndpoints {
|
||||
pub const PRODUCTION_ENDPOINTS: KigiEndpoints = KigiEndpoints {
|
||||
coding_api_base_url: "https://api.kimi.com/coding/v1",
|
||||
oauth_host: "https://auth.kimi.com",
|
||||
update_base_url: "https://git.zacharyzhang.com/api/v1/repos/ZacharyZhang-NY/Kigi-CLI/releases",
|
||||
update_base_url: "https://api.github.com/repos/ELY-Open-Source/Kigi-CLI/releases",
|
||||
upgrade_page_url: "https://www.kimi.com/code/",
|
||||
};
|
||||
|
||||
|
||||
@@ -103,7 +103,6 @@ infer = "0.15"
|
||||
image = { workspace = true, features = ["png", "jpeg", "gif", "webp"] }
|
||||
moka = { workspace = true, features = ["future"] }
|
||||
base64 = { workspace = true }
|
||||
jsonwebtoken = { version = "10", features = ["rust_crypto"] }
|
||||
sha2 = { workspace = true }
|
||||
rand = { workspace = true }
|
||||
shlex = { workspace = true }
|
||||
@@ -147,7 +146,6 @@ kigi-http = { workspace = true }
|
||||
kigi-models = { workspace = true }
|
||||
flate2 = { workspace = true }
|
||||
fs2 = { workspace = true }
|
||||
zstd = { workspace = true }
|
||||
tar = { workspace = true }
|
||||
url = { workspace = true }
|
||||
kigi-secrets = { path = "../kigi-secrets" }
|
||||
@@ -194,7 +192,6 @@ kigi-config = { workspace = true, features = ["test-support"] }
|
||||
ring = { workspace = true }
|
||||
tar = { workspace = true }
|
||||
flate2 = { workspace = true }
|
||||
rsa = { workspace = true }
|
||||
semver = { workspace = true }
|
||||
serial_test = { workspace = true }
|
||||
# Test-only builds expose `env::EnvVarGuard` and the cpu_profile test seams to
|
||||
|
||||
@@ -12,7 +12,7 @@ use std::sync::Arc;
|
||||
use serde::Serialize;
|
||||
|
||||
/// Where non-subscription users (no OAuth session) submit feedback instead.
|
||||
pub const FEEDBACK_ISSUES_URL: &str = "https://git.zacharyzhang.com/ZacharyZhang-NY/Kigi-CLI/issues";
|
||||
pub const FEEDBACK_ISSUES_URL: &str = "https://github.com/ELY-Open-Source/Kigi-CLI/issues/new";
|
||||
|
||||
/// HTTP error from the feedback endpoint with a preserved status code, so
|
||||
/// callers can distinguish auth failures (401) without string matching.
|
||||
|
||||
@@ -31,11 +31,7 @@ infer = { workspace = true }
|
||||
globset = { workspace = true }
|
||||
image = { workspace = true, features = ["png", "jpeg", "gif", "webp", "bmp", "tiff", "ico"] }
|
||||
pdf_oxide = { workspace = true }
|
||||
# PPTX text extraction (implementations/read_file/pptx.rs). Deliberately NOT
|
||||
# `workspace = true`: the workspace `zip` pin has default features on, which
|
||||
# drag aes/bzip2/lzma/zstd into the shipped pager binary. PPTX entries are
|
||||
# only ever stored or deflated.
|
||||
zip = { version = "3", default-features = false, features = ["deflate-flate2"] }
|
||||
zip = { workspace = true }
|
||||
quick-xml = { workspace = true }
|
||||
indexmap = { workspace = true, features = ["serde"] }
|
||||
minijinja = { version = "2", features = ["custom_syntax"] }
|
||||
|
||||
@@ -106,7 +106,8 @@ mod linux {
|
||||
// SAFETY: `raw` comes from a successful `inotify_init1`, so it is a
|
||||
// live fd that nothing else owns.
|
||||
let owned = unsafe { OwnedFd::from_raw_fd(raw) };
|
||||
let fd = AsyncFd::with_interest(owned, Interest::READABLE)?;
|
||||
// SAFETY: the AsyncFd owns `owned`, so the fd stays open and fixed.
|
||||
let fd = unsafe { AsyncFd::register_with_interest(owned, Interest::READABLE) }?;
|
||||
Ok(Inotify { fd })
|
||||
}
|
||||
|
||||
|
||||
@@ -31,10 +31,14 @@ pub(crate) fn extract_pptx_text_from_bytes(bytes: &[u8]) -> Result<String, Strin
|
||||
let mut archive = ZipArchive::new(Cursor::new(bytes))
|
||||
.map_err(|e| format!("Failed to open PPTX archive: {e}"))?;
|
||||
|
||||
let names = archive
|
||||
.file_names()
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
.map_err(|e| format!("Failed to read PPTX entry names: {e}"))?;
|
||||
// Collect slide numbers from `ppt/slides/slideN.xml` entries and sort
|
||||
// numerically so slide ordering matches the presentation.
|
||||
let mut slide_numbers: Vec<u32> = archive
|
||||
.file_names()
|
||||
let mut slide_numbers: Vec<u32> = names
|
||||
.iter()
|
||||
.filter_map(|name| {
|
||||
name.strip_prefix("ppt/slides/slide")?
|
||||
.strip_suffix(".xml")?
|
||||
|
||||
@@ -10,7 +10,7 @@ use crate::slash::command::{AppCtx, ArgItem, CommandExecCtx, CommandResult, Slas
|
||||
|
||||
/// Online docs landing page (hardcoded like other TUI deep-links; the
|
||||
/// project README is the docs entry point for the repo-hosted docs).
|
||||
pub const BUILD_DOCS_URL: &str = "https://git.zacharyzhang.com/ZacharyZhang-NY/Kigi-CLI/src/branch/main/README.md";
|
||||
pub const BUILD_DOCS_URL: &str = "https://github.com/ELY-Open-Source/Kigi-CLI/blob/main/README.md";
|
||||
|
||||
/// Open How-to Guides or online Build docs.
|
||||
pub struct DocsCommand;
|
||||
|
||||
@@ -6,7 +6,7 @@ use crate::slash::command::{CommandExecCtx, CommandResult, SlashCommand};
|
||||
/// Where feedback goes: the project's own issue tracker. Kigi is a community
|
||||
/// build, so its feedback belongs on its own repo — mirroring the official
|
||||
/// kimi-cli, whose `/feedback` opens its repo's issues page.
|
||||
pub const FEEDBACK_ISSUES_URL: &str = "https://git.zacharyzhang.com/ZacharyZhang-NY/Kigi-CLI/issues";
|
||||
pub const FEEDBACK_ISSUES_URL: &str = "https://github.com/ELY-Open-Source/Kigi-CLI/issues/new";
|
||||
|
||||
/// Open the Kigi issue tracker in the browser.
|
||||
pub struct FeedbackCommand;
|
||||
|
||||
@@ -695,7 +695,7 @@ pub(crate) fn detect_platform() -> Result<(&'static str, &'static str)> {
|
||||
|
||||
/// Rust target triple for this build — the key that maps a platform to its
|
||||
/// release-asset name. Must stay in lockstep with the five targets built by
|
||||
/// `.gitea/workflows/release.yml` and the tables in install.sh/install.ps1.
|
||||
/// `.github/workflows/release.yml` and the tables in install.sh/install.ps1.
|
||||
pub(crate) fn target_triple() -> Result<&'static str> {
|
||||
let triple = if cfg!(all(target_os = "macos", target_arch = "aarch64")) {
|
||||
"aarch64-apple-darwin"
|
||||
@@ -1108,7 +1108,7 @@ fn extract_kigi_binary_blocking(archive: &Path, dest_tmp: &Path) -> Result<()> {
|
||||
for i in 0..zip.len() {
|
||||
let mut entry = zip.by_index(i)?;
|
||||
let base_name = entry
|
||||
.name()
|
||||
.name()?
|
||||
.rsplit(['/', '\\'])
|
||||
.next()
|
||||
.unwrap_or_default()
|
||||
@@ -2653,7 +2653,7 @@ mod tests {
|
||||
#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
|
||||
#[test]
|
||||
fn test_release_asset_name_matches_release_workflow_naming() {
|
||||
// Must stay in lockstep with .gitea/workflows/release.yml, which
|
||||
// Must stay in lockstep with .github/workflows/release.yml, which
|
||||
// publishes kigi-<version>-<target-triple>.{tar.gz|zip}.
|
||||
let triple = target_triple().unwrap();
|
||||
assert!(
|
||||
@@ -2798,6 +2798,52 @@ mod tests {
|
||||
assert!(extract_kigi_binary(&archive, &out).await.is_err());
|
||||
}
|
||||
|
||||
// Archive extraction (Windows: zip)
|
||||
|
||||
#[cfg(windows)]
|
||||
fn make_zip(entries: &[(&str, &[u8])]) -> Vec<u8> {
|
||||
use std::io::Write as _;
|
||||
let mut writer = zip::ZipWriter::new(std::io::Cursor::new(Vec::new()));
|
||||
for (name, data) in entries {
|
||||
writer
|
||||
.start_file(*name, zip::write::SimpleFileOptions::default())
|
||||
.unwrap();
|
||||
writer.write_all(data).unwrap();
|
||||
}
|
||||
writer.finish().unwrap().into_inner()
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
#[tokio::test]
|
||||
async fn test_extract_kigi_binary_finds_kigi_exe_entry() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let archive = dir.path().join("kigi-0.1.0-test.zip");
|
||||
std::fs::write(
|
||||
&archive,
|
||||
make_zip(&[("LICENSE", b"license text"), ("kigi.exe", b"MZ binary")]),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let out = dir.path().join("kigi-extracted");
|
||||
extract_kigi_binary(&archive, &out).await.unwrap();
|
||||
assert_eq!(std::fs::read(&out).unwrap(), b"MZ binary");
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
#[tokio::test]
|
||||
async fn test_extract_kigi_binary_missing_exe_errors() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let archive = dir.path().join("kigi-0.1.0-test.zip");
|
||||
std::fs::write(&archive, make_zip(&[("LICENSE", b"license only")])).unwrap();
|
||||
|
||||
let out = dir.path().join("kigi-extracted");
|
||||
let err = extract_kigi_binary(&archive, &out).await.unwrap_err();
|
||||
assert!(
|
||||
format!("{err}").contains("no 'kigi.exe' binary"),
|
||||
"err: {err}"
|
||||
);
|
||||
}
|
||||
|
||||
// UpdateStatus serialization (camelCase contract for --json clients)
|
||||
|
||||
fn make_status() -> UpdateStatus {
|
||||
|
||||
@@ -10,7 +10,7 @@ const TTL_SECONDS_BEFORE_AUTO_UPDATE: Duration = Duration::from_secs(60 * 30);
|
||||
|
||||
/// Release channel: this repo's Releases (PRD F8). The API base is resolved
|
||||
/// through [`kigi_env::update_base_url`] — production default
|
||||
/// `https://git.zacharyzhang.com/api/v1/repos/ZacharyZhang-NY/Kigi-CLI/releases`,
|
||||
/// `https://api.github.com/repos/ELY-Open-Source/Kigi-CLI/releases`,
|
||||
/// overridable via `KIGI_UPDATE_BASE_URL` for mirrors and tests.
|
||||
pub(crate) fn update_base_url() -> String {
|
||||
kigi_env::update_base_url()
|
||||
@@ -533,7 +533,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_release_json_parses_github_wire_shape() {
|
||||
let json = r#"{
|
||||
"url": "https://git.zacharyzhang.com/api/v1/repos/ZacharyZhang-NY/Kigi-CLI/releases/1",
|
||||
"url": "https://api.github.com/repos/ELY-Open-Source/Kigi-CLI/releases/1",
|
||||
"tag_name": "v0.1.0",
|
||||
"name": "Kigi 0.1.0",
|
||||
"draft": false,
|
||||
@@ -541,13 +541,13 @@ mod tests {
|
||||
"assets": [
|
||||
{
|
||||
"name": "kigi-0.1.0-aarch64-apple-darwin.tar.gz",
|
||||
"browser_download_url": "https://git.zacharyzhang.com/ZacharyZhang-NY/Kigi-CLI/releases/download/v0.1.0/kigi-0.1.0-aarch64-apple-darwin.tar.gz",
|
||||
"browser_download_url": "https://github.com/ELY-Open-Source/Kigi-CLI/releases/download/v0.1.0/kigi-0.1.0-aarch64-apple-darwin.tar.gz",
|
||||
"size": 123,
|
||||
"content_type": "application/gzip"
|
||||
},
|
||||
{
|
||||
"name": "SHA256SUMS",
|
||||
"browser_download_url": "https://git.zacharyzhang.com/ZacharyZhang-NY/Kigi-CLI/releases/download/v0.1.0/SHA256SUMS"
|
||||
"browser_download_url": "https://github.com/ELY-Open-Source/Kigi-CLI/releases/download/v0.1.0/SHA256SUMS"
|
||||
}
|
||||
]
|
||||
}"#;
|
||||
@@ -560,7 +560,7 @@ mod tests {
|
||||
let asset = r.asset("kigi-0.1.0-aarch64-apple-darwin.tar.gz").unwrap();
|
||||
assert_eq!(
|
||||
asset.browser_download_url,
|
||||
"https://git.zacharyzhang.com/ZacharyZhang-NY/Kigi-CLI/releases/download/v0.1.0/kigi-0.1.0-aarch64-apple-darwin.tar.gz"
|
||||
"https://github.com/ELY-Open-Source/Kigi-CLI/releases/download/v0.1.0/kigi-0.1.0-aarch64-apple-darwin.tar.gz"
|
||||
);
|
||||
assert_eq!(
|
||||
r.asset("SHA256SUMS").unwrap().name,
|
||||
|
||||
@@ -114,7 +114,7 @@ pub fn host_platform() -> String {
|
||||
}
|
||||
|
||||
/// Host Rust target triple, matching `auto_update::target_triple()` and the
|
||||
/// release-asset naming in `.gitea/workflows/release.yml`.
|
||||
/// release-asset naming in `.github/workflows/release.yml`.
|
||||
pub fn host_triple() -> &'static str {
|
||||
if cfg!(all(target_os = "macos", target_arch = "aarch64")) {
|
||||
"aarch64-apple-darwin"
|
||||
|
||||
@@ -5,11 +5,6 @@
|
||||
version = 2
|
||||
yanked = "deny"
|
||||
ignore = [
|
||||
# rsa: Marvin timing sidechannel. Reached only through jsonwebtoken's
|
||||
# RS256 *signature verification* in the enterprise-OIDC login path
|
||||
# (public-key operation; Marvin concerns private-key decryption). The
|
||||
# entire OIDC stack is replaced by the Kimi device flow in M1.
|
||||
{ id = "RUSTSEC-2023-0071", reason = "verification-only use; auth stack replaced in M1" },
|
||||
# quick-xml 0.39 (two advisories): pinned by wayland-scanner 0.31.10
|
||||
# (latest), a build-time proc-macro parsing vendored Wayland protocol
|
||||
# XML — no attacker-controlled input reaches it.
|
||||
@@ -25,6 +20,11 @@ ignore = [
|
||||
{ id = "RUSTSEC-2026-0192", reason = "rustybuzz via pdf_oxide/resvg (latest); local rendering" },
|
||||
{ id = "RUSTSEC-2026-0195", reason = "ttf-parser via fontdb/resvg (latest); local font parsing" },
|
||||
{ id = "RUSTSEC-2024-0320", reason = "yaml-rust via syntect (latest); parses bundled syntax defs" },
|
||||
{ id = "RUSTSEC-2024-0449", reason = "unsafe-libyaml via serde_yaml 0.9 (final release)" },
|
||||
# zbus 6 absorbed these crates; dark-light 3 (latest) still needs zbus 5.
|
||||
{ id = "RUSTSEC-2026-0370", reason = "zvariant via zbus 5" },
|
||||
{ id = "RUSTSEC-2026-0371", reason = "zbus_names via zbus 5" },
|
||||
{ id = "RUSTSEC-2026-0372", reason = "zvariant_derive via zbus 5" },
|
||||
]
|
||||
|
||||
[licenses]
|
||||
|
||||
+42
-129
@@ -1,26 +1,27 @@
|
||||
# Release checklist (PRD F8)
|
||||
|
||||
Kigi ships as a single-file binary for five targets, published on this
|
||||
repo's Gitea Releases by `.gitea/workflows/release.yml`. Users install via
|
||||
`install.sh` / `install.ps1` and stay current through the in-app
|
||||
self-updater (`kigi-update`), which resolves the same Releases API.
|
||||
|
||||
`.github/workflows/release.yml` is the retired GitHub pipeline. Gitea ignores
|
||||
`.github/workflows` entirely whenever `.gitea/workflows` is non-empty, so it
|
||||
does not run — it is kept only as a reference for the GitHub-hosted layout.
|
||||
repo's GitHub Releases
|
||||
(<https://github.com/ELY-Open-Source/Kigi-CLI/releases>) by
|
||||
`.github/workflows/release.yml`. Users install via `install.sh` /
|
||||
`install.ps1` and stay current through the in-app self-updater
|
||||
(`kigi-update`), which resolves the same Releases API.
|
||||
|
||||
## Cutting a release
|
||||
|
||||
1. Bump `[workspace.package] version` in `Cargo.toml`; land the change on
|
||||
`main` with green CI.
|
||||
2. Regenerate the third-party notices (not enforced by CI — this is the
|
||||
step that keeps `THIRD-PARTY-NOTICES.md` fresh):
|
||||
2. Regenerate the third-party notices on Linux (not enforced by CI — this
|
||||
is the step that keeps `THIRD-PARTY-NOTICES.md` fresh):
|
||||
|
||||
```sh
|
||||
cargo install cargo-about --locked # once
|
||||
cargo install cargo-about@0.9.2 --locked --features cli # once
|
||||
cargo about generate about.hbs -o THIRD-PARTY-NOTICES.md
|
||||
```
|
||||
|
||||
Keep cargo-about at 0.9.2: 0.9.3 pastes ring's source files in as
|
||||
license text. A Windows run lists a different crate set and order.
|
||||
|
||||
Commit the result if it changed.
|
||||
3. Tag and push:
|
||||
|
||||
@@ -34,15 +35,15 @@ does not run — it is kept only as a reference for the GitHub-hosted layout.
|
||||
`release-dist` profile, packages
|
||||
`kigi-<version>-<target-triple>.{tar.gz|zip}` archives (binary +
|
||||
LICENSE + NOTICE + THIRD-PARTY-NOTICES), generates `SHA256SUMS`, and
|
||||
publishes the Gitea Release. Tags containing `-` (e.g.
|
||||
publishes the GitHub Release. Tags containing `-` (e.g.
|
||||
`v0.2.0-alpha.1`) publish as pre-releases, which only the `alpha`
|
||||
update channel picks up.
|
||||
|
||||
The release is created as a **draft** and only flipped public once
|
||||
`SHA256SUMS` is attached, so `releases/latest` never hands the installer
|
||||
a release whose checksum manifest is still missing. A failed run leaves
|
||||
the draft in place; re-pushing the tag reuses it rather than erroring on
|
||||
a duplicate `tag_name`.
|
||||
the draft in place; re-running the workflow reuses it rather than
|
||||
erroring on a duplicate `tag_name`.
|
||||
5. Smoke-test an installed artifact:
|
||||
|
||||
```sh
|
||||
@@ -52,127 +53,39 @@ does not run — it is kept only as a reference for the GitHub-hosted layout.
|
||||
|
||||
## Build runners
|
||||
|
||||
Gitea has no hosted runners, so all three `runs-on` labels below are machines
|
||||
we register ourselves with `gitea-runner` (the binary formerly called
|
||||
`act_runner`). Labels are declared in the runner's `config.yaml` as
|
||||
`<label>:host` (run directly on the machine) or `<label>:docker://<image>` (run
|
||||
in a container) — with `gitea-runner` v2, `register --labels` is ignored
|
||||
whenever a config file supplies them.
|
||||
Every leg runs on a GitHub-hosted runner; none needs local state, so no
|
||||
self-hosted runner is involved. The repo is public, so keep it that way: a
|
||||
self-hosted runner must never be reachable from a `pull_request` event, and
|
||||
this workflow only triggers on tag pushes.
|
||||
|
||||
| Label | Machine | Mode | Builds |
|
||||
| ---------------- | ------------------------------ | ------ | -------------------------------------------------- |
|
||||
| `ubuntu-latest` | the Linux server | docker | `x86_64-unknown-linux-gnu`, `aarch64-unknown-linux-gnu` |
|
||||
| `macos-arm64` | Mac Mini (M4) | host | `aarch64-apple-darwin`, `x86_64-apple-darwin` |
|
||||
| `windows-amd64` | RaidenMei (Windows PC) | host | `x86_64-pc-windows-msvc` |
|
||||
| Runner | Builds |
|
||||
| ------------------ | ------------------------------------------------------- |
|
||||
| `ubuntu-latest` | `x86_64-unknown-linux-gnu` |
|
||||
| `ubuntu-24.04-arm` | `aarch64-unknown-linux-gnu` (native, no cross toolchain) |
|
||||
| `macos-latest` | `aarch64-apple-darwin`, `x86_64-apple-darwin` |
|
||||
| `windows-latest` | `x86_64-pc-windows-msvc` |
|
||||
|
||||
The Linux legs use `ubuntu-latest` because that is what the Linux server's
|
||||
runner already advertises. That image is a bare runner-image, so those legs
|
||||
provision their own apt packages and rustup per run (`rustup show` then picks
|
||||
up the `rust-toolchain.toml` pin). If you register a dedicated
|
||||
`linux-x86_64:docker://…` runner later, change the three Linux `runs-on`
|
||||
values back to match it.
|
||||
`macos-latest` is Apple Silicon; `x86_64-apple-darwin` is a cross-compile
|
||||
against the same SDK. The Darwin targets need the real Apple linker
|
||||
(`.cargo/config.toml` passes `-ObjC` and `-undefined dynamic_lookup`), so they
|
||||
cannot move to a Linux runner.
|
||||
|
||||
**The Mac is not optional.** Apple's SDK licence limits macOS builds to
|
||||
Apple-branded hardware, and the Darwin targets need the real Apple linker
|
||||
anyway (`.cargo/config.toml` passes `-ObjC` and `-undefined dynamic_lookup`).
|
||||
There is no supported way to produce our macOS artifacts on the Linux server.
|
||||
One Apple Silicon Mac covers both Darwin targets — `x86_64-apple-darwin` is a
|
||||
cross-compile against the same SDK, exactly as the old GitHub `macos-14`
|
||||
runner did it.
|
||||
`windows-latest` ships the VS Build Tools the static MSVC CRT link needs
|
||||
(`ring`, `mimalloc`, `zstd-sys` and `libz-sys` build with
|
||||
`-C target-feature=+crt-static`). Every job installs protoc
|
||||
(`PROTOC_VERSION`, matching the `bin/protoc` dotslash pin) and runs
|
||||
`rustup show` to materialise the `rust-toolchain.toml` pin; the arm64 Linux
|
||||
leg installs rustup first if the image lacks it.
|
||||
|
||||
Windows is a softer requirement but still wants a real machine: the tree links
|
||||
`ring`, `mimalloc`, `zstd-sys` and `libz-sys` against a static MSVC CRT
|
||||
(`-C target-feature=+crt-static`). Cross-compiling that from Linux with
|
||||
`cargo-xwin` is possible but means debugging four C builds under `clang-cl`;
|
||||
a Windows runner with the VS 2022 C++ Build Tools reproduces today's binary
|
||||
exactly.
|
||||
The release steps use the preinstalled `gh` CLI with `secrets.GITHUB_TOKEN`
|
||||
(`permissions: contents: write`): `gh release create --draft`, then
|
||||
`gh release upload` per target, then `SHA256SUMS` and
|
||||
`gh release edit --draft=false`. Only the five checksum lines travel through
|
||||
`actions/upload-artifact@v4`; the archives go straight to the release.
|
||||
|
||||
Linux arm64 *is* cross-compiled on the x86_64 box — the workflow installs
|
||||
`gcc-aarch64-linux-gnu` and points `cc-rs` at it. The one thing this loses is
|
||||
the ability to smoke-test the arm64 binary before publishing (the old GitHub
|
||||
pipeline did not test it either). Register a native arm64 runner and change
|
||||
that matrix leg's `runner:` if you want it built natively.
|
||||
|
||||
### Registering a runner
|
||||
|
||||
Get a registration token from **Settings → Actions → Runners** (repo scope),
|
||||
your user settings (all your repos) or the site admin panel (instance-wide).
|
||||
Over the API it is a **POST**, not a GET — a GET is parsed as runner id `0` and
|
||||
404s:
|
||||
|
||||
```sh
|
||||
curl -fsS -X POST -H "Authorization: token $GITEA_API_TOKEN" \
|
||||
https://git.zacharyzhang.com/api/v1/user/actions/runners/registration-token
|
||||
```
|
||||
|
||||
Write the labels into `config.yaml` first (see `runner.labels` in
|
||||
`gitea-runner generate-config`), then register on each machine:
|
||||
|
||||
```sh
|
||||
# Linux (the Linux server) — container mode
|
||||
gitea-runner --config config.yaml register --no-interactive \
|
||||
--instance https://git.zacharyzhang.com \
|
||||
--token <REGISTRATION_TOKEN> \
|
||||
--name kigi-linux-x86_64
|
||||
|
||||
# macOS (Apple Silicon) — host mode, needs Xcode CLT + rustup + Node on PATH
|
||||
gitea-runner --config config.yaml register --no-interactive \
|
||||
--instance https://git.zacharyzhang.com \
|
||||
--token <REGISTRATION_TOKEN> \
|
||||
--name kigi-macos-arm64
|
||||
|
||||
# Windows — host mode, needs VS 2022 Build Tools + rustup + Node on PATH
|
||||
gitea-runner --config config.yaml register --no-interactive `
|
||||
--instance https://git.zacharyzhang.com `
|
||||
--token <REGISTRATION_TOKEN> `
|
||||
--name kigi-windows-amd64
|
||||
```
|
||||
|
||||
Host-mode runners execute steps with the daemon's own environment, so each
|
||||
needs its build prerequisites installed up front — and the supervisor that
|
||||
launches the daemon must put them on `PATH`:
|
||||
|
||||
- **macOS**: `xcode-select --install`, `rustup`, and Node (for
|
||||
`actions/checkout`, which is a JavaScript action).
|
||||
- **Windows**: VS 2022 Build Tools with the "Desktop development with C++"
|
||||
workload, `rustup`, Git for Windows, and Node. Every Windows step in the
|
||||
workflow uses `shell: powershell` (5.1) — never `bash`, which on a normal
|
||||
Windows box resolves to WSL.
|
||||
- **Linux (docker mode)**: nothing on the host — the workflow installs
|
||||
`build-essential`, `jq`, `unzip`, protoc, rustup and the cross toolchain
|
||||
inside the container per run.
|
||||
|
||||
### Keeping the runners alive
|
||||
|
||||
Each host-mode runner is supervised so it survives reboots and crashes. Both
|
||||
supervisors export `CARGO_HOME`/`RUSTUP_HOME` and prepend the toolchain, git
|
||||
and node directories to `PATH`, because host-mode jobs inherit exactly the
|
||||
daemon's environment.
|
||||
|
||||
| Machine | Supervisor | Manage with |
|
||||
| -------- | --------------------------------------------- | ------------------------------------------------------ |
|
||||
| Windows | Task Scheduler task `Gitea Runner (Kigi)` running `C:\Users\zhang\gitea-runner\run-runner.ps1` | `Get-ScheduledTask`, `Start-ScheduledTask`, `Stop-ScheduledTask` |
|
||||
| macOS | LaunchAgent `com.kigi.gitea-runner` (`KeepAlive`) | `launchctl kickstart -k gui/$(id -u)/com.kigi.gitea-runner` |
|
||||
|
||||
`prompt.txt` at the repo root is a one-shot setup prompt for the Mac Mini leg.
|
||||
Both runners also expose a liveness probe on `http://127.0.0.1:9101/healthz`.
|
||||
|
||||
### Gitea-specific things that differ from GitHub
|
||||
|
||||
- Workflows live in `.gitea/workflows/`. Once that directory is non-empty,
|
||||
`.github/workflows/` is ignored completely — you cannot run both.
|
||||
- The automatic token is `secrets.GITEA_TOKEN`, and the release steps call the
|
||||
Gitea API directly (`POST /releases`, `POST /releases/{id}/assets`,
|
||||
`PATCH /releases/{id}`) rather than `softprops/action-gh-release`, which
|
||||
targets GitHub's API and does not work here.
|
||||
- `uses:` actions are fetched from `github.com` by default
|
||||
(`DEFAULT_ACTIONS_URL`), so the runners need outbound access to it — our
|
||||
GitHub *account* being suspended does not affect downloading public actions.
|
||||
Absolute URLs (`uses: https://gitea.com/actions/checkout@v4`) work too.
|
||||
- Artifacts carry only the five checksum lines; the archives themselves go
|
||||
straight to the release. If `actions/upload-artifact@v3` misbehaves on the
|
||||
instance, the fallback is to drop the artifact steps and have `publish`
|
||||
download the archives from the release and hash them there.
|
||||
Build caches come from `Swatinem/rust-cache`. GitHub only lets a tag run
|
||||
restore caches made on its own ref or the default branch, and nothing builds
|
||||
on `main`, so a tag build starts cold; the cache helps re-runs of the same tag.
|
||||
|
||||
## Invariants to keep in lockstep
|
||||
|
||||
|
||||
+2
-2
@@ -23,8 +23,8 @@ the `kigi-frontend` Worker on `kigicli.dev` and `www.kigicli.dev`.
|
||||
Assets are matched first and served directly. Requests with no matching file
|
||||
fall through to the Worker, which owns:
|
||||
|
||||
- `GET /install.sh` — proxies `install.sh` from the Kigi repo on Gitea
|
||||
- `GET /install.ps1` — proxies `install.ps1` from the Kigi repo on Gitea
|
||||
- `GET /install.sh` — proxies `install.sh` from the Kigi repo on GitHub
|
||||
- `GET /install.ps1` — proxies `install.ps1` from the Kigi repo on GitHub
|
||||
- `GET /health` — plain-text liveness check
|
||||
- everything else — `env.ASSETS.fetch()`, which serves `index.html` for unknown
|
||||
paths (single-page-application fallback)
|
||||
|
||||
+1
-1
@@ -11,4 +11,4 @@ Error generating stack: `+e.message+`
|
||||
<path d="M12 16.25C11.5858 16.25 11.25 16.5858 11.25 17C11.25 17.4142 11.5858 17.75 12 17.75H17C17.4142 17.75 17.75 17.4142 17.75 17C17.75 16.5858 17.4142 16.25 17 16.25H12Z" fill="currentColor"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M18.1318 2.25H5.86821C5.12513 2.24999 4.52196 2.24999 4.03273 2.28996C3.52778 2.33121 3.07851 2.41876 2.66103 2.63148C2.00247 2.96703 1.46703 3.50247 1.13148 4.16103C0.918762 4.57851 0.831214 5.02778 0.789958 5.53273C0.749986 6.02196 0.749993 6.62511 0.75 7.36819V16.6318C0.749993 17.3749 0.749986 17.978 0.789958 18.4673C0.831214 18.9722 0.918762 19.4215 1.13148 19.839C1.46703 20.4975 2.00247 21.033 2.66103 21.3685C3.07851 21.5812 3.52778 21.6688 4.03273 21.71C4.52195 21.75 5.12507 21.75 5.86811 21.75H18.1318C18.8748 21.75 19.4781 21.75 19.9673 21.71C20.4722 21.6688 20.9215 21.5812 21.339 21.3685C21.9975 21.033 22.533 20.4975 22.8685 19.839C23.0812 19.4215 23.1688 18.9722 23.21 18.4673C23.25 17.9781 23.25 17.3749 23.25 16.6319V7.36819C23.25 6.62515 23.25 6.02195 23.21 5.53273C23.1688 5.02778 23.0812 4.57851 22.8685 4.16103C22.533 3.50247 21.9975 2.96703 21.339 2.63148C20.9215 2.41876 20.4722 2.33121 19.9673 2.28996C19.478 2.24999 18.8749 2.24999 18.1318 2.25ZM21.75 7.25C21.7498 6.54743 21.7472 6.04838 21.715 5.65488C21.6813 5.24269 21.619 5.0128 21.532 4.84202C21.3403 4.4657 21.0343 4.15973 20.658 3.96799C20.4872 3.88097 20.2573 3.81865 19.8451 3.78498C19.4242 3.75058 18.8824 3.75 18.1 3.75H5.9C5.11755 3.75 4.57582 3.75058 4.15488 3.78498C3.74269 3.81865 3.5128 3.88097 3.34202 3.96799C2.9657 4.15973 2.65973 4.4657 2.46799 4.84202C2.38097 5.0128 2.31865 5.24269 2.28498 5.65488C2.25283 6.04838 2.25022 6.54743 2.25002 7.25H21.75ZM2.25 8.75H21.75V16.6C21.75 17.3824 21.7494 17.9242 21.715 18.3451C21.6813 18.7573 21.619 18.9872 21.532 19.158C21.3403 19.5343 21.0343 19.8403 20.658 20.032C20.4872 20.119 20.2573 20.1813 19.8451 20.215C19.4242 20.2494 18.8824 20.25 18.1 20.25H5.9C5.11755 20.25 4.57582 20.2494 4.15488 20.215C3.74269 20.1813 3.5128 20.119 3.34202 20.032C2.9657 19.8403 2.65973 19.5343 2.46799 19.158C2.38097 18.9872 2.31865 18.7573 2.28498 18.3451C2.25058 17.9242 2.25 17.3824 2.25 16.6V8.75Z" fill="currentColor"/>`,F:`<path d="M7.46967 10.4697C7.76256 10.1768 8.23744 10.1768 8.53033 10.4697L11.5303 13.4697C11.8232 13.7626 11.8232 14.2374 11.5303 14.5303L8.53033 17.5303C8.23744 17.8232 7.76256 17.8232 7.46967 17.5303C7.17678 17.2374 7.17678 16.7626 7.46967 16.4697L9.93934 14L7.46967 11.5303C7.17678 11.2374 7.17678 10.7626 7.46967 10.4697Z" fill="currentColor"/>
|
||||
<path d="M12 16.25C11.5858 16.25 11.25 16.5858 11.25 17C11.25 17.4142 11.5858 17.75 12 17.75H17C17.4142 17.75 17.75 17.4142 17.75 17C17.75 16.5858 17.4142 16.25 17 16.25H12Z" fill="currentColor"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M4.03273 2.28996C4.52196 2.24999 5.12511 2.24999 5.86819 2.25H18.1318C18.8749 2.24999 19.478 2.24999 19.9673 2.28996C20.4722 2.33121 20.9215 2.41876 21.339 2.63148C21.9975 2.96703 22.533 3.50247 22.8685 4.16103C23.0812 4.57851 23.1688 5.02778 23.21 5.53273C23.25 6.02195 23.25 6.62507 23.25 7.36811V16.6318C23.25 17.3748 23.25 17.9781 23.21 18.4673C23.1688 18.9722 23.0812 19.4215 22.8685 19.839C22.533 20.4975 21.9975 21.033 21.339 21.3685C20.9215 21.5812 20.4722 21.6688 19.9673 21.71C19.4781 21.75 18.8749 21.75 18.1319 21.75H5.86819C5.12515 21.75 4.52195 21.75 4.03273 21.71C3.52778 21.6688 3.07851 21.5812 2.66103 21.3685C2.00247 21.033 1.46703 20.4975 1.13148 19.839C0.918762 19.4215 0.831214 18.9722 0.789958 18.4673C0.749986 17.978 0.749993 17.3749 0.75 16.6318V7.36821C0.749993 6.62513 0.749986 6.02196 0.789958 5.53273C0.831214 5.02778 0.918762 4.57851 1.13148 4.16103C1.46703 3.50247 2.00247 2.96703 2.66103 2.63148C3.07851 2.41876 3.52778 2.33121 4.03273 2.28996ZM2.25 8.75V16.6C2.25 17.3824 2.25058 17.9242 2.28498 18.3451C2.31865 18.7573 2.38097 18.9872 2.46799 19.158C2.65973 19.5343 2.9657 19.8403 3.34202 20.032C3.5128 20.119 3.74269 20.1813 4.15488 20.215C4.57582 20.2494 5.11755 20.25 5.9 20.25H18.1C18.8824 20.25 19.4242 20.2494 19.8451 20.215C20.2573 20.1813 20.4872 20.119 20.658 20.032C21.0343 19.8403 21.3403 19.5343 21.532 19.158C21.619 18.9872 21.6813 18.7573 21.715 18.3451C21.7494 17.9242 21.75 17.3824 21.75 16.6V8.75H2.25Z" fill="currentColor"/>`}),m=d(`Check`,{O:`<path d="M21.5303 5.46967C21.8232 5.76256 21.8232 6.23744 21.5303 6.53033L9.53033 18.5303C9.23744 18.8232 8.76256 18.8232 8.46967 18.5303L2.46967 12.5303C2.17678 12.2374 2.17678 11.7626 2.46967 11.4697C2.76256 11.1768 3.23744 11.1768 3.53033 11.4697L9 16.9393L20.4697 5.46967C20.7626 5.17678 21.2374 5.17678 21.5303 5.46967Z" fill="currentColor"/>`,F:`<path d="M21.7071 5.29289C22.0976 5.68342 22.0976 6.31658 21.7071 6.70711L9.70711 18.7071C9.31658 19.0976 8.68342 19.0976 8.29289 18.7071L2.29289 12.7071C1.90237 12.3166 1.90237 11.6834 2.29289 11.2929C2.68342 10.9024 3.31658 10.9024 3.70711 11.2929L9 16.5858L20.2929 5.29289C20.6834 4.90237 21.3166 4.90237 21.7071 5.29289Z" fill="currentColor"/>`}),h=d(`ChevronDown`,{F:`<g transform="scale(1.33333)"><path d="M9,13.5c-.192,0-.384-.073-.53-.22L2.22,7.03c-.293-.293-.293-.768,0-1.061s.768-.293,1.061,0l5.72,5.72,5.72-5.72c.293-.293,.768-.293,1.061,0s.293,.768,0,1.061l-6.25,6.25c-.146,.146-.338,.22-.53,.22Z" fill="currentColor"></path></g>`,O:`<g transform="scale(1.33333)"><polyline points="15.25 6.5 9 12.75 2.75 6.5" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"></polyline></g>`}),g=d(`Code`,{O:`<path d="M14.1809 4.2755C14.581 4.3827 14.8185 4.79396 14.7113 5.19406L10.7377 20.0238C10.6304 20.4239 10.2192 20.6613 9.81909 20.5541C9.41899 20.4469 9.18156 20.0356 9.28876 19.6355L13.2624 4.80583C13.3696 4.40573 13.7808 4.16829 14.1809 4.2755Z" fill="currentColor"/><path d="M16.4425 7.32781C16.7196 7.01993 17.1938 6.99497 17.5017 7.27206L19.2392 8.8358C19.9756 9.49847 20.5864 10.0482 21.0058 10.5467C21.4468 11.071 21.7603 11.6342 21.7603 12.3295C21.7603 13.0248 21.4468 13.5881 21.0058 14.1123C20.5864 14.6109 19.9756 15.1606 19.2392 15.8233L17.5017 17.387C17.1938 17.6641 16.7196 17.6391 16.4425 17.3313C16.1654 17.0234 16.1904 16.5492 16.4983 16.2721L18.1947 14.7452C18.9826 14.0362 19.5138 13.5558 19.8579 13.1467C20.1882 12.7541 20.2603 12.525 20.2603 12.3295C20.2603 12.1341 20.1882 11.9049 19.8579 11.5123C19.5138 11.1033 18.9826 10.6229 18.1947 9.91383L16.4983 8.387C16.1904 8.10991 16.1654 7.63569 16.4425 7.32781Z" fill="currentColor"/><path d="M7.50178 8.387C7.80966 8.10991 7.83462 7.63569 7.55752 7.32781C7.28043 7.01993 6.80621 6.99497 6.49833 7.27206L4.76084 8.8358C4.0245 9.49847 3.41369 10.0482 2.99428 10.5467C2.55325 11.071 2.23975 11.6342 2.23975 12.3295C2.23975 13.0248 2.55325 13.5881 2.99428 14.1123C3.41369 14.6109 4.02449 15.1606 4.76082 15.8232L6.49833 17.387C6.80621 17.6641 7.28043 17.6391 7.55752 17.3313C7.83462 17.0234 7.80966 16.5492 7.50178 16.2721L5.80531 14.7452C5.01743 14.0362 4.48623 13.5558 4.14213 13.1467C3.81188 12.7541 3.73975 12.525 3.73975 12.3295C3.73975 12.1341 3.81188 11.9049 4.14213 11.5123C4.48623 11.1033 5.01743 10.6229 5.80531 9.91383L7.50178 8.387Z" fill="currentColor"/>`,F:`<path d="M14.1809 4.2755C14.581 4.3827 14.8185 4.79396 14.7113 5.19406L10.7377 20.0238C10.6304 20.4239 10.2192 20.6613 9.81909 20.5541C9.41899 20.4469 9.18156 20.0356 9.28876 19.6355L13.2624 4.80583C13.3696 4.40573 13.7808 4.16829 14.1809 4.2755Z" fill="currentColor"/><path d="M16.4425 7.32781C16.7196 7.01993 17.1938 6.99497 17.5017 7.27206L19.2392 8.8358C19.9756 9.49847 20.5864 10.0482 21.0058 10.5467C21.4468 11.071 21.7603 11.6342 21.7603 12.3295C21.7603 13.0248 21.4468 13.5881 21.0058 14.1123C20.5864 14.6109 19.9756 15.1606 19.2392 15.8233L17.5017 17.387C17.1938 17.6641 16.7196 17.6391 16.4425 17.331Line truncated
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M4.03273 2.28996C4.52196 2.24999 5.12511 2.24999 5.86819 2.25H18.1318C18.8749 2.24999 19.478 2.24999 19.9673 2.28996C20.4722 2.33121 20.9215 2.41876 21.339 2.63148C21.9975 2.96703 22.533 3.50247 22.8685 4.16103C23.0812 4.57851 23.1688 5.02778 23.21 5.53273C23.25 6.02195 23.25 6.62507 23.25 7.36811V16.6318C23.25 17.3748 23.25 17.9781 23.21 18.4673C23.1688 18.9722 23.0812 19.4215 22.8685 19.839C22.533 20.4975 21.9975 21.033 21.339 21.3685C20.9215 21.5812 20.4722 21.6688 19.9673 21.71C19.4781 21.75 18.8749 21.75 18.1319 21.75H5.86819C5.12515 21.75 4.52195 21.75 4.03273 21.71C3.52778 21.6688 3.07851 21.5812 2.66103 21.3685C2.00247 21.033 1.46703 20.4975 1.13148 19.839C0.918762 19.4215 0.831214 18.9722 0.789958 18.4673C0.749986 17.978 0.749993 17.3749 0.75 16.6318V7.36821C0.749993 6.62513 0.749986 6.02196 0.789958 5.53273C0.831214 5.02778 0.918762 4.57851 1.13148 4.16103C1.46703 3.50247 2.00247 2.96703 2.66103 2.63148C3.07851 2.41876 3.52778 2.33121 4.03273 2.28996ZM2.25 8.75V16.6C2.25 17.3824 2.25058 17.9242 2.28498 18.3451C2.31865 18.7573 2.38097 18.9872 2.46799 19.158C2.65973 19.5343 2.9657 19.8403 3.34202 20.032C3.5128 20.119 3.74269 20.1813 4.15488 20.215C4.57582 20.2494 5.11755 20.25 5.9 20.25H18.1C18.8824 20.25 19.4242 20.2494 19.8451 20.215C20.2573 20.1813 20.4872 20.119 20.658 20.032C21.0343 19.8403 21.3403 19.5343 21.532 19.158C21.619 18.9872 21.6813 18.7573 21.715 18.3451C21.7494 17.9242 21.75 17.3824 21.75 16.6V8.75H2.25Z" fill="currentColor"/>`}),m=d(`Check`,{O:`<path d="M21.5303 5.46967C21.8232 5.76256 21.8232 6.23744 21.5303 6.53033L9.53033 18.5303C9.23744 18.8232 8.76256 18.8232 8.46967 18.5303L2.46967 12.5303C2.17678 12.2374 2.17678 11.7626 2.46967 11.4697C2.76256 11.1768 3.23744 11.1768 3.53033 11.4697L9 16.9393L20.4697 5.46967C20.7626 5.17678 21.2374 5.17678 21.5303 5.46967Z" fill="currentColor"/>`,F:`<path d="M21.7071 5.29289C22.0976 5.68342 22.0976 6.31658 21.7071 6.70711L9.70711 18.7071C9.31658 19.0976 8.68342 19.0976 8.29289 18.7071L2.29289 12.7071C1.90237 12.3166 1.90237 11.6834 2.29289 11.2929C2.68342 10.9024 3.31658 10.9024 3.70711 11.2929L9 16.5858L20.2929 5.29289C20.6834 4.90237 21.3166 4.90237 21.7071 5.29289Z" fill="currentColor"/>`}),h=d(`ChevronDown`,{F:`<g transform="scale(1.33333)"><path d="M9,13.5c-.192,0-.384-.073-.53-.22L2.22,7.03c-.293-.293-.293-.768,0-1.061s.768-.293,1.061,0l5.72,5.72,5.72-5.72c.293-.293,.768-.293,1.061,0s.293,.768,0,1.061l-6.25,6.25c-.146,.146-.338,.22-.53,.22Z" fill="currentColor"></path></g>`,O:`<g transform="scale(1.33333)"><polyline points="15.25 6.5 9 12.75 2.75 6.5" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"></polyline></g>`}),g=d(`Code`,{O:`<path d="M14.1809 4.2755C14.581 4.3827 14.8185 4.79396 14.7113 5.19406L10.7377 20.0238C10.6304 20.4239 10.2192 20.6613 9.81909 20.5541C9.41899 20.4469 9.18156 20.0356 9.28876 19.6355L13.2624 4.80583C13.3696 4.40573 13.7808 4.16829 14.1809 4.2755Z" fill="currentColor"/><path d="M16.4425 7.32781C16.7196 7.01993 17.1938 6.99497 17.5017 7.27206L19.2392 8.8358C19.9756 9.49847 20.5864 10.0482 21.0058 10.5467C21.4468 11.071 21.7603 11.6342 21.7603 12.3295C21.7603 13.0248 21.4468 13.5881 21.0058 14.1123C20.5864 14.6109 19.9756 15.1606 19.2392 15.8233L17.5017 17.387C17.1938 17.6641 16.7196 17.6391 16.4425 17.3313C16.1654 17.0234 16.1904 16.5492 16.4983 16.2721L18.1947 14.7452C18.9826 14.0362 19.5138 13.5558 19.8579 13.1467C20.1882 12.7541 20.2603 12.525 20.2603 12.3295C20.2603 12.1341 20.1882 11.9049 19.8579 11.5123C19.5138 11.1033 18.9826 10.6229 18.1947 9.91383L16.4983 8.387C16.1904 8.10991 16.1654 7.63569 16.4425 7.32781Z" fill="currentColor"/><path d="M7.50178 8.387C7.80966 8.10991 7.83462 7.63569 7.55752 7.32781C7.28043 7.01993 6.80621 6.99497 6.49833 7.27206L4.76084 8.8358C4.0245 9.49847 3.41369 10.0482 2.99428 10.5467C2.55325 11.071 2.23975 11.6342 2.23975 12.3295C2.23975 13.0248 2.55325 13.5881 2.99428 14.1123C3.41369 14.6109 4.02449 15.1606 4.76082 15.8232L6.49833 17.387C6.80621 17.6641 7.28043 17.6391 7.55752 17.3313C7.83462 17.0234 7.80966 16.5492 7.50178 16.2721L5.80531 14.7452C5.01743 14.0362 4.48623 13.5558 4.14213 13.1467C3.81188 12.7541 3.73975 12.525 3.73975 12.3295C3.73975 12.1341 3.81188 11.9049 4.14213 11.5123C4.48623 11.1033 5.01743 10.6229 5.80531 9.91383L7.50178 8.387Z" fill="currentColor"/>`,F:`<path d="M14.1809 4.2755C14.581 4.3827 14.8185 4.79396 14.7113 5.19406L10.7377 20.0238C10.6304 20.4239 10.2192 20.6613 9.81909 20.5541C9.41899 20.4469 9.18156 20.0356 9.28876 19.6355L13.2624 4.80583C13.3696 4.40573 13.7808 4.16829 14.1809 4.2755Z" fill="currentColor"/><path d="M16.4425 7.32781C16.7196 7.01993 17.1938 6.99497 17.5017 7.27206L19.2392 8.8358C19.9756 9.49847 20.5864 10.0482 21.0058 10.5467C21.4468 11.071 21.7603 11.6342 21.7603 12.3295C21.7603 13.0248 21.4468 13.5881 21.0058 14.1123C20.5864 14.6109 19.9756 15.1606 19.2392 15.8233L17.5017 17.387C17.1938 17.6641 16.7196 17.6391 16.4425 17.331Line truncated
|
||||
@@ -16,11 +16,11 @@ interface Env {
|
||||
ASSETS: Fetcher;
|
||||
}
|
||||
|
||||
/** Raw-file base for the canonical Kigi repo (Gitea, `main` branch). */
|
||||
const UPSTREAM = "https://git.zacharyzhang.com/ZacharyZhang-NY/Kigi-CLI/raw/branch/main";
|
||||
/** Raw-file base for the canonical Kigi repo (GitHub, `main` branch). */
|
||||
const UPSTREAM = "https://raw.githubusercontent.com/ELY-Open-Source/Kigi-CLI/main";
|
||||
|
||||
/** Human-facing repo URL, used in the installer-unavailable message. */
|
||||
const REPO_URL = "https://git.zacharyzhang.com/ZacharyZhang-NY/Kigi-CLI";
|
||||
const REPO_URL = "https://github.com/ELY-Open-Source/Kigi-CLI";
|
||||
|
||||
interface Installer {
|
||||
file: string;
|
||||
|
||||
+3
-3
@@ -11,7 +11,7 @@
|
||||
# Environment:
|
||||
# KIGI_SHARE_DIR install root (default: %USERPROFILE%\.kigi)
|
||||
# KIGI_UPDATE_BASE_URL releases API base, GitHub/Gitea-shaped (default:
|
||||
# https://git.zacharyzhang.com/api/v1/repos/ZacharyZhang-NY/Kigi-CLI/releases)
|
||||
# https://api.github.com/repos/ELY-Open-Source/Kigi-CLI/releases)
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
@@ -26,8 +26,8 @@ function Fail([string]$Message) {
|
||||
exit 1
|
||||
}
|
||||
|
||||
$Repo = "ZacharyZhang-NY/Kigi-CLI"
|
||||
$ApiBase = if ($env:KIGI_UPDATE_BASE_URL) { $env:KIGI_UPDATE_BASE_URL } else { "https://git.zacharyzhang.com/api/v1/repos/$Repo/releases" }
|
||||
$Repo = "ELY-Open-Source/Kigi-CLI"
|
||||
$ApiBase = if ($env:KIGI_UPDATE_BASE_URL) { $env:KIGI_UPDATE_BASE_URL } else { "https://api.github.com/repos/$Repo/releases" }
|
||||
$KigiHome = if ($env:KIGI_SHARE_DIR) { $env:KIGI_SHARE_DIR } else { Join-Path $env:USERPROFILE ".kigi" }
|
||||
$Triple = "x86_64-pc-windows-msvc"
|
||||
|
||||
|
||||
+3
-3
@@ -14,14 +14,14 @@
|
||||
# Environment:
|
||||
# KIGI_SHARE_DIR install root (default: ~/.kigi)
|
||||
# KIGI_UPDATE_BASE_URL releases API base, GitHub/Gitea-shaped (default:
|
||||
# https://git.zacharyzhang.com/api/v1/repos/ZacharyZhang-NY/Kigi-CLI/releases)
|
||||
# https://api.github.com/repos/ELY-Open-Source/Kigi-CLI/releases)
|
||||
#
|
||||
# Fails fast on any error; never leaves a partial binary as the active kigi.
|
||||
|
||||
set -eu
|
||||
|
||||
REPO="ZacharyZhang-NY/Kigi-CLI"
|
||||
API_BASE="${KIGI_UPDATE_BASE_URL:-https://git.zacharyzhang.com/api/v1/repos/${REPO}/releases}"
|
||||
REPO="ELY-Open-Source/Kigi-CLI"
|
||||
API_BASE="${KIGI_UPDATE_BASE_URL:-https://api.github.com/repos/${REPO}/releases}"
|
||||
KIGI_HOME="${KIGI_SHARE_DIR:-$HOME/.kigi}"
|
||||
|
||||
err() {
|
||||
|
||||
Reference in new issue
Block a user