mirror of
https://github.com/tinyhumansai/openhuman.git
synced 2026-07-28 13:32:23 +00:00
refactor: consolidate CLI binaries and streamline CI workflows (#44)
* chore: update dependencies and remove unused packages - Removed several unused dependencies from package.json, including `@tauri-apps/plugin-shell`, `@types/react-router-dom`, `immer`, `qrcode.react`, and `@testing-library/user-event`. - Updated the Vite configuration to exclude `telegram` from the optimizeDeps include list. - Cleaned up yarn.lock by removing references to deleted packages. - Deleted outdated GitHub Actions workflows for macOS ARM64 build, package and publish, and update changelog. * refactor: consolidate CLI binaries and update configurations - Renamed the main binary from `openhuman-core` to `openhuman` for consistency across the project. - Removed the `openhuman-cli` and `openhuman-core` binaries, consolidating functionality into the new `openhuman` binary. - Updated build configurations in GitHub Actions and Tauri to reflect the new binary name and paths. - Adjusted the Tailwind and Vite configurations to point to the correct HTML and source directories. - Introduced a new method in the Rust core server for handling JSON-RPC calls, enhancing the API structure. * chore: update subproject commit reference in skills * chore: update Rust test workflow and improve CLI command formatting - Modified the GitHub Actions workflow to include a new job for running Rust tests in the workspace. - Updated the `test:rust` command in `package.json` to run tests for the entire workspace. - Refactored CLI command definitions in `openhuman.rs` for improved readability by consolidating struct fields into single lines. * chore: enhance E2E testing scripts and workflows - Updated `.prettierignore` to exclude the `rust-core` directory. - Added new E2E testing commands in `package.json` for running all flows and improved formatting commands to include `cargo fmt`. - Enhanced GitHub Actions workflows to streamline E2E testing, including new scripts for running individual specs and all flows sequentially. - Refactored existing E2E scripts to utilize a common function for running tests, improving maintainability and readability. - Introduced a new script for resolving Node.js and Appium dependencies, ensuring compatibility for E2E tests. - Cleaned up and simplified existing E2E scripts by removing redundant code and consolidating functionality. * chore: update GitHub Actions workflows for Tauri build process - Modified build and release workflows to reference the correct target directory for Rust binaries, ensuring compatibility with the Cargo workspace structure. - Adjusted caching configuration in the test workflow for consistency and improved readability. - Standardized environment variable formatting in the test workflow to enhance clarity. * fix: standardize string formatting in GitHub Actions workflows - Updated the test workflow to use single quotes for cache configuration and environment variables, enhancing consistency across the file.
This commit is contained in:
@@ -73,13 +73,14 @@ jobs:
|
||||
run: cd skills && yarn install --frozen-lockfile
|
||||
|
||||
- name: Build sidecar core binary
|
||||
run: cargo build --manifest-path rust-core/Cargo.toml --release --target x86_64-unknown-linux-gnu --bin openhuman-core
|
||||
run: cargo build --manifest-path rust-core/Cargo.toml --release --target x86_64-unknown-linux-gnu --bin openhuman
|
||||
|
||||
- name: Stage sidecar for Tauri bundler
|
||||
run: |
|
||||
mkdir -p src-tauri/binaries
|
||||
cp rust-core/target/x86_64-unknown-linux-gnu/release/openhuman-core src-tauri/binaries/openhuman-core-x86_64-unknown-linux-gnu
|
||||
chmod +x src-tauri/binaries/openhuman-core-x86_64-unknown-linux-gnu
|
||||
# Workspace root target/ (not rust-core/target/) — see root Cargo.toml [workspace]
|
||||
cp target/x86_64-unknown-linux-gnu/release/openhuman src-tauri/binaries/openhuman-x86_64-unknown-linux-gnu
|
||||
chmod +x src-tauri/binaries/openhuman-x86_64-unknown-linux-gnu
|
||||
|
||||
- name: Build Tauri app
|
||||
run: |
|
||||
|
||||
@@ -1,125 +0,0 @@
|
||||
# Standalone macOS Apple Silicon (aarch64) Tauri build — no prepare-release / tagging.
|
||||
#
|
||||
# GitHub: workflow_dispatch checks out the ref. Local act: ACT=true skips checkout (use -b bind + run
|
||||
# ./scripts/run-macos-arm64-build.sh so submodules are initialized before act copies the tree).
|
||||
name: macOS ARM64 build
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build-macos-arm64:
|
||||
name: Build macOS aarch64 (signed)
|
||||
runs-on: macos-latest
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.XGH_TOKEN || github.token }}
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
if: ${{ env.ACT != 'true' }}
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set Xcode version
|
||||
uses: maxim-lobanov/setup-xcode@v1
|
||||
with:
|
||||
xcode-version: latest-stable
|
||||
|
||||
- name: Setup Node.js 24.x
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 24.x
|
||||
cache: yarn
|
||||
|
||||
- name: Install Rust stable
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
targets: aarch64-apple-darwin
|
||||
|
||||
- name: Cargo.lock fingerprint (deps only)
|
||||
id: cargo-lock-fingerprint
|
||||
shell: bash
|
||||
run: |
|
||||
echo "hash=$(tail -n +8 src-tauri/Cargo.lock | openssl dgst -sha256 | awk '{print $2}')" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Cache Cargo registry and git sources
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/registry
|
||||
~/.cargo/git
|
||||
key: ${{ runner.os }}-cargo-registry-${{ steps.cargo-lock-fingerprint.outputs.hash }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-cargo-registry-
|
||||
|
||||
- name: Install dependencies
|
||||
run: yarn install --frozen-lockfile
|
||||
|
||||
- name: Install skills dependencies
|
||||
run: cd skills && yarn install --frozen-lockfile
|
||||
|
||||
- name: Build skills
|
||||
run: cd skills && yarn build
|
||||
|
||||
- name: Define Tauri configuration overrides
|
||||
id: config-overrides
|
||||
uses: actions/github-script@v7
|
||||
env:
|
||||
BASE_URL: ${{ vars.BASE_URL }}
|
||||
UPDATER_PUBLIC_KEY: ${{ secrets.UPDATER_PUBLIC_KEY }}
|
||||
WITH_UPDATER: 'true'
|
||||
with:
|
||||
github-token: ${{ secrets.XGH_TOKEN || github.token }}
|
||||
script: |
|
||||
const workspacePath = process.env.GITHUB_WORKSPACE.replace(/\\/g, '/');
|
||||
const prefix = workspacePath.startsWith('/') ? 'file://' : 'file:///';
|
||||
const moduleUrl = `${prefix}${workspacePath}/scripts/prepareTauriConfig.js`;
|
||||
const { default: prepareTauriConfig } = await import(moduleUrl);
|
||||
const config = prepareTauriConfig();
|
||||
core.setOutput('json', JSON.stringify(config));
|
||||
|
||||
- name: Build frontend
|
||||
run: yarn build
|
||||
env:
|
||||
NODE_ENV: production
|
||||
VITE_BACKEND_URL: ${{ vars.VITE_BACKEND_URL }}
|
||||
VITE_SENTRY_DSN: ${{ vars.VITE_SENTRY_DSN }}
|
||||
VITE_DEBUG: ${{ vars.VITE_DEBUG }}
|
||||
|
||||
- name: Build sidecar core binary
|
||||
shell: bash
|
||||
run: |
|
||||
cargo build \
|
||||
--manifest-path rust-core/Cargo.toml \
|
||||
--release \
|
||||
--target aarch64-apple-darwin \
|
||||
--bin openhuman-core
|
||||
|
||||
- name: Stage sidecar for Tauri bundler
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p src-tauri/binaries
|
||||
cp rust-core/target/aarch64-apple-darwin/release/openhuman-core \
|
||||
src-tauri/binaries/openhuman-core-aarch64-apple-darwin
|
||||
chmod +x src-tauri/binaries/openhuman-core-aarch64-apple-darwin
|
||||
|
||||
- name: Build, package (no GitHub release upload)
|
||||
uses: tauri-apps/tauri-action@v0.6.2
|
||||
env:
|
||||
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE_BASE64 }}
|
||||
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
||||
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
|
||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||
APPLE_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}
|
||||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
||||
BASE_URL: ${{ vars.BASE_URL }}
|
||||
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
|
||||
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
|
||||
WITH_UPDATER: 'true'
|
||||
MACOSX_DEPLOYMENT_TARGET: '10.15'
|
||||
with:
|
||||
args: -c ${{ steps.config-overrides.outputs.json }} --target aarch64-apple-darwin -- -- --bin OpenHuman
|
||||
includeDebug: false
|
||||
includeRelease: true
|
||||
includeUpdaterJson: false
|
||||
@@ -1,499 +0,0 @@
|
||||
# Terms:
|
||||
# "build" - Compile web project using webpack.
|
||||
# "package" - Produce a distributive package for a specific platform as a workflow artifact.
|
||||
# "publish" - Send a package to corresponding store and GitHub release page.
|
||||
# "release" - build + package + publish
|
||||
#
|
||||
# Jobs in this workflow will skip the "publish" step when `SHOULD_PUBLISH` is not set.
|
||||
|
||||
name: Package and publish (Legacy)
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
# pull_request:
|
||||
# branches:
|
||||
# - main
|
||||
|
||||
env:
|
||||
IS_PR: ${{ github.event_name == 'pull_request' }}
|
||||
SHOULD_PUBLISH: ${{ github.event_name != 'pull_request' && github.ref == 'refs/heads/main' }}
|
||||
PUBLISH_REPO: openhumanxyz/openhuman
|
||||
XGH_TOKEN: ${{ secrets.XGH_TOKEN }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
jobs:
|
||||
get-version:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
package-version: ${{ steps.extract-version.outputs.package-version }}
|
||||
tag-name: ${{ steps.extract-version.outputs.tag-name }}
|
||||
should-publish: ${{ steps.extract-version.outputs.should-publish }}
|
||||
release-name: ${{ steps.extract-version.outputs.release-name }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 1
|
||||
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || github.ref }}
|
||||
token: ${{ secrets.XGH_TOKEN_READ }}
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20.x
|
||||
|
||||
- name: Extract version and tag
|
||||
id: extract-version
|
||||
run: |
|
||||
PACKAGE_VERSION=$(node -p "require('./package.json').version")
|
||||
TAG_NAME="v${PACKAGE_VERSION}"
|
||||
RELEASE_NAME="OpenHuman v${PACKAGE_VERSION}"
|
||||
echo "package-version=$PACKAGE_VERSION" >> $GITHUB_OUTPUT
|
||||
echo "tag-name=$TAG_NAME" >> $GITHUB_OUTPUT
|
||||
echo "release-name=$RELEASE_NAME" >> $GITHUB_OUTPUT
|
||||
echo "should-publish=$SHOULD_PUBLISH" >> $GITHUB_OUTPUT
|
||||
echo "Extracted version: $PACKAGE_VERSION"
|
||||
echo "Generated tag: $TAG_NAME"
|
||||
echo "Generated release name: $RELEASE_NAME"
|
||||
|
||||
check-version:
|
||||
runs-on: ubuntu-latest
|
||||
needs: get-version
|
||||
environment: ${{ github.ref == 'refs/heads/main' && 'Production' || '' }}
|
||||
outputs:
|
||||
should-skip: ${{ steps.check-release.outputs.should-skip }}
|
||||
steps:
|
||||
- name: Check if release already exists
|
||||
id: check-release
|
||||
env:
|
||||
PACKAGE_VERSION: ${{ needs.get-version.outputs.package-version }}
|
||||
TAG_NAME: ${{ needs.get-version.outputs.tag-name }}
|
||||
run: |
|
||||
# For non-main branches or when publishing is disabled, always continue
|
||||
if [ -z "$SHOULD_PUBLISH" ]; then
|
||||
echo "🚧 Publishing disabled (non-main branch)"
|
||||
echo "should-skip=false" >> $GITHUB_OUTPUT
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "Checking if release already exists for tag: $TAG_NAME"
|
||||
|
||||
RESPONSE=$(curl -s -w "\n%{http_code}" -H "Authorization: Bearer $XGH_TOKEN" \
|
||||
-H "Accept: application/vnd.github.v3+json" \
|
||||
"https://api.github.com/repos/$PUBLISH_REPO/releases/tags/$TAG_NAME")
|
||||
HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
|
||||
BODY=$(echo "$RESPONSE" | sed '$d')
|
||||
|
||||
if [ "$HTTP_CODE" = "404" ]; then
|
||||
echo "🆕 No release found for version $PACKAGE_VERSION, will create new release"
|
||||
echo "should-skip=false" >> $GITHUB_OUTPUT
|
||||
elif [ "$HTTP_CODE" != "200" ]; then
|
||||
echo "⚠️ Warning: Failed to check release (HTTP $HTTP_CODE). Response: $BODY"
|
||||
echo "Continuing anyway..."
|
||||
echo "should-skip=false" >> $GITHUB_OUTPUT
|
||||
elif echo "$BODY" | jq -e '.tag_name' > /dev/null; then
|
||||
IS_DRAFT=$(echo "$BODY" | jq -r '.draft')
|
||||
if [ "$IS_DRAFT" = "false" ]; then
|
||||
echo "✅ Published release already exists for version $PACKAGE_VERSION"
|
||||
echo "should-skip=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "📝 Draft release exists for version $PACKAGE_VERSION, will continue"
|
||||
echo "should-skip=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
else
|
||||
echo "🆕 No release found for version $PACKAGE_VERSION, will create new release"
|
||||
echo "should-skip=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
create-release:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [get-version, check-version]
|
||||
environment: ${{ github.ref == 'refs/heads/main' && 'Production' || '' }}
|
||||
if: github.ref == 'refs/heads/main' && needs.get-version.outputs.should-publish == 'true' && needs.check-version.outputs.should-skip != 'true'
|
||||
permissions:
|
||||
contents: write
|
||||
outputs:
|
||||
releaseId: ${{ steps.create-release.outputs.releaseId }}
|
||||
steps:
|
||||
- name: Create draft release
|
||||
id: create-release
|
||||
env:
|
||||
PACKAGE_VERSION: ${{ needs.get-version.outputs.package-version }}
|
||||
TAG_NAME: ${{ needs.get-version.outputs.tag-name }}
|
||||
RELEASE_NAME: ${{ needs.get-version.outputs.release-name }}
|
||||
XGH_TOKEN: ${{ secrets.XGH_TOKEN }}
|
||||
run: |
|
||||
echo "Creating draft release for tag: $TAG_NAME"
|
||||
echo "Repository: $PUBLISH_REPO"
|
||||
RELEASE_BODY="See the assets below to download this version."
|
||||
RESPONSE=$(curl -s -w "\n%{http_code}" -X POST \
|
||||
-H "Authorization: Bearer $XGH_TOKEN" \
|
||||
-H "Accept: application/vnd.github.v3+json" \
|
||||
-d '{"tag_name": "'"$TAG_NAME"'", "name": "'"$RELEASE_NAME"'", "draft": true, "body": "'"$RELEASE_BODY"'"}' \
|
||||
"https://api.github.com/repos/$PUBLISH_REPO/releases")
|
||||
HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
|
||||
BODY=$(echo "$RESPONSE" | sed '$d')
|
||||
echo "HTTP Status Code: $HTTP_CODE"
|
||||
echo "Response body: $BODY"
|
||||
if [ "$HTTP_CODE" != "201" ]; then
|
||||
echo "Error: Failed to create release. HTTP $HTTP_CODE"
|
||||
echo "Response: $BODY"
|
||||
exit 1
|
||||
fi
|
||||
RELEASE_ID=$(echo "$BODY" | jq -r '.id')
|
||||
echo "Extracted Release ID: $RELEASE_ID"
|
||||
if [ "$RELEASE_ID" = "null" ] || [ -z "$RELEASE_ID" ]; then
|
||||
echo "Error: Failed to extract release ID. Response was: $BODY"
|
||||
exit 1
|
||||
fi
|
||||
echo "releaseId=$RELEASE_ID" >> $GITHUB_OUTPUT
|
||||
|
||||
package-tauri:
|
||||
name: Build, package and publish Tauri
|
||||
needs: [get-version, check-version, create-release]
|
||||
if: ${{ !failure() && !cancelled() && needs.check-version.outputs.should-skip != 'true' }}
|
||||
environment: ${{ github.ref == 'refs/heads/main' && 'Production' || '' }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.XGH_TOKEN }}
|
||||
permissions:
|
||||
contents: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
settings:
|
||||
- platform: 'macos-latest'
|
||||
args: '--target aarch64-apple-darwin'
|
||||
target: 'aarch64-apple-darwin'
|
||||
- platform: 'macos-latest'
|
||||
args: '--target x86_64-apple-darwin'
|
||||
target: 'x86_64-apple-darwin'
|
||||
- platform: 'ubuntu-22.04'
|
||||
args: '--target x86_64-unknown-linux-gnu'
|
||||
target: 'x86_64-unknown-linux-gnu'
|
||||
runs-on: ${{ matrix.settings.platform }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 1
|
||||
submodules: true
|
||||
token: ${{ secrets.XGH_TOKEN_READ }}
|
||||
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || github.ref }}
|
||||
|
||||
- name: Set Xcode version
|
||||
if: matrix.settings.platform == 'macos-latest'
|
||||
uses: maxim-lobanov/setup-xcode@v1
|
||||
with:
|
||||
xcode-version: latest-stable
|
||||
|
||||
- name: Setup Node.js 24.x
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 24.x
|
||||
cache: 'yarn'
|
||||
|
||||
- name: Install Rust stable
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
targets: ${{ matrix.settings.platform == 'macos-latest' && 'aarch64-apple-darwin,x86_64-apple-darwin' || '' }}
|
||||
|
||||
- name: Install Tauri dependencies (ubuntu only)
|
||||
if: matrix.settings.platform == 'ubuntu-22.04'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf
|
||||
|
||||
# OpenMP is now disabled via Cargo.toml (default-features = false for llama-cpp-2)
|
||||
# This avoids cross-compilation issues where Homebrew ARM64 OpenMP can't be used for x86_64 builds
|
||||
|
||||
- name: Cache Cargo registry
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/registry
|
||||
~/.cargo/git
|
||||
key: ${{ runner.os }}-cargo-${{ hashFiles('src-tauri/Cargo.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-cargo-
|
||||
|
||||
- name: Cache Cargo build artifacts
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: src-tauri/target
|
||||
key: ${{ runner.os }}-cargo-target-${{ matrix.settings.platform }}-${{ hashFiles('src-tauri/Cargo.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-cargo-target-${{ matrix.settings.platform }}-
|
||||
|
||||
- name: Cache node modules
|
||||
id: yarn-cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: node_modules
|
||||
key: ${{ runner.os }}-build-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-build-
|
||||
|
||||
- name: Install dependencies
|
||||
if: steps.yarn-cache.outputs.cache-hit != 'true'
|
||||
run: yarn install --frozen-lockfile
|
||||
|
||||
- name: Cache skills node modules
|
||||
id: skills-yarn-cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: skills/node_modules
|
||||
key: ${{ runner.os }}-skills-${{ hashFiles('skills/yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-skills-
|
||||
|
||||
- name: Install skills dependencies
|
||||
if: steps.skills-yarn-cache.outputs.cache-hit != 'true'
|
||||
run: cd skills && yarn install --frozen-lockfile
|
||||
|
||||
- name: Build skills
|
||||
run: cd skills && yarn build
|
||||
|
||||
- name: Extract repository owner and name
|
||||
id: repository-info
|
||||
if: needs.get-version.outputs.should-publish != ''
|
||||
shell: bash
|
||||
run: |
|
||||
echo "owner=${PUBLISH_REPO%%/*}" >> $GITHUB_OUTPUT
|
||||
echo "repo=${PUBLISH_REPO#*/}" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Define Tauri configuration overrides
|
||||
id: config-overrides
|
||||
uses: actions/github-script@v7
|
||||
env:
|
||||
BASE_URL: ${{ vars.BASE_URL }}
|
||||
UPDATER_PUBLIC_KEY: ${{ secrets.UPDATER_PUBLIC_KEY }}
|
||||
WITH_UPDATER: ${{ needs.get-version.outputs.should-publish != '' && 'true' || 'false' }}
|
||||
with:
|
||||
script: |
|
||||
const workspacePath = process.env.GITHUB_WORKSPACE.replace(/\\/g, '/');
|
||||
const prefix = workspacePath.startsWith('/') ? 'file://' : 'file:///';
|
||||
const moduleUrl = `${prefix}${workspacePath}/scripts/prepareTauriConfig.js`;
|
||||
const { default: prepareTauriConfig } = await import(moduleUrl)
|
||||
const config = prepareTauriConfig();
|
||||
|
||||
const configJson = JSON.stringify(config);
|
||||
console.log(configJson);
|
||||
|
||||
core.setOutput("json", configJson);
|
||||
|
||||
- name: Build frontend
|
||||
run: yarn build
|
||||
env:
|
||||
NODE_ENV: production
|
||||
VITE_BACKEND_URL: ${{ vars.VITE_BACKEND_URL }}
|
||||
VITE_SENTRY_DSN: ${{ secrets.VITE_SENTRY_DSN }}
|
||||
VITE_DEBUG: ${{ vars.VITE_DEBUG }}
|
||||
|
||||
- name: Build sidecar core binary
|
||||
shell: bash
|
||||
run: |
|
||||
cargo build \
|
||||
--manifest-path rust-core/Cargo.toml \
|
||||
--release \
|
||||
--target "$MATRIX_TARGET" \
|
||||
--bin openhuman-core
|
||||
env:
|
||||
MATRIX_TARGET: ${{ matrix.settings.target }}
|
||||
|
||||
- name: Stage sidecar for Tauri bundler
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p src-tauri/binaries
|
||||
SOURCE="rust-core/target/$MATRIX_TARGET/release/openhuman-core"
|
||||
DEST="src-tauri/binaries/openhuman-core-$MATRIX_TARGET"
|
||||
cp "$SOURCE" "$DEST"
|
||||
chmod +x "$DEST"
|
||||
env:
|
||||
MATRIX_TARGET: ${{ matrix.settings.target }}
|
||||
|
||||
- name: Build, package and publish
|
||||
uses: tauri-apps/tauri-action@v0.6.2
|
||||
id: build-tauri
|
||||
env:
|
||||
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE_BASE64 }}
|
||||
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
||||
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
|
||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||
APPLE_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}
|
||||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
||||
BASE_URL: ${{ vars.BASE_URL }}
|
||||
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.UPDATER_PRIVATE_KEY }}
|
||||
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.UPDATER_PRIVATE_KEY_PASSWORD }}
|
||||
WITH_UPDATER: ${{ needs.get-version.outputs.should-publish != '' && 'true' || 'false' }}
|
||||
# macOS 10.15+ required for std::filesystem used by llama.cpp
|
||||
MACOSX_DEPLOYMENT_TARGET: ${{ matrix.settings.platform == 'macos-latest' && '10.15' || '' }}
|
||||
with:
|
||||
args: '-c ${{ steps.config-overrides.outputs.json }} ${{ matrix.settings.args }} -- -- --bin OpenHuman'
|
||||
includeDebug: ${{ needs.get-version.outputs.should-publish == '' && inputs.forceRelease != 'true' }}
|
||||
includeRelease: ${{ needs.get-version.outputs.should-publish != '' || inputs.forceRelease == 'true' }}
|
||||
# TDLib dylibs are now bundled natively via build.rs + tauri.conf.json macOS.frameworks
|
||||
# No post-build scripts needed - Tauri bundler handles copying and signing
|
||||
releaseId: ${{ needs.create-release.outputs.releaseId }}
|
||||
owner: openhumanxyz
|
||||
repo: openhuman
|
||||
|
||||
- name: Get file info
|
||||
id: file-info
|
||||
shell: bash
|
||||
run: |
|
||||
FULL_PATH=$(echo "${{ fromJSON(steps.build-tauri.outputs.artifactPaths)[0] }}")
|
||||
FILENAME=$(basename "$FULL_PATH")
|
||||
NAME_WITH_EXT="${FILENAME%.*}"
|
||||
VERSION="${{ needs.get-version.outputs.package-version }}"
|
||||
TAG_NAME="${{ needs.get-version.outputs.tag-name }}"
|
||||
|
||||
# Remove version/tag patterns from name
|
||||
# Patterns to remove: v0.14.0-1, 0.14.0-1, v0.14.0, 0.14.0, etc.
|
||||
# Package managers add release numbers like -1, -2, etc.
|
||||
NAME="$NAME_WITH_EXT"
|
||||
|
||||
# Remove version-release pattern (0.14.0-1, 0.14.0-2, etc.) - escape dots for regex
|
||||
VERSION_ESCAPED=$(echo "$VERSION" | sed 's/\./\\./g')
|
||||
NAME=$(echo "$NAME" | sed -E "s/[_-]?${VERSION_ESCAPED}-[0-9]+[_-]?//g")
|
||||
|
||||
# Remove tag-release pattern (v0.14.0-1, v0.14.0-2, etc.)
|
||||
TAG_ESCAPED=$(echo "$TAG_NAME" | sed 's/\./\\./g')
|
||||
NAME=$(echo "$NAME" | sed -E "s/[_-]?${TAG_ESCAPED}-[0-9]+[_-]?//g")
|
||||
|
||||
# Remove tag name (v0.14.0) with various separators
|
||||
NAME=$(echo "$NAME" | sed -E "s/[_-]?${TAG_ESCAPED}[_-]?//g")
|
||||
|
||||
# Remove version (0.14.0) with various separators
|
||||
NAME=$(echo "$NAME" | sed -E "s/[_-]?${VERSION_ESCAPED}[_-]?//g")
|
||||
|
||||
# Remove version with dots replaced by separators (0_14_0, 0-14-0)
|
||||
VERSION_DASH=$(echo "$VERSION" | tr '.' '-')
|
||||
VERSION_UNDERSCORE=$(echo "$VERSION" | tr '.' '_')
|
||||
NAME=$(echo "$NAME" | sed -E "s/[_-]?v?${VERSION_DASH}[_-]?//g")
|
||||
NAME=$(echo "$NAME" | sed -E "s/[_-]?v?${VERSION_UNDERSCORE}[_-]?//g")
|
||||
|
||||
# Clean up any double separators or trailing/leading separators
|
||||
NAME=$(echo "$NAME" | sed -E 's/[_-]{2,}/_/g' | sed 's/^[_-]//' | sed 's/[_-]$//')
|
||||
|
||||
FILE_PATH=$(cd "$(dirname "$FULL_PATH")" && pwd)
|
||||
# Extract architecture from target (e.g., aarch64-apple-darwin -> aarch64)
|
||||
ARCHITECTURE=$(echo "${{ matrix.settings.target }}" | cut -d'-' -f1)
|
||||
echo "name=$NAME" >> $GITHUB_OUTPUT
|
||||
echo "filename=$FILENAME" >> $GITHUB_OUTPUT
|
||||
echo "architecture=$ARCHITECTURE" >> $GITHUB_OUTPUT
|
||||
echo "path=$FILE_PATH" >> $GITHUB_OUTPUT
|
||||
|
||||
# MacOS release — upload the DMG after TDLib bundling and re-signing
|
||||
- name: Upload release asset (MacOS)
|
||||
if: matrix.settings.platform == 'macos-latest' && needs.get-version.outputs.should-publish != ''
|
||||
shell: bash
|
||||
run: |
|
||||
SANITIZED_FILENAME=$(echo "${{ steps.file-info.outputs.name }}" | sed 's/ /./g')
|
||||
PUBLISH_FILE_NAME="$SANITIZED_FILENAME-${{ steps.file-info.outputs.architecture }}.dmg"
|
||||
FILE_PATH="${{ steps.file-info.outputs.path }}/${{ steps.file-info.outputs.filename }}"
|
||||
RELEASE_ID="${{ needs.create-release.outputs.releaseId }}"
|
||||
curl -X POST -H "Authorization: Bearer $XGH_TOKEN" \
|
||||
-H "Content-Type: application/octet-stream" \
|
||||
--data-binary "@$FILE_PATH" \
|
||||
"https://uploads.github.com/repos/$PUBLISH_REPO/releases/$RELEASE_ID/assets?name=$PUBLISH_FILE_NAME"
|
||||
|
||||
- name: Upload artifact (MacOS)
|
||||
if: matrix.settings.platform == 'macos-latest'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ steps.file-info.outputs.name }}-${{ steps.file-info.outputs.architecture }}.dmg
|
||||
path: ${{ steps.file-info.outputs.path }}/${{ steps.file-info.outputs.filename }}
|
||||
|
||||
# Linux release
|
||||
- name: Upload Linux artifact (Linux)
|
||||
if: matrix.settings.platform == 'ubuntu-22.04'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ steps.file-info.outputs.filename }}
|
||||
path: ${{ steps.file-info.outputs.path }}/${{ steps.file-info.outputs.filename }}
|
||||
|
||||
publish-release:
|
||||
runs-on: ubuntu-latest
|
||||
# needs: [get-version, check-version, create-release, package-tauri, package-android]
|
||||
needs: [get-version, check-version, create-release, package-tauri]
|
||||
environment: ${{ github.ref == 'refs/heads/main' && 'Production' || '' }}
|
||||
if: github.ref == 'refs/heads/main' && needs.get-version.outputs.should-publish == 'true' && needs.check-version.outputs.should-skip != 'true'
|
||||
permissions:
|
||||
contents: write
|
||||
env:
|
||||
RELEASE_ID: ${{ needs.create-release.outputs.releaseId }}
|
||||
XGH_TOKEN: ${{ secrets.XGH_TOKEN }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 1
|
||||
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || github.ref }}
|
||||
|
||||
- name: Publish release
|
||||
run: |
|
||||
RESPONSE=$(curl -s -w "\n%{http_code}" -X PATCH \
|
||||
-H "Authorization: Bearer $XGH_TOKEN" \
|
||||
-H "Accept: application/vnd.github.v3+json" \
|
||||
-d '{"draft": false}' \
|
||||
"https://api.github.com/repos/$PUBLISH_REPO/releases/$RELEASE_ID")
|
||||
HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
|
||||
BODY=$(echo "$RESPONSE" | sed '$d')
|
||||
if [ "$HTTP_CODE" != "200" ]; then
|
||||
echo "Error: Failed to publish release. HTTP $HTTP_CODE"
|
||||
echo "Response: $BODY"
|
||||
exit 1
|
||||
fi
|
||||
echo "Release published successfully"
|
||||
|
||||
- name: Update Gist with JSON
|
||||
run: |
|
||||
ASSET_ID=$(curl -s -H "Authorization: Bearer $XGH_TOKEN" \
|
||||
-H "Accept: application/vnd.github.v3+json" \
|
||||
"https://api.github.com/repos/$PUBLISH_REPO/releases/$RELEASE_ID/assets" | jq -r '.[] | select(.name == "latest.json") | .id')
|
||||
JSON_CONTENT=$(curl -sSL -H "Accept: application/octet-stream" \
|
||||
-H "Authorization: Bearer $XGH_TOKEN" \
|
||||
"https://api.github.com/repos/$PUBLISH_REPO/releases/assets/$ASSET_ID")
|
||||
GIST_CONTENT=$(jq -n --arg json "$JSON_CONTENT" '{"files":{"updater.json":{"content":$json}}}')
|
||||
curl -X PATCH -H "Authorization: Bearer $XGH_TOKEN" \
|
||||
-H "Accept: application/vnd.github.v3+json" \
|
||||
-d "$GIST_CONTENT" \
|
||||
"https://api.github.com/gists/$UPDATER_GIST_ID"
|
||||
|
||||
delete-release-on-failure:
|
||||
name: Delete draft release on build/publish failure
|
||||
runs-on: ubuntu-latest
|
||||
needs: [get-version, create-release, package-tauri, publish-release]
|
||||
if: failure() && needs.create-release.result == 'success' && needs.create-release.outputs.releaseId != ''
|
||||
permissions:
|
||||
contents: write
|
||||
env:
|
||||
RELEASE_ID: ${{ needs.create-release.outputs.releaseId }}
|
||||
TAG_NAME: ${{ needs.get-version.outputs.tag-name }}
|
||||
XGH_TOKEN: ${{ secrets.XGH_TOKEN }}
|
||||
steps:
|
||||
- name: Delete draft release
|
||||
run: |
|
||||
echo "Deleting draft release $RELEASE_ID after build or publish failure"
|
||||
RESPONSE=$(curl -s -w "\n%{http_code}" -X DELETE \
|
||||
-H "Authorization: Bearer $XGH_TOKEN" \
|
||||
-H "Accept: application/vnd.github.v3+json" \
|
||||
"https://api.github.com/repos/$PUBLISH_REPO/releases/$RELEASE_ID")
|
||||
HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
|
||||
BODY=$(echo "$RESPONSE" | sed '$d')
|
||||
if [ "$HTTP_CODE" = "204" ] || [ "$HTTP_CODE" = "404" ]; then
|
||||
echo "Release deleted (or already gone)"
|
||||
else
|
||||
echo "Warning: Delete release returned HTTP $HTTP_CODE. Response: $BODY"
|
||||
fi
|
||||
- name: Delete tag
|
||||
run: |
|
||||
echo "Deleting tag $TAG_NAME"
|
||||
RESPONSE=$(curl -s -w "\n%{http_code}" -X DELETE \
|
||||
-H "Authorization: Bearer $XGH_TOKEN" \
|
||||
-H "Accept: application/vnd.github.v3+json" \
|
||||
"https://api.github.com/repos/$PUBLISH_REPO/git/refs/tags/$TAG_NAME")
|
||||
HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
|
||||
if [ "$HTTP_CODE" = "204" ] || [ "$HTTP_CODE" = "404" ]; then
|
||||
echo "Tag deleted (or already gone)"
|
||||
else
|
||||
echo "Warning: Delete tag returned HTTP $HTTP_CODE"
|
||||
fi
|
||||
@@ -305,27 +305,57 @@ jobs:
|
||||
VITE_SENTRY_DSN: ${{ vars.VITE_SENTRY_DSN }}
|
||||
VITE_DEBUG: ${{ vars.VITE_DEBUG }}
|
||||
|
||||
- name: Resolve core manifest and binary names
|
||||
id: core-paths
|
||||
shell: bash
|
||||
run: |
|
||||
if [ -f "openhuman_core/Cargo.toml" ]; then
|
||||
CORE_DIR="openhuman_core"
|
||||
elif [ -f "rust-core/Cargo.toml" ]; then
|
||||
CORE_DIR="rust-core"
|
||||
else
|
||||
echo "No core Cargo manifest found (expected openhuman_core/Cargo.toml or rust-core/Cargo.toml)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SIDE_CAR_BASE="$(node -e "const fs=require('fs');const c=JSON.parse(fs.readFileSync('src-tauri/tauri.conf.json','utf8'));const b=(c.bundle&&Array.isArray(c.bundle.externalBin)&&c.bundle.externalBin[0])||'binaries/openhuman';process.stdout.write(String(b).split('/').pop());")"
|
||||
CORE_BIN_NAME="${SIDE_CAR_BASE}"
|
||||
|
||||
echo "core_dir=$CORE_DIR" >> "$GITHUB_OUTPUT"
|
||||
echo "core_manifest=$CORE_DIR/Cargo.toml" >> "$GITHUB_OUTPUT"
|
||||
# Cargo workspace: release artifacts are under repo root target/, not <member>/target/
|
||||
echo "core_target_dir=target/$MATRIX_TARGET/release" >> "$GITHUB_OUTPUT"
|
||||
echo "core_bin_name=$CORE_BIN_NAME" >> "$GITHUB_OUTPUT"
|
||||
echo "sidecar_base=$SIDE_CAR_BASE" >> "$GITHUB_OUTPUT"
|
||||
env:
|
||||
MATRIX_TARGET: ${{ matrix.settings.target }}
|
||||
|
||||
- name: Build sidecar core binary
|
||||
shell: bash
|
||||
run: |
|
||||
cargo build \
|
||||
--manifest-path rust-core/Cargo.toml \
|
||||
--manifest-path "$CORE_MANIFEST" \
|
||||
--release \
|
||||
--target "$MATRIX_TARGET" \
|
||||
--bin openhuman-core
|
||||
--bin "$CORE_BIN_NAME"
|
||||
env:
|
||||
MATRIX_TARGET: ${{ matrix.settings.target }}
|
||||
CORE_MANIFEST: ${{ steps.core-paths.outputs.core_manifest }}
|
||||
CORE_BIN_NAME: ${{ steps.core-paths.outputs.core_bin_name }}
|
||||
|
||||
- name: Stage sidecar for Tauri bundler
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p src-tauri/binaries
|
||||
SOURCE="rust-core/target/$MATRIX_TARGET/release/openhuman-core"
|
||||
DEST="src-tauri/binaries/openhuman-core-$MATRIX_TARGET"
|
||||
SOURCE="$CORE_TARGET_DIR/$CORE_BIN_NAME"
|
||||
DEST="src-tauri/binaries/$SIDECAR_BASE-$MATRIX_TARGET"
|
||||
cp "$SOURCE" "$DEST"
|
||||
chmod +x "$DEST"
|
||||
env:
|
||||
MATRIX_TARGET: ${{ matrix.settings.target }}
|
||||
CORE_TARGET_DIR: ${{ steps.core-paths.outputs.core_target_dir }}
|
||||
CORE_BIN_NAME: ${{ steps.core-paths.outputs.core_bin_name }}
|
||||
SIDECAR_BASE: ${{ steps.core-paths.outputs.sidecar_base }}
|
||||
|
||||
- name: Build, package and upload to release
|
||||
uses: tauri-apps/tauri-action@v0.6.2
|
||||
@@ -364,32 +394,36 @@ jobs:
|
||||
APP_PATH="src-tauri/target/${{ matrix.settings.target }}/release/bundle/macos/OpenHuman.app"
|
||||
echo "Inspecting bundle at: $APP_PATH"
|
||||
ls -la "$APP_PATH/Contents/MacOS"
|
||||
ls -la "$APP_PATH/Contents/Resources" | grep openhuman-core || true
|
||||
if [ -f "$APP_PATH/Contents/MacOS/openhuman-core" ]; then
|
||||
ls -la "$APP_PATH/Contents/Resources" | grep openhuman || true
|
||||
if [ -f "$APP_PATH/Contents/MacOS/openhuman" ]; then
|
||||
echo "Unexpected standalone core binary found in MacOS dir"
|
||||
exit 1
|
||||
fi
|
||||
if ! ls "$APP_PATH/Contents/Resources"/openhuman-core-* >/dev/null 2>&1; then
|
||||
if ! ls "$APP_PATH/Contents/Resources"/openhuman-* >/dev/null 2>&1; then
|
||||
echo "Sidecar core binary missing from app resources"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Build standalone CLI binary
|
||||
- name: Build standalone core CLI binary
|
||||
shell: bash
|
||||
run: |
|
||||
cargo build --manifest-path rust-core/Cargo.toml --release --target "$MATRIX_TARGET" --bin openhuman-cli
|
||||
cargo build --manifest-path "$CORE_MANIFEST" --release --target "$MATRIX_TARGET" --bin "$CORE_BIN_NAME"
|
||||
env:
|
||||
MATRIX_TARGET: ${{ matrix.settings.target }}
|
||||
CORE_MANIFEST: ${{ steps.core-paths.outputs.core_manifest }}
|
||||
CORE_BIN_NAME: ${{ steps.core-paths.outputs.core_bin_name }}
|
||||
|
||||
- name: Resolve standalone CLI artifact path
|
||||
- name: Resolve standalone core CLI artifact path
|
||||
id: cli-paths
|
||||
shell: bash
|
||||
run: |
|
||||
BASE_DIR="rust-core/target/$MATRIX_TARGET/release"
|
||||
BASE_DIR="$CORE_TARGET_DIR"
|
||||
echo "base_dir=$BASE_DIR" >> "$GITHUB_OUTPUT"
|
||||
echo "cli_path=$BASE_DIR/openhuman-cli" >> "$GITHUB_OUTPUT"
|
||||
echo "cli_path=$BASE_DIR/$CORE_BIN_NAME" >> "$GITHUB_OUTPUT"
|
||||
env:
|
||||
MATRIX_TARGET: ${{ matrix.settings.target }}
|
||||
CORE_TARGET_DIR: ${{ steps.core-paths.outputs.core_target_dir }}
|
||||
CORE_BIN_NAME: ${{ steps.core-paths.outputs.core_bin_name }}
|
||||
|
||||
- name: Upload standalone CLI artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
|
||||
@@ -54,3 +54,87 @@ jobs:
|
||||
name: coverage-report
|
||||
path: coverage
|
||||
retention-days: 7
|
||||
|
||||
rust-tests:
|
||||
name: Run Rust Tests
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Install Rust stable
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
targets: x86_64-unknown-linux-gnu
|
||||
|
||||
- name: Install Tauri build dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf
|
||||
|
||||
# Match build.yml: lockfile body only (skip workspace version header noise)
|
||||
- name: Cargo.lock fingerprint (deps only)
|
||||
id: cargo-lock-fingerprint
|
||||
shell: bash
|
||||
run: |
|
||||
echo "hash=$(tail -n +8 Cargo.lock | openssl dgst -sha256 | awk '{print $2}')" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Cache Cargo registry and git sources
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/registry
|
||||
~/.cargo/git
|
||||
key: ${{ runner.os }}-rust-test-cargo-${{ steps.cargo-lock-fingerprint.outputs.hash }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-rust-test-cargo-
|
||||
|
||||
- name: Test rust-core (openhuman-core)
|
||||
run: cargo test -p openhuman-core
|
||||
|
||||
- name: Test src-tauri (OpenHuman)
|
||||
run: cargo test -p OpenHuman
|
||||
|
||||
e2e-macos:
|
||||
name: E2E (macOS / Appium)
|
||||
runs-on: macos-latest
|
||||
timeout-minutes: 90
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 1
|
||||
submodules: recursive
|
||||
|
||||
- name: Setup Node.js 24.x
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 24.x
|
||||
cache: 'yarn'
|
||||
|
||||
- name: Install Rust stable
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
|
||||
- name: Install dependencies
|
||||
run: yarn install --frozen-lockfile
|
||||
|
||||
- name: Install skills dependencies
|
||||
run: cd skills && yarn install --frozen-lockfile
|
||||
|
||||
- name: Ensure .env exists for E2E build
|
||||
run: touch .env
|
||||
|
||||
- name: Install Appium and mac2 driver
|
||||
run: |
|
||||
npm install -g appium
|
||||
appium driver install mac2
|
||||
|
||||
- name: Build E2E app bundle
|
||||
run: yarn test:e2e:build
|
||||
env:
|
||||
E2E_SKIP_CARGO_CLEAN: '1'
|
||||
|
||||
- name: Run all E2E flows
|
||||
run: yarn test:e2e:all:flows
|
||||
|
||||
@@ -1,197 +0,0 @@
|
||||
name: Update Changelog
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
concurrency:
|
||||
group: update-changelog
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
update-changelog:
|
||||
runs-on: ubuntu-latest
|
||||
# Skip if commit message contains [skip ci] or is a version bump commit
|
||||
if: "!contains(github.event.head_commit.message, '[skip ci]') && !contains(github.event.head_commit.message, 'chore: bump version')"
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Configure Git
|
||||
run: |
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||
|
||||
- name: Fetch tags
|
||||
run: |
|
||||
git fetch origin --tags
|
||||
|
||||
- name: Calculate next version
|
||||
id: next-version
|
||||
run: |
|
||||
# Get the latest version tag (format: v1.2.3)
|
||||
LATEST_TAG=$(git tag -l "v*" | sort -V | tail -n 1 || echo "")
|
||||
|
||||
if [ -z "$LATEST_TAG" ]; then
|
||||
# No tags found, start with v1.0.0
|
||||
NEXT_VERSION="v1.0.0"
|
||||
LATEST_TAG="(none)"
|
||||
else
|
||||
# Extract version number (remove 'v' prefix)
|
||||
VERSION="${LATEST_TAG#v}"
|
||||
|
||||
# Split into major.minor.patch
|
||||
IFS='.' read -r MAJOR MINOR PATCH <<< "$VERSION"
|
||||
|
||||
# Ensure we have valid numbers (default to 0 if empty)
|
||||
MAJOR=${MAJOR:-0}
|
||||
MINOR=${MINOR:-0}
|
||||
PATCH=${PATCH:-0}
|
||||
|
||||
# Increment minor version and reset patch to 0
|
||||
MINOR=$((MINOR + 1))
|
||||
PATCH=0
|
||||
|
||||
NEXT_VERSION="v${MAJOR}.${MINOR}.${PATCH}"
|
||||
fi
|
||||
|
||||
echo "Latest tag: $LATEST_TAG"
|
||||
echo "Predicted next version: $NEXT_VERSION"
|
||||
echo "version=$NEXT_VERSION" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Get commits since last tag
|
||||
id: get-commits
|
||||
run: |
|
||||
# Get the latest actual tag (not the predicted one)
|
||||
LATEST_TAG=$(git tag -l "v*" | sort -V | tail -n 1 || echo "")
|
||||
|
||||
# Get commits since the last tag (or all commits if no tag exists)
|
||||
if [ -n "$LATEST_TAG" ] && git rev-parse "$LATEST_TAG" >/dev/null 2>&1; then
|
||||
# Tag exists, get commits since that tag
|
||||
git log "$LATEST_TAG"..HEAD --pretty=format:"- %s (%h)" --no-merges > commits.txt || echo "- $(git log -1 --pretty=format:'%s (%h)')" > commits.txt
|
||||
else
|
||||
# No tag exists, get all commits
|
||||
git log --pretty=format:"- %s (%h)" --no-merges > commits.txt || echo "- $(git log -1 --pretty=format:'%s (%h)')" > commits.txt
|
||||
fi
|
||||
|
||||
# If file is empty, use current commit
|
||||
if [ ! -s commits.txt ]; then
|
||||
echo "- $(git log -1 --pretty=format:'%s (%h)')" > commits.txt
|
||||
fi
|
||||
|
||||
- name: Get current date
|
||||
id: date
|
||||
run: |
|
||||
echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Update CHANGELOG.md
|
||||
run: |
|
||||
CHANGELOG_PATH="publish/CHANGELOG.md"
|
||||
NEXT_VERSION="${{ steps.next-version.outputs.version }}"
|
||||
RELEASE_DATE="${{ steps.date.outputs.date }}"
|
||||
|
||||
# Create changelog directory if it doesn't exist
|
||||
mkdir -p publish
|
||||
|
||||
# Check if changelog exists and has content
|
||||
if [ ! -f "$CHANGELOG_PATH" ] || [ ! -s "$CHANGELOG_PATH" ]; then
|
||||
# Create new changelog with header
|
||||
cat > "$CHANGELOG_PATH" <<'EOF'
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
- Initial changelog
|
||||
|
||||
EOF
|
||||
fi
|
||||
|
||||
# Check if this version already exists in changelog
|
||||
if grep -q "## \[$NEXT_VERSION\]" "$CHANGELOG_PATH"; then
|
||||
echo "Version $NEXT_VERSION already exists in CHANGELOG.md. Skipping update."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Use Python to update the changelog
|
||||
python3 <<PYTHON_SCRIPT
|
||||
changelog_path = "$CHANGELOG_PATH"
|
||||
next_version = "$NEXT_VERSION"
|
||||
release_date = "$RELEASE_DATE"
|
||||
|
||||
# Read commits
|
||||
with open("commits.txt", "r") as f:
|
||||
commits = f.read().strip()
|
||||
|
||||
# Read existing changelog
|
||||
with open(changelog_path, "r") as f:
|
||||
lines = f.readlines()
|
||||
|
||||
# Create new version entry
|
||||
new_entry = f"""## [{next_version}] - {release_date}
|
||||
|
||||
### Changed
|
||||
{commits}
|
||||
|
||||
"""
|
||||
|
||||
# Find [Unreleased] section and insert after it
|
||||
output_lines = []
|
||||
inserted = False
|
||||
i = 0
|
||||
while i < len(lines):
|
||||
line = lines[i]
|
||||
output_lines.append(line)
|
||||
|
||||
# Check if this is the [Unreleased] header line
|
||||
if line.strip() == "## [Unreleased]":
|
||||
# Find the end of the [Unreleased] section (next ## header or end of file)
|
||||
i += 1
|
||||
while i < len(lines) and not lines[i].startswith("##"):
|
||||
output_lines.append(lines[i])
|
||||
i += 1
|
||||
# Insert new entry after the [Unreleased] section
|
||||
output_lines.append("\n")
|
||||
output_lines.append(new_entry)
|
||||
inserted = True
|
||||
# Continue with remaining lines
|
||||
continue
|
||||
|
||||
i += 1
|
||||
|
||||
# If [Unreleased] not found, prepend
|
||||
if not inserted:
|
||||
output_lines = [new_entry, "\n"] + lines
|
||||
|
||||
# Write updated changelog
|
||||
with open(changelog_path, "w") as f:
|
||||
f.writelines(output_lines)
|
||||
|
||||
print(f"Updated CHANGELOG.md with version {next_version}")
|
||||
PYTHON_SCRIPT
|
||||
|
||||
- name: Commit and push changes
|
||||
run: |
|
||||
git add publish/CHANGELOG.md
|
||||
|
||||
# Check if there are changes to commit
|
||||
if git diff --staged --quiet; then
|
||||
echo "No changes to commit."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
git commit -m "chore: update changelog for ${{ steps.next-version.outputs.version }} [skip ci]"
|
||||
git push origin develop
|
||||
Reference in New Issue
Block a user