chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,320 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
|
||||
concurrency:
|
||||
group: ci-${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
SWIFT_VERSION: 6.3.3
|
||||
SWIFTLY_VERSION: 1.1.3
|
||||
SWIFTLY_SIGNING_FINGERPRINT: E813C892820A6FA13755B268F167DF1ACF9CE069
|
||||
|
||||
jobs:
|
||||
changes:
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 5
|
||||
outputs:
|
||||
macos-tests: ${{ steps.macos-tests.outputs.macos-tests }}
|
||||
macos-tests-reason: ${{ steps.macos-tests.outputs.macos-tests-reason }}
|
||||
changed-path-count: ${{ steps.macos-tests.outputs.changed-path-count }}
|
||||
steps:
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Detect macOS test impact
|
||||
id: macos-tests
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
|
||||
base_sha="${{ github.event.pull_request.base.sha }}"
|
||||
else
|
||||
base_sha="${{ github.event.before }}"
|
||||
fi
|
||||
|
||||
changed_paths="${RUNNER_TEMP}/changed-paths.txt"
|
||||
if [[ -z "$base_sha" || "$base_sha" =~ ^0+$ ]]; then
|
||||
git ls-files | awk '{ print "A\t" $0 }' > "$changed_paths"
|
||||
elif ! git cat-file -e "${base_sha}^{commit}" 2>/dev/null; then
|
||||
echo "Base commit ${base_sha} is unavailable; running macOS tests conservatively."
|
||||
git ls-files | awk '{ print "A\t" $0 }' > "$changed_paths"
|
||||
else
|
||||
git diff --name-status "$base_sha" "$GITHUB_SHA" > "$changed_paths"
|
||||
fi
|
||||
|
||||
printf 'Changed paths:\n'
|
||||
sed 's/^/- /' "$changed_paths"
|
||||
./Scripts/ci_macos_test_gate.sh "$changed_paths"
|
||||
|
||||
- name: Summarize macOS test gate
|
||||
if: ${{ always() }}
|
||||
shell: bash
|
||||
env:
|
||||
MACOS_TESTS: ${{ steps.macos-tests.outputs.macos-tests }}
|
||||
MACOS_TESTS_REASON: ${{ steps.macos-tests.outputs.macos-tests-reason }}
|
||||
CHANGED_PATH_COUNT: ${{ steps.macos-tests.outputs.changed-path-count }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
reason="${MACOS_TESTS_REASON:-<unset>}"
|
||||
reason="${reason//|/\\|}"
|
||||
{
|
||||
printf '### macOS test gate\n\n'
|
||||
printf '| Field | Value |\n'
|
||||
printf '| --- | --- |\n'
|
||||
printf '| macOS Swift tests required | `%s` |\n' "${MACOS_TESTS:-<unset>}"
|
||||
printf '| Reason | %s |\n' "$reason"
|
||||
printf '| Changed path entries | `%s` |\n' "${CHANGED_PATH_COUNT:-<unset>}"
|
||||
} >> "$GITHUB_STEP_SUMMARY"
|
||||
|
||||
lint:
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
|
||||
- name: Install lint tools
|
||||
run: ./Scripts/install_lint_tools.sh swiftlint
|
||||
|
||||
- name: Lint
|
||||
run: ./Scripts/lint.sh lint-linux
|
||||
|
||||
swift-test-macos:
|
||||
needs: changes
|
||||
if: ${{ needs.changes.outputs.macos-tests == 'true' }}
|
||||
runs-on: macos-15-intel
|
||||
timeout-minutes: 60
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
# Two shards amortize SwiftPM's per-shard discovery/cold build.
|
||||
# Each shard remains within the 50-minute Swift Test timeout.
|
||||
shard-index: [0, 1]
|
||||
shard-count: [2]
|
||||
steps:
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
|
||||
- name: Select Xcode 26.3 or 26.2
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# Both versions are part of the official macOS 15 runner image.
|
||||
for candidate in /Applications/Xcode_26.3.app /Applications/Xcode_26.2.app; do
|
||||
if [[ -d "$candidate" ]]; then
|
||||
sudo xcode-select -s "${candidate}/Contents/Developer"
|
||||
echo "DEVELOPER_DIR=${candidate}/Contents/Developer" >> "$GITHUB_ENV"
|
||||
break
|
||||
fi
|
||||
done
|
||||
[[ "$(/usr/bin/xcodebuild -version)" == Xcode\ 26.* ]]
|
||||
/usr/bin/xcodebuild -version
|
||||
|
||||
- name: Swift toolchain version
|
||||
run: |
|
||||
set -euo pipefail
|
||||
swift --version
|
||||
swift package --version
|
||||
|
||||
- name: Check app locales and Swift formatting
|
||||
if: ${{ matrix.shard-index == 0 }}
|
||||
run: ./Scripts/lint.sh lint-macos
|
||||
|
||||
- name: Swift Test
|
||||
# Keep small batches to reduce SwiftPM process overhead without returning to one aggregate run.
|
||||
timeout-minutes: 50
|
||||
run: |
|
||||
CODEXBAR_TEST_GROUP_SIZE=4 \
|
||||
CODEXBAR_TEST_SUITE_TIMEOUT=120 \
|
||||
CODEXBAR_TEST_RETRY_NON_TIMEOUT_FAILURES=0 \
|
||||
CODEXBAR_TEST_SHARD_INDEX=${{ matrix.shard-index }} \
|
||||
CODEXBAR_TEST_SHARD_COUNT=${{ matrix.shard-count }} \
|
||||
./Scripts/test.sh
|
||||
|
||||
- name: Summarize macOS shard
|
||||
if: ${{ always() }}
|
||||
shell: bash
|
||||
env:
|
||||
SHARD_INDEX: ${{ matrix.shard-index }}
|
||||
SHARD_COUNT: ${{ matrix.shard-count }}
|
||||
RUNS_LINT_MACOS: ${{ matrix.shard-index == 0 }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
display_shard_index=$((SHARD_INDEX + 1))
|
||||
xcode_version="$(/usr/bin/xcodebuild -version 2>/dev/null | tr '\n' ' ' || true)"
|
||||
{
|
||||
printf '### macOS Swift shard\n\n'
|
||||
printf '| Field | Value |\n'
|
||||
printf '| --- | --- |\n'
|
||||
printf '| Shard | `%s / %s` |\n' "$display_shard_index" "$SHARD_COUNT"
|
||||
printf '| Runner | `%s` |\n' "${RUNNER_NAME:-unknown}"
|
||||
printf '| Xcode | `%s` |\n' "${xcode_version:-unknown}"
|
||||
printf '| Runs lint-macos | `%s` |\n' "$RUNS_LINT_MACOS"
|
||||
} >> "$GITHUB_STEP_SUMMARY"
|
||||
|
||||
lint-build-test:
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 5
|
||||
needs:
|
||||
- changes
|
||||
- lint
|
||||
- swift-test-macos
|
||||
if: ${{ always() && !cancelled() }}
|
||||
steps:
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
|
||||
- name: Verify lint and macOS test jobs
|
||||
run: |
|
||||
./Scripts/ci_verify_test_jobs.sh \
|
||||
"${{ needs.lint.result }}" \
|
||||
"${{ needs.changes.result }}" \
|
||||
"${{ needs.changes.outputs.macos-tests }}" \
|
||||
"${{ needs.swift-test-macos.result }}"
|
||||
|
||||
- name: Summarize aggregate CI gate
|
||||
if: ${{ always() }}
|
||||
shell: bash
|
||||
env:
|
||||
LINT_RESULT: ${{ needs.lint.result }}
|
||||
CHANGES_RESULT: ${{ needs.changes.result }}
|
||||
MACOS_TESTS: ${{ needs.changes.outputs.macos-tests }}
|
||||
MACOS_TESTS_REASON: ${{ needs.changes.outputs.macos-tests-reason }}
|
||||
MACOS_RESULT: ${{ needs.swift-test-macos.result }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
reason="${MACOS_TESTS_REASON:-<unset>}"
|
||||
reason="${reason//|/\\|}"
|
||||
{
|
||||
printf '### Aggregate CI gate\n\n'
|
||||
printf '| Field | Value |\n'
|
||||
printf '| --- | --- |\n'
|
||||
printf '| lint result | `%s` |\n' "$LINT_RESULT"
|
||||
printf '| changes result | `%s` |\n' "$CHANGES_RESULT"
|
||||
printf '| macOS Swift tests required | `%s` |\n' "${MACOS_TESTS:-<unset>}"
|
||||
printf '| macOS gate reason | %s |\n' "$reason"
|
||||
printf '| swift-test-macos result | `%s` |\n' "$MACOS_RESULT"
|
||||
} >> "$GITHUB_STEP_SUMMARY"
|
||||
|
||||
build-linux-cli:
|
||||
timeout-minutes: 20
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- name: linux-x64
|
||||
runs-on: ubuntu-24.04
|
||||
- name: linux-arm64
|
||||
runs-on: ubuntu-24.04-arm
|
||||
runs-on: ${{ matrix.runs-on }}
|
||||
steps:
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
|
||||
- name: Runner info
|
||||
run: |
|
||||
set -euo pipefail
|
||||
uname -a
|
||||
uname -m
|
||||
|
||||
- name: Restore Swift toolchain cache
|
||||
id: swift-toolchain-cache
|
||||
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
||||
with:
|
||||
path: ~/.local/share/swiftly
|
||||
key: swift-${{ runner.os }}-${{ runner.arch }}-${{ env.SWIFT_VERSION }}-swiftly-${{ env.SWIFTLY_VERSION }}
|
||||
|
||||
- name: Install Swift ${{ env.SWIFT_VERSION }} via swiftly
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
missing_packages=()
|
||||
for package in ca-certificates gpg libcurl4-openssl-dev; do
|
||||
if ! dpkg-query -W -f='${Status}' "$package" 2>/dev/null | grep -q "install ok installed"; then
|
||||
missing_packages+=("$package")
|
||||
fi
|
||||
done
|
||||
if [[ "${#missing_packages[@]}" -gt 0 ]]; then
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y "${missing_packages[@]}"
|
||||
fi
|
||||
|
||||
SWIFTLY_ARCH="$(uname -m)"
|
||||
SWIFTLY_ARCHIVE="$RUNNER_TEMP/swiftly-${SWIFTLY_VERSION}-${SWIFTLY_ARCH}.tar.gz"
|
||||
SWIFTLY_SIGNATURE="${SWIFTLY_ARCHIVE}.sig"
|
||||
SWIFTLY_HOME_DIR="$HOME/.local/share/swiftly"
|
||||
SWIFTLY_BIN_DIR="$HOME/.local/bin"
|
||||
SWIFT_GNUPGHOME="$(mktemp -d)"
|
||||
SWIFT_KEYS="$RUNNER_TEMP/swift-signing-keys.asc"
|
||||
POST_INSTALL_SCRIPT="$(mktemp)"
|
||||
|
||||
mkdir -p "$SWIFTLY_BIN_DIR"
|
||||
chmod 700 "$SWIFT_GNUPGHOME"
|
||||
echo "Swift toolchain cache hit: ${{ steps.swift-toolchain-cache.outputs.cache-hit }}"
|
||||
curl -fsSL "https://download.swift.org/swiftly/linux/swiftly-${SWIFTLY_VERSION}-${SWIFTLY_ARCH}.tar.gz" -o "$SWIFTLY_ARCHIVE"
|
||||
curl -fsSL "https://download.swift.org/swiftly/linux/swiftly-${SWIFTLY_VERSION}-${SWIFTLY_ARCH}.tar.gz.sig" -o "$SWIFTLY_SIGNATURE"
|
||||
curl -fsSL --compressed "https://www.swift.org/keys/all-keys.asc" -o "$SWIFT_KEYS"
|
||||
GNUPGHOME="$SWIFT_GNUPGHOME" gpg --batch --import "$SWIFT_KEYS"
|
||||
SIGNATURE_STATUS="$(GNUPGHOME="$SWIFT_GNUPGHOME" gpg --batch --status-fd=1 \
|
||||
--verify "$SWIFTLY_SIGNATURE" "$SWIFTLY_ARCHIVE" 2>&1)"
|
||||
printf '%s\n' "$SIGNATURE_STATUS"
|
||||
grep -Fq "[GNUPG:] VALIDSIG ${SWIFTLY_SIGNING_FINGERPRINT} " <<< "$SIGNATURE_STATUS"
|
||||
tar -xzf "$SWIFTLY_ARCHIVE" -C /tmp
|
||||
/tmp/swiftly init --assume-yes --skip-install
|
||||
|
||||
. "$SWIFTLY_HOME_DIR/env.sh"
|
||||
echo "$SWIFTLY_BIN_DIR" >> "$GITHUB_PATH"
|
||||
echo "SWIFTLY_HOME_DIR=$SWIFTLY_HOME_DIR" >> "$GITHUB_ENV"
|
||||
echo "SWIFTLY_BIN_DIR=$SWIFTLY_BIN_DIR" >> "$GITHUB_ENV"
|
||||
|
||||
swiftly install "$SWIFT_VERSION" --use --assume-yes --verify --post-install-file "$POST_INSTALL_SCRIPT"
|
||||
if [[ -s "$POST_INSTALL_SCRIPT" ]]; then
|
||||
sudo apt-get update
|
||||
sudo bash "$POST_INSTALL_SCRIPT"
|
||||
fi
|
||||
|
||||
hash -r
|
||||
swift --version
|
||||
|
||||
- name: Build CodexBarCLI (release, static Swift stdlib)
|
||||
run: swift build -c release --product CodexBarCLI --static-swift-stdlib
|
||||
|
||||
- name: Swift Test (Linux only)
|
||||
run: swift test --parallel
|
||||
|
||||
- name: Smoke test CodexBarCLI
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
BIN_DIR="$(swift build -c release --product CodexBarCLI --static-swift-stdlib --show-bin-path)"
|
||||
BIN="$BIN_DIR/CodexBarCLI"
|
||||
"$BIN" --help >/dev/null
|
||||
"$BIN" --version >/dev/null
|
||||
if "$BIN" usage --provider codex --web >/dev/null 2>&1; then
|
||||
echo "Expected --web to fail on Linux"
|
||||
exit 1
|
||||
fi
|
||||
"$BIN" usage --provider codex --web 2>&1 | tee /tmp/codexbarcli-stderr.txt >/dev/null || true
|
||||
grep -q "macOS" /tmp/codexbarcli-stderr.txt
|
||||
|
||||
- name: Summarize Linux CLI build
|
||||
if: ${{ always() }}
|
||||
shell: bash
|
||||
env:
|
||||
MATRIX_NAME: ${{ matrix.name }}
|
||||
MATRIX_RUNS_ON: ${{ matrix.runs-on }}
|
||||
SWIFT_CACHE_HIT: ${{ steps.swift-toolchain-cache.outputs.cache-hit }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
{
|
||||
printf '### Linux CLI build\n\n'
|
||||
printf '| Field | Value |\n'
|
||||
printf '| --- | --- |\n'
|
||||
printf '| Matrix | `%s` |\n' "$MATRIX_NAME"
|
||||
printf '| Runner label | `%s` |\n' "$MATRIX_RUNS_ON"
|
||||
printf '| Swift version | `%s` |\n' "$SWIFT_VERSION"
|
||||
printf '| Swift toolchain cache hit | `%s` |\n' "${SWIFT_CACHE_HIT:-false}"
|
||||
} >> "$GITHUB_STEP_SUMMARY"
|
||||
@@ -0,0 +1,497 @@
|
||||
name: Release CLI
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: "Release tag/version to package for manual artifact builds; manual runs do not publish."
|
||||
required: false
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
build-cli:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- name: linux-x64
|
||||
runs-on: ubuntu-24.04
|
||||
platform: linux
|
||||
asset-platform: linux
|
||||
asset-arch: x86_64
|
||||
build-arch: ""
|
||||
static-swift-stdlib: true
|
||||
swift-sdk: ""
|
||||
swift-sdk-triple: ""
|
||||
swift-sdk-arch: ""
|
||||
file-arch-pattern: x86-64
|
||||
- name: linux-arm64
|
||||
runs-on: ubuntu-24.04-arm
|
||||
platform: linux
|
||||
asset-platform: linux
|
||||
asset-arch: aarch64
|
||||
build-arch: ""
|
||||
static-swift-stdlib: true
|
||||
swift-sdk: ""
|
||||
swift-sdk-triple: ""
|
||||
swift-sdk-arch: ""
|
||||
file-arch-pattern: aarch64
|
||||
- name: linux-musl-x64
|
||||
runs-on: ubuntu-24.04
|
||||
platform: linux
|
||||
asset-platform: linux-musl
|
||||
asset-arch: x86_64
|
||||
build-arch: ""
|
||||
static-swift-stdlib: false
|
||||
swift-sdk: swift-6.2.1-RELEASE_static-linux-0.0.1
|
||||
swift-sdk-triple: x86_64-swift-linux-musl
|
||||
swift-sdk-arch: x86_64
|
||||
file-arch-pattern: x86-64
|
||||
- name: linux-musl-arm64
|
||||
runs-on: ubuntu-24.04-arm
|
||||
platform: linux
|
||||
asset-platform: linux-musl
|
||||
asset-arch: aarch64
|
||||
build-arch: ""
|
||||
static-swift-stdlib: false
|
||||
swift-sdk: swift-6.2.1-RELEASE_static-linux-0.0.1
|
||||
swift-sdk-triple: aarch64-swift-linux-musl
|
||||
swift-sdk-arch: aarch64
|
||||
file-arch-pattern: aarch64
|
||||
- name: macos-arm64
|
||||
runs-on: macos-15
|
||||
platform: macos
|
||||
asset-platform: macos
|
||||
asset-arch: arm64
|
||||
build-arch: arm64
|
||||
static-swift-stdlib: false
|
||||
swift-sdk: ""
|
||||
swift-sdk-triple: ""
|
||||
swift-sdk-arch: ""
|
||||
file-arch-pattern: ""
|
||||
- name: macos-x86_64
|
||||
runs-on: macos-15-intel
|
||||
platform: macos
|
||||
asset-platform: macos
|
||||
asset-arch: x86_64
|
||||
build-arch: x86_64
|
||||
static-swift-stdlib: false
|
||||
swift-sdk: ""
|
||||
swift-sdk-triple: ""
|
||||
swift-sdk-arch: ""
|
||||
file-arch-pattern: ""
|
||||
runs-on: ${{ matrix.runs-on }}
|
||||
env:
|
||||
RELEASE_TAG: ${{ inputs.tag || github.ref_name }}
|
||||
SWIFT_VERSION: 6.2.1
|
||||
SWIFTLY_VERSION: 1.1.3
|
||||
SWIFTLY_SIGNING_FINGERPRINT: E813C892820A6FA13755B268F167DF1ACF9CE069
|
||||
SWIFT_STATIC_LINUX_SDK_URL: https://download.swift.org/swift-6.2.1-release/static-sdk/swift-6.2.1-RELEASE/swift-6.2.1-RELEASE_static-linux-0.0.1.artifactbundle.tar.gz
|
||||
SWIFT_STATIC_LINUX_SDK_CHECKSUM: 08e1939a504e499ec871b36826569173103e4562769e12b9b8c2a50f098374ad
|
||||
SQLITE_AMALGAMATION_VERSION: "3530300"
|
||||
SQLITE_AMALGAMATION_SHA3_256: d45c688a8cb23f68611a894a756a12d7eb6ab6e9e2468ca70adbeab3808b5ab9
|
||||
steps:
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
|
||||
- name: Select Xcode 26.3 or 26.2
|
||||
if: matrix.platform == 'macos'
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# Both versions are part of the official macOS 15 runner image.
|
||||
for candidate in /Applications/Xcode_26.3.app /Applications/Xcode_26.2.app; do
|
||||
if [[ -d "$candidate" ]]; then
|
||||
sudo xcode-select -s "${candidate}/Contents/Developer"
|
||||
echo "DEVELOPER_DIR=${candidate}/Contents/Developer" >> "$GITHUB_ENV"
|
||||
break
|
||||
fi
|
||||
done
|
||||
[[ "$(/usr/bin/xcodebuild -version)" == Xcode\ 26.* ]]
|
||||
/usr/bin/xcodebuild -version
|
||||
|
||||
- name: Runner info
|
||||
run: |
|
||||
set -euo pipefail
|
||||
uname -a
|
||||
uname -m
|
||||
swift --version
|
||||
|
||||
- name: Validate release tag
|
||||
if: github.event_name == 'release' || inputs.tag != ''
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [[ -z "$RELEASE_TAG" ]]; then
|
||||
echo "Missing release tag." >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! "$RELEASE_TAG" =~ ^v[0-9A-Za-z._-]+$ ]]; then
|
||||
echo "Invalid release tag: $RELEASE_TAG" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Install Swift ${{ env.SWIFT_VERSION }} via swiftly
|
||||
if: matrix.platform == 'linux'
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
if ! command -v gpg >/dev/null 2>&1; then
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y ca-certificates gpg
|
||||
fi
|
||||
|
||||
SWIFTLY_ARCH="$(uname -m)"
|
||||
SWIFTLY_ARCHIVE="$RUNNER_TEMP/swiftly-${SWIFTLY_VERSION}-${SWIFTLY_ARCH}.tar.gz"
|
||||
SWIFTLY_SIGNATURE="${SWIFTLY_ARCHIVE}.sig"
|
||||
SWIFTLY_HOME_DIR="$HOME/.local/share/swiftly"
|
||||
SWIFTLY_BIN_DIR="$HOME/.local/bin"
|
||||
SWIFT_GNUPGHOME="$(mktemp -d)"
|
||||
SWIFT_KEYS="$RUNNER_TEMP/swift-signing-keys.asc"
|
||||
POST_INSTALL_SCRIPT="$(mktemp)"
|
||||
|
||||
mkdir -p "$SWIFTLY_BIN_DIR"
|
||||
chmod 700 "$SWIFT_GNUPGHOME"
|
||||
curl -fsSL "https://download.swift.org/swiftly/linux/swiftly-${SWIFTLY_VERSION}-${SWIFTLY_ARCH}.tar.gz" -o "$SWIFTLY_ARCHIVE"
|
||||
curl -fsSL "https://download.swift.org/swiftly/linux/swiftly-${SWIFTLY_VERSION}-${SWIFTLY_ARCH}.tar.gz.sig" -o "$SWIFTLY_SIGNATURE"
|
||||
curl -fsSL --compressed "https://www.swift.org/keys/all-keys.asc" -o "$SWIFT_KEYS"
|
||||
GNUPGHOME="$SWIFT_GNUPGHOME" gpg --batch --import "$SWIFT_KEYS"
|
||||
SIGNATURE_STATUS="$(GNUPGHOME="$SWIFT_GNUPGHOME" gpg --batch --status-fd=1 \
|
||||
--verify "$SWIFTLY_SIGNATURE" "$SWIFTLY_ARCHIVE" 2>&1)"
|
||||
printf '%s\n' "$SIGNATURE_STATUS"
|
||||
grep -Fq "[GNUPG:] VALIDSIG ${SWIFTLY_SIGNING_FINGERPRINT} " <<< "$SIGNATURE_STATUS"
|
||||
tar -xzf "$SWIFTLY_ARCHIVE" -C /tmp
|
||||
/tmp/swiftly init --assume-yes --skip-install
|
||||
|
||||
. "$SWIFTLY_HOME_DIR/env.sh"
|
||||
echo "$SWIFTLY_BIN_DIR" >> "$GITHUB_PATH"
|
||||
echo "SWIFTLY_HOME_DIR=$SWIFTLY_HOME_DIR" >> "$GITHUB_ENV"
|
||||
echo "SWIFTLY_BIN_DIR=$SWIFTLY_BIN_DIR" >> "$GITHUB_ENV"
|
||||
|
||||
swiftly install "$SWIFT_VERSION" --use --assume-yes --verify --post-install-file "$POST_INSTALL_SCRIPT"
|
||||
if [[ -s "$POST_INSTALL_SCRIPT" ]]; then
|
||||
sudo apt-get update
|
||||
sudo bash "$POST_INSTALL_SCRIPT"
|
||||
fi
|
||||
|
||||
hash -r
|
||||
swift --version
|
||||
|
||||
- name: Install Swift Static Linux SDK
|
||||
if: matrix.swift-sdk != ''
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
swift sdk install "$SWIFT_STATIC_LINUX_SDK_URL" --checksum "$SWIFT_STATIC_LINUX_SDK_CHECKSUM"
|
||||
swift sdk list | grep -Fx "${{ matrix.swift-sdk }}"
|
||||
|
||||
sdk_root="$(
|
||||
find "$HOME" -type d -path "*/${{ matrix.swift-sdk }}.artifactbundle/${{ matrix.swift-sdk }}/swift-linux-musl" | head -n1
|
||||
)"
|
||||
if [[ -z "$sdk_root" ]]; then
|
||||
echo "Swift SDK root not found." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
python3 - "$sdk_root/swift-sdk.json" "${{ matrix.swift-sdk-triple }}" <<'PY'
|
||||
import json
|
||||
import sys
|
||||
|
||||
sdk_json_path, target_triple = sys.argv[1], sys.argv[2]
|
||||
with open(sdk_json_path, encoding="utf-8") as handle:
|
||||
sdk_json = json.load(handle)
|
||||
|
||||
target_triples = sdk_json.get("targetTriples", {})
|
||||
if target_triple not in target_triples:
|
||||
raise SystemExit(f"Swift SDK target triple not found: {target_triple}")
|
||||
|
||||
sdk_json["targetTriples"] = {target_triple: target_triples[target_triple]}
|
||||
with open(sdk_json_path, "w", encoding="utf-8") as handle:
|
||||
json.dump(sdk_json, handle, indent=2)
|
||||
handle.write("\n")
|
||||
PY
|
||||
|
||||
for sdk_arch in "$sdk_root"/musl-1.2.5.sdk/*; do
|
||||
if [[ "$(basename "$sdk_arch")" != "${{ matrix.swift-sdk-arch }}" ]]; then
|
||||
rm -rf "$sdk_arch"
|
||||
fi
|
||||
done
|
||||
|
||||
- name: Build static SQLite for musl SDK
|
||||
if: matrix.swift-sdk != ''
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
missing_packages=()
|
||||
for tool in clang openssl unzip; do
|
||||
if ! command -v "$tool" >/dev/null 2>&1; then
|
||||
missing_packages+=("$tool")
|
||||
fi
|
||||
done
|
||||
if [[ "${#missing_packages[@]}" -gt 0 ]]; then
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y "${missing_packages[@]}"
|
||||
fi
|
||||
|
||||
sqlite_zip="$RUNNER_TEMP/sqlite-amalgamation-${SQLITE_AMALGAMATION_VERSION}.zip"
|
||||
sqlite_src="$RUNNER_TEMP/sqlite-src"
|
||||
sqlite_out="$RUNNER_TEMP/sqlite-${{ matrix.swift-sdk-triple }}"
|
||||
|
||||
curl -fsSL "https://www.sqlite.org/2026/sqlite-amalgamation-${SQLITE_AMALGAMATION_VERSION}.zip" -o "$sqlite_zip"
|
||||
actual_sha3="$(openssl dgst -sha3-256 "$sqlite_zip" | awk '{print $NF}')"
|
||||
if [[ "$actual_sha3" != "$SQLITE_AMALGAMATION_SHA3_256" ]]; then
|
||||
echo "SQLite amalgamation checksum mismatch: $actual_sha3" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rm -rf "$sqlite_src" "$sqlite_out"
|
||||
mkdir -p "$sqlite_src" "$sqlite_out/build" "$sqlite_out/lib"
|
||||
unzip -q "$sqlite_zip" -d "$sqlite_src"
|
||||
|
||||
sdk_bundle="$(
|
||||
find "$HOME" -type d -name "${{ matrix.swift-sdk }}.artifactbundle" | head -n1
|
||||
)"
|
||||
if [[ -z "$sdk_bundle" ]]; then
|
||||
echo "Swift SDK artifact bundle not found." >&2
|
||||
exit 1
|
||||
fi
|
||||
sysroot="$sdk_bundle/${{ matrix.swift-sdk }}/swift-linux-musl/musl-1.2.5.sdk/${{ matrix.swift-sdk-arch }}"
|
||||
if [[ ! -d "$sysroot" ]]; then
|
||||
echo "Swift SDK sysroot not found: $sysroot" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
sqlite_amalgamation="$sqlite_src/sqlite-amalgamation-${SQLITE_AMALGAMATION_VERSION}"
|
||||
mkdir -p "$sysroot/usr/include"
|
||||
install -m 0644 "$sqlite_amalgamation/sqlite3.h" "$sysroot/usr/include/sqlite3.h"
|
||||
|
||||
clang \
|
||||
-target "${{ matrix.swift-sdk-triple }}" \
|
||||
--sysroot="$sysroot" \
|
||||
-O2 \
|
||||
-DSQLITE_OMIT_LOAD_EXTENSION=1 \
|
||||
-c "$sqlite_amalgamation/sqlite3.c" \
|
||||
-o "$sqlite_out/build/sqlite3.o"
|
||||
llvm-ar crs "$sqlite_out/lib/libsqlite3.a" "$sqlite_out/build/sqlite3.o"
|
||||
|
||||
echo "CODEXBAR_SQLITE3_LIB_DIR=$sqlite_out/lib" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Build CodexBarCLI (release)
|
||||
id: build
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
BUILD_ARGS=(swift build -c release --product CodexBarCLI)
|
||||
if [[ -n "${{ matrix.swift-sdk }}" ]]; then
|
||||
BUILD_ARGS+=(--swift-sdk "${{ matrix.swift-sdk }}" --triple "${{ matrix.swift-sdk-triple }}")
|
||||
elif [[ -n "${{ matrix.build-arch }}" ]]; then
|
||||
BUILD_ARGS+=(--arch "${{ matrix.build-arch }}")
|
||||
fi
|
||||
if [[ "${{ matrix.static-swift-stdlib }}" == "true" ]]; then
|
||||
BUILD_ARGS+=(--static-swift-stdlib)
|
||||
fi
|
||||
"${BUILD_ARGS[@]}"
|
||||
|
||||
SHOW_BIN_ARGS=(swift build -c release --product CodexBarCLI --show-bin-path)
|
||||
if [[ -n "${{ matrix.swift-sdk }}" ]]; then
|
||||
SHOW_BIN_ARGS+=(--swift-sdk "${{ matrix.swift-sdk }}" --triple "${{ matrix.swift-sdk-triple }}")
|
||||
elif [[ -n "${{ matrix.build-arch }}" ]]; then
|
||||
SHOW_BIN_ARGS+=(--arch "${{ matrix.build-arch }}")
|
||||
fi
|
||||
if [[ "${{ matrix.static-swift-stdlib }}" == "true" ]]; then
|
||||
SHOW_BIN_ARGS+=(--static-swift-stdlib)
|
||||
fi
|
||||
|
||||
echo "bin_dir=$("${SHOW_BIN_ARGS[@]}")" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Smoke test CodexBarCLI
|
||||
timeout-minutes: 5
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
BIN_DIR="${{ steps.build.outputs.bin_dir }}"
|
||||
BIN="$BIN_DIR/CodexBarCLI"
|
||||
run_with_timeout() {
|
||||
local output="$1"
|
||||
shift
|
||||
"$@" > "$output" &
|
||||
local pid=$!
|
||||
local run_status=
|
||||
for _ in {1..20}; do
|
||||
if ! kill -0 "$pid" 2>/dev/null; then
|
||||
set +e
|
||||
wait "$pid"
|
||||
run_status=$?
|
||||
set -e
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
if [[ -z "$run_status" ]]; then
|
||||
kill "$pid" 2>/dev/null || true
|
||||
wait "$pid" 2>/dev/null || true
|
||||
echo "$* timed out." >&2
|
||||
exit 124
|
||||
fi
|
||||
if [[ "$run_status" -ne 0 ]]; then
|
||||
cat "$output" >&2 || true
|
||||
exit "$run_status"
|
||||
fi
|
||||
}
|
||||
|
||||
echo "BIN=$BIN"
|
||||
file "$BIN"
|
||||
if [[ "${{ matrix.platform }}" == "macos" ]]; then
|
||||
lipo -archs "$BIN" | tr ' ' '\n' | grep -Fx "${{ matrix.asset-arch }}"
|
||||
run_with_timeout "$RUNNER_TEMP/codexbar-cli-smoke-${{ matrix.name }}.txt" "$BIN" config validate --format json
|
||||
elif [[ -n "${{ matrix.swift-sdk }}" ]]; then
|
||||
run_with_timeout "$RUNNER_TEMP/codexbar-cli-help-${{ matrix.name }}.txt" "$BIN" --help
|
||||
run_with_timeout "$RUNNER_TEMP/codexbar-cli-config-${{ matrix.name }}.json" "$BIN" config validate --format json
|
||||
file "$BIN" | grep -q "${{ matrix.file-arch-pattern }}"
|
||||
file "$BIN" | grep -q "statically linked"
|
||||
else
|
||||
run_with_timeout "$RUNNER_TEMP/codexbar-cli-help-${{ matrix.name }}.txt" "$BIN" --help
|
||||
file "$BIN" | grep -q "${{ matrix.file-arch-pattern }}"
|
||||
fi
|
||||
printf '%s\n' "${RELEASE_TAG#v}" > "$BIN_DIR/VERSION"
|
||||
VERSION_OUTPUT="$RUNNER_TEMP/codexbar-cli-version-${{ matrix.name }}.txt"
|
||||
run_with_timeout "$VERSION_OUTPUT" "$BIN" --version
|
||||
grep -Fx "CodexBar ${RELEASE_TAG#v}" "$VERSION_OUTPUT"
|
||||
rm "$BIN_DIR/VERSION"
|
||||
|
||||
- name: Package
|
||||
id: pkg
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
REF_NAME="${RELEASE_TAG}"
|
||||
if [[ -z "$REF_NAME" ]]; then
|
||||
echo "Missing release tag." >&2
|
||||
exit 1
|
||||
fi
|
||||
SAFE_REF_NAME="${REF_NAME//\//-}"
|
||||
|
||||
BIN_DIR="${{ steps.build.outputs.bin_dir }}"
|
||||
OUT_DIR="$(mktemp -d)"
|
||||
install -m 0755 "$BIN_DIR/CodexBarCLI" "$OUT_DIR/CodexBarCLI"
|
||||
ln -s "CodexBarCLI" "$OUT_DIR/codexbar"
|
||||
printf '%s\n' "${SAFE_REF_NAME#v}" > "$OUT_DIR/VERSION"
|
||||
|
||||
ASSET="CodexBarCLI-${SAFE_REF_NAME}-${{ matrix.asset-platform }}-${{ matrix.asset-arch }}.tar.gz"
|
||||
(cd "$OUT_DIR" && tar czf "$ASSET" CodexBarCLI codexbar VERSION)
|
||||
if command -v sha256sum >/dev/null 2>&1; then
|
||||
sha256sum "$OUT_DIR/$ASSET" > "$OUT_DIR/$ASSET.sha256"
|
||||
else
|
||||
shasum -a 256 "$OUT_DIR/$ASSET" > "$OUT_DIR/$ASSET.sha256"
|
||||
fi
|
||||
|
||||
echo "out_dir=$OUT_DIR" >> "$GITHUB_OUTPUT"
|
||||
echo "asset=$ASSET" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Upload release assets
|
||||
if: github.event_name == 'release'
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
TAG="${RELEASE_TAG}"
|
||||
OUT_DIR="${{ steps.pkg.outputs.out_dir }}"
|
||||
ASSET="${{ steps.pkg.outputs.asset }}"
|
||||
gh release upload "$TAG" "$OUT_DIR/$ASSET" "$OUT_DIR/$ASSET.sha256" --clobber
|
||||
|
||||
- name: Upload workflow artifact (manual runs)
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: codexbar-cli-${{ matrix.name }}
|
||||
path: |
|
||||
${{ steps.pkg.outputs.out_dir }}/${{ steps.pkg.outputs.asset }}
|
||||
${{ steps.pkg.outputs.out_dir }}/${{ steps.pkg.outputs.asset }}.sha256
|
||||
|
||||
update-homebrew-tap:
|
||||
runs-on: ubuntu-24.04
|
||||
needs: build-cli
|
||||
if: github.event_name == 'release'
|
||||
steps:
|
||||
- name: Resolve release tag
|
||||
id: release
|
||||
env:
|
||||
RELEASE_TAG: ${{ github.ref_name }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
tag="${RELEASE_TAG}"
|
||||
if [[ -z "$tag" ]]; then
|
||||
echo "Missing release tag." >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! "$tag" =~ ^v[0-9A-Za-z._-]+$ ]]; then
|
||||
echo "Invalid release tag: $tag" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "tag=$tag" >> "$GITHUB_OUTPUT"
|
||||
echo "request_id=codexbar-${tag}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Dispatch tap update
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }}
|
||||
RELEASE_TAG: ${{ steps.release.outputs.tag }}
|
||||
REQUEST_ID: ${{ steps.release.outputs.request_id }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
test -n "$GH_TOKEN"
|
||||
for attempt in {1..6}; do
|
||||
if gh workflow run update-formula.yml \
|
||||
--repo steipete/homebrew-tap \
|
||||
-f formula=codexbar \
|
||||
-f tag="$RELEASE_TAG" \
|
||||
-f repository=steipete/CodexBar \
|
||||
-f artifact_template='CodexBarCLI-{tag}-{target}.tar.gz' \
|
||||
-f target_aliases='darwin_arm64=macos-arm64,darwin_amd64=macos-x86_64,linux_arm64=linux-aarch64,linux_amd64=linux-x86_64' \
|
||||
-f cask=codexbar \
|
||||
-f cask_artifact='CodexBar-macos-universal-{version}.zip' \
|
||||
-f request_id="$REQUEST_ID"; then
|
||||
exit 0
|
||||
fi
|
||||
if [[ "$attempt" -eq 6 ]]; then
|
||||
echo "Failed to dispatch tap update after ${attempt} attempts." >&2
|
||||
exit 1
|
||||
fi
|
||||
sleep $((attempt * 30))
|
||||
done
|
||||
|
||||
- name: Wait for tap update
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }}
|
||||
REQUEST_ID: ${{ steps.release.outputs.request_id }}
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
for _ in {1..20}; do
|
||||
run_id="$(
|
||||
gh run list \
|
||||
--repo steipete/homebrew-tap \
|
||||
--workflow update-formula.yml \
|
||||
--json databaseId,displayTitle \
|
||||
--jq '.[] | select(.displayTitle | contains(env.REQUEST_ID)) | .databaseId' 2>/tmp/codexbar-tap-run-list.err \
|
||||
| head -n1 || true
|
||||
)"
|
||||
if [[ -n "$run_id" ]]; then
|
||||
gh run watch "$run_id" --repo steipete/homebrew-tap --exit-status
|
||||
exit 0
|
||||
fi
|
||||
cat /tmp/codexbar-tap-run-list.err >&2 || true
|
||||
sleep 5
|
||||
done
|
||||
echo "Timed out waiting for tap workflow to appear." >&2
|
||||
exit 1
|
||||
@@ -0,0 +1,188 @@
|
||||
name: Monitor Upstream Changes
|
||||
|
||||
on:
|
||||
schedule:
|
||||
# Run Monday and Thursday at 9 AM UTC
|
||||
- cron: '0 9 * * 1,4'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
target:
|
||||
description: 'Which upstream to check'
|
||||
required: false
|
||||
default: 'all'
|
||||
type: choice
|
||||
options:
|
||||
- all
|
||||
- upstream
|
||||
- quotio
|
||||
|
||||
jobs:
|
||||
check-upstreams:
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
issues: write
|
||||
contents: read
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Configure git
|
||||
run: |
|
||||
git config --global user.name 'github-actions[bot]'
|
||||
git config --global user.email 'github-actions[bot]@users.noreply.github.com'
|
||||
|
||||
- name: Add upstream remotes
|
||||
run: |
|
||||
git remote add upstream https://github.com/steipete/CodexBar.git || true
|
||||
git remote add quotio https://github.com/nguyenphutrong/quotio.git || true
|
||||
git fetch upstream
|
||||
git fetch quotio
|
||||
|
||||
- name: Check for new commits
|
||||
id: check
|
||||
run: |
|
||||
remote_default_branch() {
|
||||
local remote="$1"
|
||||
local branch=""
|
||||
branch=$(git symbolic-ref -q --short "refs/remotes/${remote}/HEAD" 2>/dev/null | sed "s#^${remote}/##" || true)
|
||||
if [ -z "$branch" ]; then
|
||||
branch=$(git remote show "$remote" 2>/dev/null | awk '/HEAD branch/ {print $NF; exit}' || true)
|
||||
fi
|
||||
if [ -n "$branch" ] && git rev-parse --verify -q "${remote}/${branch}" >/dev/null; then
|
||||
echo "$branch"
|
||||
return 0
|
||||
fi
|
||||
for candidate in main master; do
|
||||
if git rev-parse --verify -q "${remote}/${candidate}" >/dev/null; then
|
||||
echo "$candidate"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
echo "Could not resolve default branch for ${remote}" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
UPSTREAM_BRANCH=$(remote_default_branch upstream)
|
||||
QUOTIO_BRANCH=$(remote_default_branch quotio)
|
||||
UPSTREAM_REF="upstream/${UPSTREAM_BRANCH}"
|
||||
QUOTIO_REF="quotio/${QUOTIO_BRANCH}"
|
||||
echo "upstream_ref=$UPSTREAM_REF" >> $GITHUB_OUTPUT
|
||||
echo "quotio_ref=$QUOTIO_REF" >> $GITHUB_OUTPUT
|
||||
|
||||
# Count new commits in upstream
|
||||
UPSTREAM_NEW=$(git log --oneline "main..${UPSTREAM_REF}" --no-merges 2>/dev/null | wc -l | tr -d ' ')
|
||||
echo "upstream_commits=$UPSTREAM_NEW" >> $GITHUB_OUTPUT
|
||||
|
||||
# Count new commits in quotio (last 7 days)
|
||||
QUOTIO_NEW=$(git log --oneline "$QUOTIO_REF" --since="7 days ago" 2>/dev/null | wc -l | tr -d ' ')
|
||||
echo "quotio_commits=$QUOTIO_NEW" >> $GITHUB_OUTPUT
|
||||
|
||||
# Get commit summaries
|
||||
echo "upstream_summary<<EOF" >> $GITHUB_OUTPUT
|
||||
git log --oneline "main..${UPSTREAM_REF}" --no-merges 2>/dev/null | head -10 >> $GITHUB_OUTPUT || echo "No commits" >> $GITHUB_OUTPUT
|
||||
echo "EOF" >> $GITHUB_OUTPUT
|
||||
|
||||
echo "quotio_summary<<EOF" >> $GITHUB_OUTPUT
|
||||
git log --oneline "$QUOTIO_REF" --since="7 days ago" 2>/dev/null | head -10 >> $GITHUB_OUTPUT || echo "No commits" >> $GITHUB_OUTPUT
|
||||
echo "EOF" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Create or update issue
|
||||
if: steps.check.outputs.upstream_commits > 0 || steps.check.outputs.quotio_commits > 0
|
||||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
with:
|
||||
script: |
|
||||
const upstreamCommits = '${{ steps.check.outputs.upstream_commits }}';
|
||||
const quotioCommits = '${{ steps.check.outputs.quotio_commits }}';
|
||||
const upstreamRef = '${{ steps.check.outputs.upstream_ref }}';
|
||||
const quotioRef = '${{ steps.check.outputs.quotio_ref }}';
|
||||
const upstreamBranch = upstreamRef.replace('upstream/', '');
|
||||
const quotioBranch = quotioRef.replace('quotio/', '');
|
||||
const upstreamSummary = `${{ steps.check.outputs.upstream_summary }}`;
|
||||
const quotioSummary = `${{ steps.check.outputs.quotio_summary }}`;
|
||||
|
||||
const body = `## 🔄 Upstream Changes Detected
|
||||
|
||||
**steipete/CodexBar:** ${upstreamCommits} new commits
|
||||
**quotio:** ${quotioCommits} new commits (last 7 days)
|
||||
**Source refs:** ${upstreamRef}, ${quotioRef}
|
||||
|
||||
### steipete/CodexBar Recent Commits
|
||||
\`\`\`
|
||||
${upstreamSummary}
|
||||
\`\`\`
|
||||
|
||||
### quotio Recent Commits
|
||||
\`\`\`
|
||||
${quotioSummary}
|
||||
\`\`\`
|
||||
|
||||
### 📋 Review Actions
|
||||
|
||||
**Review upstream changes:**
|
||||
\`\`\`bash
|
||||
./Scripts/review_upstream.sh upstream
|
||||
\`\`\`
|
||||
|
||||
**Review quotio changes:**
|
||||
\`\`\`bash
|
||||
./Scripts/analyze_quotio.sh
|
||||
\`\`\`
|
||||
|
||||
**View detailed diffs:**
|
||||
\`\`\`bash
|
||||
git diff main..${upstreamRef}
|
||||
git log -p ${quotioRef} --since='7 days ago'
|
||||
\`\`\`
|
||||
|
||||
### 🔗 Links
|
||||
- [steipete commits](https://github.com/steipete/CodexBar/compare/${context.sha}...steipete:CodexBar:${upstreamBranch})
|
||||
- [quotio commits](https://github.com/nguyenphutrong/quotio/commits/${quotioBranch})
|
||||
|
||||
---
|
||||
*Auto-generated by upstream-monitor workflow*
|
||||
*Last checked: ${new Date().toISOString()}*`;
|
||||
|
||||
// Check for existing open issue
|
||||
const issues = await github.rest.issues.listForRepo({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
labels: 'upstream-sync',
|
||||
state: 'open'
|
||||
});
|
||||
|
||||
if (issues.data.length > 0) {
|
||||
// Update existing issue
|
||||
await github.rest.issues.update({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issues.data[0].number,
|
||||
body: body
|
||||
});
|
||||
|
||||
// Add comment
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issues.data[0].number,
|
||||
body: `🔄 Updated with latest changes (${upstreamCommits} upstream, ${quotioCommits} quotio)`
|
||||
});
|
||||
} else {
|
||||
// Create new issue
|
||||
await github.rest.issues.create({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
title: '🔄 Upstream Changes Available for Review',
|
||||
body: body,
|
||||
labels: ['upstream-sync', 'needs-review']
|
||||
});
|
||||
}
|
||||
|
||||
- name: No changes detected
|
||||
if: steps.check.outputs.upstream_commits == 0 && steps.check.outputs.quotio_commits == 0
|
||||
run: |
|
||||
echo "✅ No new upstream changes detected"
|
||||
echo "steipete/CodexBar: up to date"
|
||||
echo "quotio: no commits in last 7 days"
|
||||
Reference in New Issue
Block a user