mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-08-04 06:52:47 +00:00
🛡️ chore: Harden CI Supply Chain Workflows (#13090)
* chore: harden CI supply chain workflows * chore: address CI hardening review feedback * chore: tighten GitNexus dispatch hardening * chore: use app token for Locize PR automation * chore: use dedicated token for Locize PR automation
This commit is contained in:
parent
68eac104ad
commit
21574f02ca
22 changed files with 347 additions and 108 deletions
4
.github/workflows/a11y.yml
vendored
4
.github/workflows/a11y.yml
vendored
|
|
@ -11,6 +11,10 @@ on:
|
|||
required: true
|
||||
default: 'false'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
axe-linter:
|
||||
runs-on: ubuntu-latest
|
||||
|
|
|
|||
3
.github/workflows/backend-review.yml
vendored
3
.github/workflows/backend-review.yml
vendored
|
|
@ -5,6 +5,9 @@ on:
|
|||
- 'api/**'
|
||||
- 'packages/**'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
NODE_ENV: CI
|
||||
NODE_OPTIONS: '--max-old-space-size=${{ secrets.NODE_MAX_OLD_SPACE_SIZE || 6144 }}'
|
||||
|
|
|
|||
15
.github/workflows/build.yml
vendored
15
.github/workflows/build.yml
vendored
|
|
@ -3,6 +3,9 @@ name: Linux_Container_Workflow
|
|||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
RUNNER_VERSION: 2.293.0
|
||||
|
||||
|
|
@ -12,26 +15,26 @@ jobs:
|
|||
steps:
|
||||
# checkout the repo
|
||||
- name: 'Checkout GitHub Action'
|
||||
uses: actions/checkout@main
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: 'Login via Azure CLI'
|
||||
uses: azure/login@v1
|
||||
uses: azure/login@v2
|
||||
with:
|
||||
creds: ${{ secrets.AZURE_CREDENTIALS }}
|
||||
|
||||
- name: 'Build GitHub Runner container image'
|
||||
uses: azure/docker-login@v1
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
login-server: ${{ secrets.REGISTRY_LOGIN_SERVER }}
|
||||
registry: ${{ secrets.REGISTRY_LOGIN_SERVER }}
|
||||
username: ${{ secrets.REGISTRY_USERNAME }}
|
||||
password: ${{ secrets.REGISTRY_PASSWORD }}
|
||||
- run: |
|
||||
docker build --build-arg RUNNER_VERSION=${{ env.RUNNER_VERSION }} -t ${{ secrets.REGISTRY_LOGIN_SERVER }}/pwd9000-github-runner-lin:${{ env.RUNNER_VERSION }} .
|
||||
|
||||
- name: 'Push container image to ACR'
|
||||
uses: azure/docker-login@v1
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
login-server: ${{ secrets.REGISTRY_LOGIN_SERVER }}
|
||||
registry: ${{ secrets.REGISTRY_LOGIN_SERVER }}
|
||||
username: ${{ secrets.REGISTRY_USERNAME }}
|
||||
password: ${{ secrets.REGISTRY_PASSWORD }}
|
||||
- run: |
|
||||
|
|
|
|||
|
|
@ -15,6 +15,9 @@ on:
|
|||
- 'redis-config/**'
|
||||
- '.github/workflows/cache-integration-tests.yml'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
cache_integration_tests:
|
||||
name: Integration Tests that use actual Redis Cache
|
||||
|
|
|
|||
62
.github/workflows/client.yml
vendored
62
.github/workflows/client.yml
vendored
|
|
@ -14,31 +14,27 @@ on:
|
|||
default: 'Manual publish requested'
|
||||
|
||||
permissions:
|
||||
id-token: write # Required for OIDC trusted publishing
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build-and-publish:
|
||||
pack:
|
||||
runs-on: ubuntu-latest
|
||||
environment: publish # Must match npm trusted publisher config
|
||||
outputs:
|
||||
skip: ${{ steps.check.outputs.skip }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20.x'
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
|
||||
- name: Update npm for OIDC support
|
||||
run: npm install -g npm@latest # Must be 11.5.1+ for provenance
|
||||
|
||||
|
||||
- name: Install client dependencies
|
||||
run: cd packages/client && npm ci
|
||||
|
||||
|
||||
- name: Build client
|
||||
run: cd packages/client && npm run build
|
||||
|
||||
|
||||
- name: Check version change
|
||||
id: check
|
||||
working-directory: packages/client
|
||||
|
|
@ -52,13 +48,47 @@ jobs:
|
|||
echo "Version changed, proceeding with publish"
|
||||
echo "skip=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
|
||||
- name: Pack package
|
||||
if: steps.check.outputs.skip != 'true'
|
||||
working-directory: packages/client
|
||||
run: npm pack
|
||||
|
||||
- name: Publish
|
||||
run: |
|
||||
mkdir -p "$GITHUB_WORKSPACE/npm-package"
|
||||
npm pack --pack-destination "$GITHUB_WORKSPACE/npm-package"
|
||||
|
||||
- name: Upload package
|
||||
if: steps.check.outputs.skip != 'true'
|
||||
working-directory: packages/client
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: librechat-client-package
|
||||
path: npm-package/*.tgz
|
||||
if-no-files-found: error
|
||||
retention-days: 2
|
||||
|
||||
publish-npm:
|
||||
needs: pack
|
||||
if: github.ref == 'refs/heads/main' && needs.pack.outputs.skip != 'true'
|
||||
runs-on: ubuntu-latest
|
||||
environment: publish # Must match npm trusted publisher config
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write # Required for OIDC trusted publishing
|
||||
steps:
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20.x'
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
|
||||
- name: Install npm with OIDC support
|
||||
run: npm install -g npm@11.14.1 --ignore-scripts
|
||||
|
||||
- name: Download package
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: librechat-client-package
|
||||
path: npm-package
|
||||
|
||||
- name: Publish
|
||||
working-directory: npm-package
|
||||
run: npm publish *.tgz --access public --provenance
|
||||
|
|
|
|||
42
.github/workflows/data-provider.yml
vendored
42
.github/workflows/data-provider.yml
vendored
|
|
@ -14,11 +14,10 @@ on:
|
|||
default: 'Manual publish requested'
|
||||
|
||||
permissions:
|
||||
id-token: write # Required for OIDC trusted publishing
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
pack:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
|
@ -27,21 +26,42 @@ jobs:
|
|||
node-version: 20
|
||||
- run: cd packages/data-provider && npm ci
|
||||
- run: cd packages/data-provider && npm run build
|
||||
- name: Pack package
|
||||
run: |
|
||||
mkdir -p npm-package
|
||||
cd packages/data-provider
|
||||
npm pack --pack-destination "$GITHUB_WORKSPACE/npm-package"
|
||||
- name: Upload package
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: librechat-data-provider-package
|
||||
path: npm-package/*.tgz
|
||||
if-no-files-found: error
|
||||
retention-days: 2
|
||||
|
||||
publish-npm:
|
||||
needs: build
|
||||
needs: pack
|
||||
if: github.ref == 'refs/heads/main'
|
||||
runs-on: ubuntu-latest
|
||||
environment: publish # Must match npm trusted publisher config
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write # Required for OIDC trusted publishing
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
|
||||
- name: Update npm for OIDC support
|
||||
run: npm install -g npm@latest # Must be 11.5.1+ for provenance
|
||||
|
||||
- run: cd packages/data-provider && npm ci
|
||||
- run: cd packages/data-provider && npm run build
|
||||
- run: cd packages/data-provider && npm publish --provenance
|
||||
|
||||
- name: Install npm with OIDC support
|
||||
run: npm install -g npm@11.14.1 --ignore-scripts
|
||||
|
||||
- name: Download package
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: librechat-data-provider-package
|
||||
path: npm-package
|
||||
|
||||
- name: Publish package
|
||||
working-directory: npm-package
|
||||
run: npm publish *.tgz --provenance
|
||||
|
|
|
|||
62
.github/workflows/data-schemas.yml
vendored
62
.github/workflows/data-schemas.yml
vendored
|
|
@ -14,31 +14,27 @@ on:
|
|||
default: 'Manual publish requested'
|
||||
|
||||
permissions:
|
||||
id-token: write # Required for OIDC trusted publishing
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build-and-publish:
|
||||
pack:
|
||||
runs-on: ubuntu-latest
|
||||
environment: publish # Must match npm trusted publisher config
|
||||
outputs:
|
||||
skip: ${{ steps.check.outputs.skip }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20.x'
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
|
||||
- name: Update npm for OIDC support
|
||||
run: npm install -g npm@latest # Must be 11.5.1+ for provenance
|
||||
|
||||
|
||||
- name: Install dependencies
|
||||
run: cd packages/data-schemas && npm ci
|
||||
|
||||
|
||||
- name: Build
|
||||
run: cd packages/data-schemas && npm run build
|
||||
|
||||
|
||||
- name: Check version change
|
||||
id: check
|
||||
working-directory: packages/data-schemas
|
||||
|
|
@ -52,13 +48,47 @@ jobs:
|
|||
echo "Version changed, proceeding with publish"
|
||||
echo "skip=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
|
||||
- name: Pack package
|
||||
if: steps.check.outputs.skip != 'true'
|
||||
working-directory: packages/data-schemas
|
||||
run: npm pack
|
||||
|
||||
- name: Publish
|
||||
run: |
|
||||
mkdir -p "$GITHUB_WORKSPACE/npm-package"
|
||||
npm pack --pack-destination "$GITHUB_WORKSPACE/npm-package"
|
||||
|
||||
- name: Upload package
|
||||
if: steps.check.outputs.skip != 'true'
|
||||
working-directory: packages/data-schemas
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: librechat-data-schemas-package
|
||||
path: npm-package/*.tgz
|
||||
if-no-files-found: error
|
||||
retention-days: 2
|
||||
|
||||
publish-npm:
|
||||
needs: pack
|
||||
if: github.ref == 'refs/heads/main' && needs.pack.outputs.skip != 'true'
|
||||
runs-on: ubuntu-latest
|
||||
environment: publish # Must match npm trusted publisher config
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write # Required for OIDC trusted publishing
|
||||
steps:
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20.x'
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
|
||||
- name: Install npm with OIDC support
|
||||
run: npm install -g npm@11.14.1 --ignore-scripts
|
||||
|
||||
- name: Download package
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: librechat-data-schemas-package
|
||||
path: npm-package
|
||||
|
||||
- name: Publish
|
||||
working-directory: npm-package
|
||||
run: npm publish *.tgz --access public --provenance
|
||||
|
|
|
|||
5
.github/workflows/deploy-dev.yml
vendored
5
.github/workflows/deploy-dev.yml
vendored
|
|
@ -7,6 +7,9 @@ on:
|
|||
- completed
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
|
|
@ -29,7 +32,7 @@ jobs:
|
|||
DO_HOST: ${{ secrets.DO_HOST }}
|
||||
DO_USER: ${{ secrets.DO_USER }}
|
||||
run: |
|
||||
ssh -o StrictHostKeyChecking=no ${DO_USER}@${DO_HOST} << EOF
|
||||
ssh ${DO_USER}@${DO_HOST} << EOF
|
||||
sudo -i -u danny bash << 'EEOF'
|
||||
cd ~/LibreChat && \
|
||||
git fetch origin main && \
|
||||
|
|
|
|||
5
.github/workflows/deploy.yml
vendored
5
.github/workflows/deploy.yml
vendored
|
|
@ -3,6 +3,9 @@ name: Deploy_GHRunner_Linux_ACI
|
|||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
RUNNER_VERSION: 2.293.0
|
||||
ACI_RESOURCE_GROUP: 'Demo-ACI-GitHub-Runners-RG'
|
||||
|
|
@ -20,7 +23,7 @@ jobs:
|
|||
uses: actions/checkout@v4
|
||||
|
||||
- name: 'Login via Azure CLI'
|
||||
uses: azure/login@v1
|
||||
uses: azure/login@v2
|
||||
with:
|
||||
creds: ${{ secrets.AZURE_CREDENTIALS }}
|
||||
|
||||
|
|
|
|||
6
.github/workflows/dev-branch-images.yml
vendored
6
.github/workflows/dev-branch-images.yml
vendored
|
|
@ -10,6 +10,10 @@ on:
|
|||
- 'client/**'
|
||||
- 'packages/**'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
|
@ -43,7 +47,7 @@ jobs:
|
|||
|
||||
# Log in to GitHub Container Registry
|
||||
- name: Log in to GitHub Container Registry
|
||||
uses: docker/login-action@v2
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
|
|
|
|||
6
.github/workflows/dev-images.yml
vendored
6
.github/workflows/dev-images.yml
vendored
|
|
@ -10,6 +10,10 @@ on:
|
|||
- 'client/**'
|
||||
- 'packages/**'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
|
@ -39,7 +43,7 @@ jobs:
|
|||
|
||||
# Log in to GitHub Container Registry
|
||||
- name: Log in to GitHub Container Registry
|
||||
uses: docker/login-action@v2
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
|
|
|
|||
7
.github/workflows/dev-staging-images.yml
vendored
7
.github/workflows/dev-staging-images.yml
vendored
|
|
@ -3,6 +3,10 @@ name: Docker Dev Staging Images Build
|
|||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
|
@ -31,7 +35,7 @@ jobs:
|
|||
|
||||
# Log in to GitHub Container Registry
|
||||
- name: Log in to GitHub Container Registry
|
||||
uses: docker/login-action@v2
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
|
|
@ -63,4 +67,3 @@ jobs:
|
|||
${{ secrets.DOCKERHUB_USERNAME }}/${{ matrix.image_name }}:latest
|
||||
platforms: linux/amd64,linux/arm64
|
||||
target: ${{ matrix.target }}
|
||||
|
||||
|
|
|
|||
3
.github/workflows/frontend-review.yml
vendored
3
.github/workflows/frontend-review.yml
vendored
|
|
@ -6,6 +6,9 @@ on:
|
|||
- 'client/**'
|
||||
- 'packages/data-provider/**'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
NODE_OPTIONS: '--max-old-space-size=${{ secrets.NODE_MAX_OLD_SPACE_SIZE || 6144 }}'
|
||||
|
||||
|
|
|
|||
7
.github/workflows/generate_embeddings.yml
vendored
7
.github/workflows/generate_embeddings.yml
vendored
|
|
@ -7,14 +7,17 @@ on:
|
|||
paths:
|
||||
- 'docs/**'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
generate:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: supabase/embeddings-generator@v0.0.5
|
||||
with:
|
||||
supabase-url: ${{ secrets.SUPABASE_URL }}
|
||||
supabase-service-role-key: ${{ secrets.SUPABASE_SERVICE_ROLE_KEY }}
|
||||
openai-key: ${{ secrets.OPENAI_DOC_EMBEDDINGS_KEY }}
|
||||
docs-root-path: 'docs'
|
||||
docs-root-path: 'docs'
|
||||
|
|
|
|||
85
.github/workflows/gitnexus-index.yml
vendored
85
.github/workflows/gitnexus-index.yml
vendored
|
|
@ -25,9 +25,13 @@ on:
|
|||
type: string
|
||||
default: ''
|
||||
pr_ref:
|
||||
description: 'PR head SHA or ref to check out (set by /gitnexus command)'
|
||||
description: 'Optional PR head ref to check out; defaults to refs/pull/<pr_number>/head when pr_number is set'
|
||||
type: string
|
||||
default: ''
|
||||
deploy_after:
|
||||
description: 'Dispatch GitNexus Deploy after a successful index run'
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
|
@ -61,10 +65,35 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 25
|
||||
steps:
|
||||
- name: Validate dispatch inputs
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
env:
|
||||
PR_NUMBER: ${{ inputs.pr_number }}
|
||||
PR_REF: ${{ inputs.pr_ref }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [ -n "$PR_NUMBER" ]; then
|
||||
if [[ ! "$PR_NUMBER" =~ ^[0-9]+$ ]]; then
|
||||
echo "::error::pr_number must be numeric"
|
||||
exit 1
|
||||
fi
|
||||
EXPECTED_REF="refs/pull/${PR_NUMBER}/head"
|
||||
if [ -n "$PR_REF" ] && [ "$PR_REF" != "$EXPECTED_REF" ]; then
|
||||
echo "::error::pr_ref must match ${EXPECTED_REF}"
|
||||
exit 1
|
||||
fi
|
||||
elif [ -n "$PR_REF" ]; then
|
||||
echo "::error::pr_ref requires pr_number"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Resolve GitNexus flags
|
||||
id: flags
|
||||
env:
|
||||
EVENT_NAME: ${{ github.event_name }}
|
||||
ENABLE_EMBEDDINGS_INPUT: ${{ inputs.embeddings }}
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
PR_NUM: ${{ github.event.pull_request.number }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
|
|
@ -79,15 +108,14 @@ jobs:
|
|||
# (default false). This also covers the
|
||||
# /gitnexus index [embeddings] command.
|
||||
ENABLE_EMBEDDINGS=false
|
||||
case "${{ github.event_name }}" in
|
||||
case "$EVENT_NAME" in
|
||||
workflow_dispatch)
|
||||
[ "${{ inputs.embeddings }}" = "true" ] && ENABLE_EMBEDDINGS=true
|
||||
[ "$ENABLE_EMBEDDINGS_INPUT" = "true" ] && ENABLE_EMBEDDINGS=true
|
||||
;;
|
||||
push)
|
||||
ENABLE_EMBEDDINGS=true
|
||||
;;
|
||||
pull_request)
|
||||
PR_NUM="${{ github.event.pull_request.number }}"
|
||||
CHANGED=$(gh api "repos/${{ github.repository }}/pulls/$PR_NUM/files" \
|
||||
--paginate --jq '.[].filename' 2>/dev/null || echo "")
|
||||
if printf '%s\n' "$CHANGED" | grep -qE '^(api/|client/|packages/)'; then
|
||||
|
|
@ -145,13 +173,15 @@ jobs:
|
|||
# repo for every PR, so checkout works for fork PRs too. When
|
||||
# pr_ref is empty (native push/pull_request), fall back to the
|
||||
# default ref actions/checkout would use.
|
||||
ref: ${{ inputs.pr_ref || '' }}
|
||||
ref: ${{ inputs.pr_ref || (inputs.pr_number != '' && format('refs/pull/{0}/head', inputs.pr_number) || '') }}
|
||||
fetch-depth: 1
|
||||
persist-credentials: false
|
||||
|
||||
- name: Run GitNexus Analyze
|
||||
working-directory: ${{ runner.temp }}
|
||||
env:
|
||||
ENABLE_EMBEDDINGS: ${{ steps.flags.outputs.enable_embeddings }}
|
||||
FORCE: ${{ inputs.force }}
|
||||
GITNEXUS_BIN: ${{ runner.temp }}/gitnexus-cli/node_modules/.bin/gitnexus
|
||||
NPM_CONFIG_AUDIT: false
|
||||
NPM_CONFIG_CACHE: ${{ runner.temp }}/gitnexus-npm-cache
|
||||
|
|
@ -163,10 +193,10 @@ jobs:
|
|||
set -euo pipefail
|
||||
FLAGS=(--skip-agents-md --verbose)
|
||||
|
||||
if [ "${{ steps.flags.outputs.enable_embeddings }}" = "true" ]; then
|
||||
if [ "$ENABLE_EMBEDDINGS" = "true" ]; then
|
||||
FLAGS+=(--embeddings)
|
||||
fi
|
||||
if [ "${{ inputs.force }}" = "true" ]; then
|
||||
if [ "$FORCE" = "true" ]; then
|
||||
FLAGS+=(--force)
|
||||
fi
|
||||
"$GITNEXUS_BIN" analyze "$GITHUB_WORKSPACE" "${FLAGS[@]}"
|
||||
|
|
@ -206,27 +236,25 @@ jobs:
|
|||
if: |
|
||||
always() &&
|
||||
(inputs.pr_number != '' ||
|
||||
(github.triggering_actor == 'github-actions[bot]' && needs.index.result == 'success'))
|
||||
inputs.deploy_after)
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
permissions:
|
||||
contents: read
|
||||
actions: write # dispatch gitnexus-deploy.yml on bot-triggered runs
|
||||
actions: write # dispatch gitnexus-deploy.yml when deploy_after is set
|
||||
pull-requests: write # post completion comments for /gitnexus command runs
|
||||
steps:
|
||||
# GitHub suppresses workflow_run events for workflow runs whose
|
||||
# triggering actor is GITHUB_TOKEN (to prevent recursive chaining).
|
||||
# That means when this workflow is dispatched by gitnexus-pr-command
|
||||
# via `gh api workflow_dispatch`, the deploy workflow's workflow_run
|
||||
# trigger never fires. Manually dispatch the deploy here in that
|
||||
# specific case — user-triggered runs continue to rely on the
|
||||
# existing workflow_run trigger, so we don't double-deploy.
|
||||
- name: Trigger deploy workflow for bot-triggered runs
|
||||
if: github.triggering_actor == 'github-actions[bot]' && needs.index.result == 'success'
|
||||
# GitHub suppresses workflow_run events for workflow runs triggered
|
||||
# by GITHUB_TOKEN (to prevent recursive chaining). Command-triggered
|
||||
# index runs opt into a deploy by setting deploy_after=true.
|
||||
- name: Trigger deploy workflow after command-triggered runs
|
||||
if: inputs.deploy_after && needs.index.result == 'success'
|
||||
uses: actions/github-script@v7
|
||||
env:
|
||||
PR_NUMBER: ${{ inputs.pr_number }}
|
||||
with:
|
||||
script: |
|
||||
core.info('Triggering actor is github-actions[bot]; workflow_run would not fire. Dispatching gitnexus-deploy.yml manually.');
|
||||
core.info('deploy_after=true; dispatching gitnexus-deploy.yml manually.');
|
||||
// Pass pr_number through so the deploy workflow knows which
|
||||
// PR to post its completion comment on (for /gitnexus
|
||||
// command runs this will be set; for other bot dispatches
|
||||
|
|
@ -237,7 +265,7 @@ jobs:
|
|||
workflow_id: 'gitnexus-deploy.yml',
|
||||
ref: 'main',
|
||||
inputs: {
|
||||
pr_number: '${{ inputs.pr_number }}',
|
||||
pr_number: process.env.PR_NUMBER || '',
|
||||
},
|
||||
});
|
||||
|
||||
|
|
@ -249,19 +277,28 @@ jobs:
|
|||
- name: Comment on PR — index complete
|
||||
if: inputs.pr_number != ''
|
||||
uses: actions/github-script@v7
|
||||
env:
|
||||
EMBEDDINGS_INPUT: ${{ inputs.embeddings }}
|
||||
INDEX_RESULT: ${{ needs.index.result }}
|
||||
PR_NUMBER: ${{ inputs.pr_number }}
|
||||
with:
|
||||
script: |
|
||||
const outcome = '${{ needs.index.result }}' === 'success' ? '✅ indexed' : '❌ index failed';
|
||||
const prNum = parseInt('${{ inputs.pr_number }}', 10);
|
||||
const indexSucceeded = process.env.INDEX_RESULT === 'success';
|
||||
const outcome = indexSucceeded ? '✅ indexed' : '❌ index failed';
|
||||
const prNum = parseInt(process.env.PR_NUMBER || '', 10);
|
||||
if (!Number.isSafeInteger(prNum)) {
|
||||
core.setFailed(`Invalid PR number: ${process.env.PR_NUMBER}`);
|
||||
return;
|
||||
}
|
||||
const runUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`;
|
||||
const embeddingsFlag = '${{ inputs.embeddings }}' === 'true' ? 'with embeddings' : 'graph-only';
|
||||
const embeddingsFlag = process.env.EMBEDDINGS_INPUT === 'true' ? 'with embeddings' : 'graph-only';
|
||||
const body = [
|
||||
`### GitNexus: ${outcome}`,
|
||||
``,
|
||||
`PR #${prNum} was indexed ${embeddingsFlag}.`,
|
||||
`[Index run](${runUrl})`,
|
||||
'',
|
||||
'${{ needs.index.result }}' === 'success'
|
||||
indexSucceeded
|
||||
? '⏳ Waiting for deploy to serve the fresh index…'
|
||||
: '_Index run failed — the previous index (if any) continues to be served._',
|
||||
].join('\n');
|
||||
|
|
|
|||
26
.github/workflows/gitnexus-pr-command.yml
vendored
26
.github/workflows/gitnexus-pr-command.yml
vendored
|
|
@ -94,18 +94,38 @@ jobs:
|
|||
|
||||
- name: Dispatch gitnexus-index workflow
|
||||
uses: actions/github-script@v7
|
||||
env:
|
||||
EMBEDDINGS: ${{ steps.parse.outputs.embeddings }}
|
||||
PR_NUMBER: ${{ steps.parse.outputs.pr_number }}
|
||||
PR_REF: ${{ steps.parse.outputs.pr_ref }}
|
||||
with:
|
||||
script: |
|
||||
const prNumber = process.env.PR_NUMBER || '';
|
||||
const prRef = process.env.PR_REF || '';
|
||||
const embeddings = process.env.EMBEDDINGS || 'false';
|
||||
if (!/^[0-9]+$/.test(prNumber)) {
|
||||
core.setFailed(`Invalid PR number: ${prNumber}`);
|
||||
return;
|
||||
}
|
||||
if (prRef !== `refs/pull/${prNumber}/head`) {
|
||||
core.setFailed(`Invalid PR ref: ${prRef}`);
|
||||
return;
|
||||
}
|
||||
if (!['true', 'false'].includes(embeddings)) {
|
||||
core.setFailed(`Invalid embeddings value: ${embeddings}`);
|
||||
return;
|
||||
}
|
||||
await github.rest.actions.createWorkflowDispatch({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
workflow_id: 'gitnexus-index.yml',
|
||||
ref: 'main',
|
||||
inputs: {
|
||||
pr_number: '${{ steps.parse.outputs.pr_number }}',
|
||||
pr_ref: '${{ steps.parse.outputs.pr_ref }}',
|
||||
embeddings: '${{ steps.parse.outputs.embeddings }}',
|
||||
pr_number: prNumber,
|
||||
pr_ref: prRef,
|
||||
embeddings,
|
||||
force: 'false',
|
||||
deploy_after: 'true',
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
|||
9
.github/workflows/helmcharts.yml
vendored
9
.github/workflows/helmcharts.yml
vendored
|
|
@ -40,13 +40,14 @@ jobs:
|
|||
env:
|
||||
REF_NAME: ${{ github.ref_name }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
CHART_VERSION="${REF_NAME#chart-}"
|
||||
SEMVER_REGEX='^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?(\+[0-9A-Za-z.-]+)?$'
|
||||
if [[ ! "$CHART_VERSION" =~ $SEMVER_REGEX ]]; then
|
||||
echo "Invalid chart version: $CHART_VERSION" >&2
|
||||
SEMVER_REGEX='^[0-9]+[.][0-9]+[.][0-9]+(-[0-9A-Za-z.-]+)?([+][0-9A-Za-z.-]+)?$'
|
||||
if [[ "$REF_NAME" != chart-* || ! "$CHART_VERSION" =~ $SEMVER_REGEX ]]; then
|
||||
echo "::error::Chart tags must use the form chart-<semver>, for example chart-2.0.3"
|
||||
exit 1
|
||||
fi
|
||||
echo "CHART_VERSION=${CHART_VERSION}" >> "$GITHUB_OUTPUT"
|
||||
printf 'CHART_VERSION=%s\n' "$CHART_VERSION" >> "$GITHUB_OUTPUT"
|
||||
|
||||
# Log in to GitHub Container Registry
|
||||
- name: Log in to GitHub Container Registry
|
||||
|
|
|
|||
5
.github/workflows/i18n-unused-keys.yml
vendored
5
.github/workflows/i18n-unused-keys.yml
vendored
|
|
@ -18,10 +18,11 @@ jobs:
|
|||
detect-unused-i18n-keys:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Find unused i18next keys
|
||||
id: find-unused
|
||||
|
|
@ -140,7 +141,7 @@ jobs:
|
|||
|
||||
gh api "repos/${{ github.repository }}/issues/${PR_NUMBER}/comments" \
|
||||
-f body="$COMMENT_BODY" \
|
||||
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}"
|
||||
-H "Authorization: token $GITHUB_TOKEN"
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
|
|
|
|||
25
.github/workflows/locize-i18n-sync.yml
vendored
25
.github/workflows/locize-i18n-sync.yml
vendored
|
|
@ -6,6 +6,9 @@ on:
|
|||
repository_dispatch:
|
||||
types: [locize/versionPublished]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
sync-translations:
|
||||
name: Sync Translation Keys with Locize
|
||||
|
|
@ -13,6 +16,8 @@ jobs:
|
|||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Set Up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
|
|
@ -25,9 +30,12 @@ jobs:
|
|||
# Sync translations (Push missing keys & remove deleted ones)
|
||||
- name: Sync Locize with Repository
|
||||
if: ${{ github.event_name == 'push' }}
|
||||
env:
|
||||
LOCIZE_API_KEY: ${{ secrets.LOCIZE_API_KEY }}
|
||||
LOCIZE_PROJECT_ID: ${{ secrets.LOCIZE_PROJECT_ID }}
|
||||
run: |
|
||||
cd client/src/locales
|
||||
locize sync --api-key ${{ secrets.LOCIZE_API_KEY }} --project-id ${{ secrets.LOCIZE_PROJECT_ID }} --language en
|
||||
locize sync --api-key "$LOCIZE_API_KEY" --project-id "$LOCIZE_PROJECT_ID" --language en
|
||||
|
||||
# When triggered by repository_dispatch, skip sync step.
|
||||
- name: Skip sync step on non-push events
|
||||
|
|
@ -39,12 +47,13 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
needs: sync-translations
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
contents: read
|
||||
steps:
|
||||
# 1. Check out the repository.
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
# 2. Download translation files from locize.
|
||||
- name: Download Translations from locize
|
||||
|
|
@ -53,12 +62,14 @@ jobs:
|
|||
project-id: ${{ secrets.LOCIZE_PROJECT_ID }}
|
||||
path: "client/src/locales"
|
||||
|
||||
# 3. Create a Pull Request using built-in functionality.
|
||||
# 3. Create a Pull Request using a dedicated fine-grained PAT so this
|
||||
# workflow does not depend on the global GITHUB_TOKEN PR-creation setting.
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v7
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
sign-commits: true
|
||||
token: ${{ secrets.LOCIZE_PR_TOKEN }}
|
||||
add-paths: |
|
||||
client/src/locales/**
|
||||
commit-message: "🌍 i18n: Update translation.json with latest translations"
|
||||
base: main
|
||||
branch: i18n/locize-translation-update
|
||||
|
|
@ -69,4 +80,4 @@ jobs:
|
|||
- 🎯 **Objective**: Update `translation.json` with the latest translations from locize.
|
||||
- 🔍 **Details**: This PR is automatically generated upon receiving a versionPublished event with version "latest". It reflects the newest translations provided by locize.
|
||||
- ✅ **Status**: Ready for review.
|
||||
labels: "🌍 i18n"
|
||||
labels: "🌍 i18n"
|
||||
|
|
|
|||
19
.github/workflows/main-image-workflow.yml
vendored
19
.github/workflows/main-image-workflow.yml
vendored
|
|
@ -3,6 +3,10 @@ name: Docker Compose Build Latest Main Image Tag (Manual Dispatch)
|
|||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
|
@ -19,11 +23,20 @@ jobs:
|
|||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: main
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Fetch tags and set the latest tag
|
||||
run: |
|
||||
git fetch --tags
|
||||
echo "LATEST_TAG=$(git describe --tags `git rev-list --tags --max-count=1`)" >> $GITHUB_ENV
|
||||
set -euo pipefail
|
||||
git fetch --tags --force
|
||||
LATEST_TAG=$(git tag --list 'v[0-9]*' --sort=-v:refname | grep -E '^v[0-9]+[.][0-9]+[.][0-9]+$' | head -n 1)
|
||||
if [ -z "$LATEST_TAG" ]; then
|
||||
echo "::error::No stable v<semver> tag found"
|
||||
exit 1
|
||||
fi
|
||||
printf 'LATEST_TAG=%s\n' "$LATEST_TAG" >> "$GITHUB_ENV"
|
||||
|
||||
# Set up QEMU
|
||||
- name: Set up QEMU
|
||||
|
|
@ -35,7 +48,7 @@ jobs:
|
|||
|
||||
# Log in to GitHub Container Registry
|
||||
- name: Log in to GitHub Container Registry
|
||||
uses: docker/login-action@v2
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
|
|
|
|||
53
.github/workflows/tag-images.yml
vendored
53
.github/workflows/tag-images.yml
vendored
|
|
@ -3,7 +3,11 @@ name: Docker Images Build on Tag
|
|||
on:
|
||||
push:
|
||||
tags:
|
||||
- '*'
|
||||
- 'v*'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
|
@ -23,6 +27,25 @@ jobs:
|
|||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Validate release tag
|
||||
id: release-tag
|
||||
env:
|
||||
REF_NAME: ${{ github.ref_name }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
TAG_REGEX='^v[0-9]+[.][0-9]+[.][0-9]+(-rc[0-9]+)?$'
|
||||
STABLE_TAG_REGEX='^v[0-9]+[.][0-9]+[.][0-9]+$'
|
||||
if [[ ! "$REF_NAME" =~ $TAG_REGEX ]]; then
|
||||
echo "::error::Docker release tags must use v<semver> or v<semver>-rcN, for example v0.8.5 or v0.8.5-rc1"
|
||||
exit 1
|
||||
fi
|
||||
printf 'image_tag=%s\n' "$REF_NAME" >> "$GITHUB_OUTPUT"
|
||||
if [[ "$REF_NAME" =~ $STABLE_TAG_REGEX ]]; then
|
||||
echo "is_stable=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "is_stable=false" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
# Set up QEMU
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
|
@ -33,7 +56,7 @@ jobs:
|
|||
|
||||
# Log in to GitHub Container Registry
|
||||
- name: Log in to GitHub Container Registry
|
||||
uses: docker/login-action@v2
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
|
|
@ -51,6 +74,26 @@ jobs:
|
|||
run: |
|
||||
cp .env.example .env
|
||||
|
||||
- name: Resolve image tags
|
||||
id: image-tags
|
||||
env:
|
||||
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
IMAGE_NAME: ${{ matrix.image_name }}
|
||||
IMAGE_TAG: ${{ steps.release-tag.outputs.image_tag }}
|
||||
IS_STABLE: ${{ steps.release-tag.outputs.is_stable }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
{
|
||||
echo 'tags<<EOF'
|
||||
printf 'ghcr.io/%s/%s:%s\n' "$GITHUB_REPOSITORY_OWNER" "$IMAGE_NAME" "$IMAGE_TAG"
|
||||
printf '%s/%s:%s\n' "$DOCKERHUB_USERNAME" "$IMAGE_NAME" "$IMAGE_TAG"
|
||||
if [ "$IS_STABLE" = "true" ]; then
|
||||
printf 'ghcr.io/%s/%s:latest\n' "$GITHUB_REPOSITORY_OWNER" "$IMAGE_NAME"
|
||||
printf '%s/%s:latest\n' "$DOCKERHUB_USERNAME" "$IMAGE_NAME"
|
||||
fi
|
||||
echo 'EOF'
|
||||
} >> "$GITHUB_OUTPUT"
|
||||
|
||||
# Build and push Docker images for each target
|
||||
- name: Build and push Docker images
|
||||
uses: docker/build-push-action@v5
|
||||
|
|
@ -58,10 +101,6 @@ jobs:
|
|||
context: .
|
||||
file: ${{ matrix.file }}
|
||||
push: true
|
||||
tags: |
|
||||
ghcr.io/${{ github.repository_owner }}/${{ matrix.image_name }}:${{ github.ref_name }}
|
||||
ghcr.io/${{ github.repository_owner }}/${{ matrix.image_name }}:latest
|
||||
${{ secrets.DOCKERHUB_USERNAME }}/${{ matrix.image_name }}:${{ github.ref_name }}
|
||||
${{ secrets.DOCKERHUB_USERNAME }}/${{ matrix.image_name }}:latest
|
||||
tags: ${{ steps.image-tags.outputs.tags }}
|
||||
platforms: linux/amd64,linux/arm64
|
||||
target: ${{ matrix.target }}
|
||||
|
|
|
|||
3
.github/workflows/unused-packages.yml
vendored
3
.github/workflows/unused-packages.yml
vendored
|
|
@ -14,6 +14,7 @@ jobs:
|
|||
detect-unused-packages:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
|
||||
steps:
|
||||
|
|
@ -272,7 +273,7 @@ jobs:
|
|||
|
||||
gh api "repos/${{ github.repository }}/issues/${PR_NUMBER}/comments" \
|
||||
-f body="$COMMENT_BODY" \
|
||||
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}"
|
||||
-H "Authorization: token $GITHUB_TOKEN"
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue