Commit d059cbaf by Archer Committed by GitHub

chore: harden github actions workflows (#6991)

parent 5bab5bf1
...@@ -7,7 +7,26 @@ on: ...@@ -7,7 +7,26 @@ on:
- "v*" - "v*"
jobs: jobs:
validate-version:
runs-on: ubuntu-24.04
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- name: Validate release version
id: version
env:
VERSION: ${{ github.ref_name }}
REF_TYPE: ${{ github.ref_type }}
CURRENT_REF: ${{ github.ref }}
run: |
if [[ "$REF_TYPE" != "tag" || ! "$VERSION" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "::error::Release workflow must run on a tag like v1.2.3. Current ref: ${CURRENT_REF}"
exit 1
fi
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
build-fastgpt-admin-images: build-fastgpt-admin-images:
needs: validate-version
permissions: permissions:
packages: write packages: write
contents: read contents: read
...@@ -107,7 +126,7 @@ jobs: ...@@ -107,7 +126,7 @@ jobs:
contents: read contents: read
attestations: write attestations: write
id-token: write id-token: write
needs: build-fastgpt-admin-images needs: [validate-version, build-fastgpt-admin-images]
strategy: strategy:
matrix: matrix:
sub_routes: sub_routes:
...@@ -141,17 +160,11 @@ jobs: ...@@ -141,17 +160,11 @@ jobs:
- name: Set image name and tag - name: Set image name and tag
run: | run: |
if [[ "${{ github.ref_name }}" == "main" ]]; then VERSION="${{ needs.validate-version.outputs.version }}"
echo "Git_Tag=ghcr.io/${{ github.repository_owner }}/${{ matrix.sub_routes.repo }}:latest" >> $GITHUB_ENV echo "Git_Tag=ghcr.io/${{ github.repository_owner }}/${{ matrix.sub_routes.repo }}:${VERSION}" >> $GITHUB_ENV
echo "Git_Latest=ghcr.io/${{ github.repository_owner }}/${{ matrix.sub_routes.repo }}:latest" >> $GITHUB_ENV echo "Git_Latest=ghcr.io/${{ github.repository_owner }}/${{ matrix.sub_routes.repo }}:latest" >> $GITHUB_ENV
echo "Ali_Tag=${{ secrets.FASTGPT_ALI_IMAGE_PREFIX }}/${{ matrix.sub_routes.repo }}:latest" >> $GITHUB_ENV echo "Ali_Tag=${{ secrets.FASTGPT_ALI_IMAGE_PREFIX }}/${{ matrix.sub_routes.repo }}:${VERSION}" >> $GITHUB_ENV
echo "Ali_Latest=${{ secrets.FASTGPT_ALI_IMAGE_PREFIX }}/${{ matrix.sub_routes.repo }}:latest" >> $GITHUB_ENV echo "Ali_Latest=${{ secrets.FASTGPT_ALI_IMAGE_PREFIX }}/${{ matrix.sub_routes.repo }}:latest" >> $GITHUB_ENV
else
echo "Git_Tag=ghcr.io/${{ github.repository_owner }}/${{ matrix.sub_routes.repo }}:${{ github.ref_name }}" >> $GITHUB_ENV
echo "Git_Latest=ghcr.io/${{ github.repository_owner }}/${{ matrix.sub_routes.repo }}:latest" >> $GITHUB_ENV
echo "Ali_Tag=${{ secrets.FASTGPT_ALI_IMAGE_PREFIX }}/${{ matrix.sub_routes.repo }}:${{ github.ref_name }}" >> $GITHUB_ENV
echo "Ali_Latest=${{ secrets.FASTGPT_ALI_IMAGE_PREFIX }}/${{ matrix.sub_routes.repo }}:latest" >> $GITHUB_ENV
fi
- name: Create manifest list and push - name: Create manifest list and push
working-directory: ${{ runner.temp }}/digests working-directory: ${{ runner.temp }}/digests
......
...@@ -8,8 +8,25 @@ on: ...@@ -8,8 +8,25 @@ on:
type: string type: string
jobs: jobs:
validate-version:
runs-on: ubuntu-24.04
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- name: Validate release version
id: version
env:
VERSION: ${{ github.event.inputs.version }}
run: |
if [[ ! "$VERSION" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "::error::Image version must be like v1.2.3. Current value: ${VERSION}"
exit 1
fi
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
# ── agent-sandbox ────────────────────────────────────────────────────────── # ── agent-sandbox ──────────────────────────────────────────────────────────
build-fastgpt-agent-sandbox-images: build-fastgpt-agent-sandbox-images:
needs: validate-version
permissions: permissions:
packages: write packages: write
contents: read contents: read
...@@ -24,7 +41,7 @@ jobs: ...@@ -24,7 +41,7 @@ jobs:
runs-on: ${{ matrix.runs-on || 'ubuntu-24.04' }} runs-on: ${{ matrix.runs-on || 'ubuntu-24.04' }}
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v4
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Set up Docker Buildx - name: Set up Docker Buildx
...@@ -80,7 +97,7 @@ jobs: ...@@ -80,7 +97,7 @@ jobs:
contents: read contents: read
attestations: write attestations: write
id-token: write id-token: write
needs: build-fastgpt-agent-sandbox-images needs: [validate-version, build-fastgpt-agent-sandbox-images]
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
steps: steps:
- name: Login to GitHub Container Registry - name: Login to GitHub Container Registry
...@@ -113,7 +130,7 @@ jobs: ...@@ -113,7 +130,7 @@ jobs:
- name: Set image name and tag - name: Set image name and tag
run: | run: |
VERSION="${{ github.event.inputs.version }}" VERSION="${{ needs.validate-version.outputs.version }}"
echo "Git_Tag=ghcr.io/${{ github.repository_owner }}/fastgpt-agent-sandbox:${VERSION}" >> $GITHUB_ENV echo "Git_Tag=ghcr.io/${{ github.repository_owner }}/fastgpt-agent-sandbox:${VERSION}" >> $GITHUB_ENV
echo "Git_Latest=ghcr.io/${{ github.repository_owner }}/fastgpt-agent-sandbox:latest" >> $GITHUB_ENV echo "Git_Latest=ghcr.io/${{ github.repository_owner }}/fastgpt-agent-sandbox:latest" >> $GITHUB_ENV
echo "Ali_Tag=${{ secrets.FASTGPT_ALI_IMAGE_PREFIX }}/fastgpt-agent-sandbox:${VERSION}" >> $GITHUB_ENV echo "Ali_Tag=${{ secrets.FASTGPT_ALI_IMAGE_PREFIX }}/fastgpt-agent-sandbox:${VERSION}" >> $GITHUB_ENV
...@@ -133,6 +150,7 @@ jobs: ...@@ -133,6 +150,7 @@ jobs:
# ── volume-manager ───────────────────────────────────────────────────────── # ── volume-manager ─────────────────────────────────────────────────────────
build-fastgpt-volume-manager-images: build-fastgpt-volume-manager-images:
needs: validate-version
permissions: permissions:
packages: write packages: write
contents: read contents: read
...@@ -147,7 +165,7 @@ jobs: ...@@ -147,7 +165,7 @@ jobs:
runs-on: ${{ matrix.runs-on || 'ubuntu-24.04' }} runs-on: ${{ matrix.runs-on || 'ubuntu-24.04' }}
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v4
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Set up Docker Buildx - name: Set up Docker Buildx
...@@ -204,7 +222,7 @@ jobs: ...@@ -204,7 +222,7 @@ jobs:
contents: read contents: read
attestations: write attestations: write
id-token: write id-token: write
needs: build-fastgpt-volume-manager-images needs: [validate-version, build-fastgpt-volume-manager-images]
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
steps: steps:
- name: Login to GitHub Container Registry - name: Login to GitHub Container Registry
...@@ -237,7 +255,7 @@ jobs: ...@@ -237,7 +255,7 @@ jobs:
- name: Set image name and tag - name: Set image name and tag
run: | run: |
VERSION="${{ github.event.inputs.version }}" VERSION="${{ needs.validate-version.outputs.version }}"
echo "Git_Tag=ghcr.io/${{ github.repository_owner }}/fastgpt-agent-volume-manager:${VERSION}" >> $GITHUB_ENV echo "Git_Tag=ghcr.io/${{ github.repository_owner }}/fastgpt-agent-volume-manager:${VERSION}" >> $GITHUB_ENV
echo "Git_Latest=ghcr.io/${{ github.repository_owner }}/fastgpt-agent-volume-manager:latest" >> $GITHUB_ENV echo "Git_Latest=ghcr.io/${{ github.repository_owner }}/fastgpt-agent-volume-manager:latest" >> $GITHUB_ENV
echo "Ali_Tag=${{ secrets.FASTGPT_ALI_IMAGE_PREFIX }}/fastgpt-agent-volume-manager:${VERSION}" >> $GITHUB_ENV echo "Ali_Tag=${{ secrets.FASTGPT_ALI_IMAGE_PREFIX }}/fastgpt-agent-volume-manager:${VERSION}" >> $GITHUB_ENV
......
...@@ -7,7 +7,26 @@ on: ...@@ -7,7 +7,26 @@ on:
tags: tags:
- 'v*' - 'v*'
jobs: jobs:
validate-version:
runs-on: ubuntu-24.04
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- name: Validate release version
id: version
env:
VERSION: ${{ github.ref_name }}
REF_TYPE: ${{ github.ref_type }}
CURRENT_REF: ${{ github.ref }}
run: |
if [[ "$REF_TYPE" != "tag" || ! "$VERSION" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "::error::Release workflow must run on a tag like v1.2.3. Current ref: ${CURRENT_REF}"
exit 1
fi
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
build-fastgpt-code-sandbox-images: build-fastgpt-code-sandbox-images:
needs: validate-version
permissions: permissions:
packages: write packages: write
contents: read contents: read
...@@ -23,7 +42,7 @@ jobs: ...@@ -23,7 +42,7 @@ jobs:
steps: steps:
# install env # install env
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v4
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Set up Docker Buildx - name: Set up Docker Buildx
...@@ -80,7 +99,7 @@ jobs: ...@@ -80,7 +99,7 @@ jobs:
contents: read contents: read
attestations: write attestations: write
id-token: write id-token: write
needs: build-fastgpt-code-sandbox-images needs: [validate-version, build-fastgpt-code-sandbox-images]
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
steps: steps:
- name: Login to GitHub Container Registry - name: Login to GitHub Container Registry
...@@ -107,17 +126,11 @@ jobs: ...@@ -107,17 +126,11 @@ jobs:
- name: Set image name and tag - name: Set image name and tag
run: | run: |
if [[ "${{ github.ref_name }}" == "main" ]]; then VERSION="${{ needs.validate-version.outputs.version }}"
echo "Git_Tag=ghcr.io/${{ github.repository_owner }}/fastgpt-code-sandbox:latest" >> $GITHUB_ENV echo "Git_Tag=ghcr.io/${{ github.repository_owner }}/fastgpt-code-sandbox:${VERSION}" >> $GITHUB_ENV
echo "Git_Latest=ghcr.io/${{ github.repository_owner }}/fastgpt-code-sandbox:latest" >> $GITHUB_ENV echo "Git_Latest=ghcr.io/${{ github.repository_owner }}/fastgpt-code-sandbox:latest" >> $GITHUB_ENV
echo "Ali_Tag=${{ secrets.FASTGPT_ALI_IMAGE_PREFIX }}/fastgpt-code-sandbox:latest" >> $GITHUB_ENV echo "Ali_Tag=${{ secrets.FASTGPT_ALI_IMAGE_PREFIX }}/fastgpt-code-sandbox:${VERSION}" >> $GITHUB_ENV
echo "Ali_Latest=${{ secrets.FASTGPT_ALI_IMAGE_PREFIX }}/fastgpt-code-sandbox:latest" >> $GITHUB_ENV echo "Ali_Latest=${{ secrets.FASTGPT_ALI_IMAGE_PREFIX }}/fastgpt-code-sandbox:latest" >> $GITHUB_ENV
else
echo "Git_Tag=ghcr.io/${{ github.repository_owner }}/fastgpt-code-sandbox:${{ github.ref_name }}" >> $GITHUB_ENV
echo "Git_Latest=ghcr.io/${{ github.repository_owner }}/fastgpt-code-sandbox:latest" >> $GITHUB_ENV
echo "Ali_Tag=${{ secrets.FASTGPT_ALI_IMAGE_PREFIX }}/fastgpt-code-sandbox:${{ github.ref_name }}" >> $GITHUB_ENV
echo "Ali_Latest=${{ secrets.FASTGPT_ALI_IMAGE_PREFIX }}/fastgpt-code-sandbox:latest" >> $GITHUB_ENV
fi
- name: Create manifest list and push - name: Create manifest list and push
working-directory: ${{ runner.temp }}/digests working-directory: ${{ runner.temp }}/digests
......
...@@ -10,7 +10,26 @@ on: ...@@ -10,7 +10,26 @@ on:
- 'v*' - 'v*'
jobs: jobs:
validate-version:
runs-on: ubuntu-24.04
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- name: Validate release version
id: version
env:
VERSION: ${{ github.ref_name }}
REF_TYPE: ${{ github.ref_type }}
CURRENT_REF: ${{ github.ref }}
run: |
if [[ "$REF_TYPE" != "tag" || ! "$VERSION" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "::error::Release workflow must run on a tag like v1.2.3. Current ref: ${CURRENT_REF}"
exit 1
fi
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
build-fastgpt-images: build-fastgpt-images:
needs: validate-version
permissions: permissions:
packages: write packages: write
contents: read contents: read
...@@ -94,7 +113,7 @@ jobs: ...@@ -94,7 +113,7 @@ jobs:
contents: read contents: read
attestations: write attestations: write
id-token: write id-token: write
needs: build-fastgpt-images needs: [validate-version, build-fastgpt-images]
strategy: strategy:
matrix: matrix:
sub_routes: sub_routes:
...@@ -133,21 +152,13 @@ jobs: ...@@ -133,21 +152,13 @@ jobs:
- name: Set image name and tag - name: Set image name and tag
run: | run: |
if [[ "${{ github.ref_name }}" == "main" ]]; then VERSION="${{ needs.validate-version.outputs.version }}"
echo "Git_Tag=ghcr.io/${{ github.repository_owner }}/${{ matrix.sub_routes.repo }}:latest" >> $GITHUB_ENV echo "Git_Tag=ghcr.io/${{ github.repository_owner }}/${{ matrix.sub_routes.repo }}:${VERSION}" >> $GITHUB_ENV
echo "Git_Latest=ghcr.io/${{ github.repository_owner }}/${{ matrix.sub_routes.repo }}:latest" >> $GITHUB_ENV echo "Git_Latest=ghcr.io/${{ github.repository_owner }}/${{ matrix.sub_routes.repo }}:latest" >> $GITHUB_ENV
echo "Ali_Tag=${{ secrets.FASTGPT_ALI_IMAGE_PREFIX }}/${{ matrix.sub_routes.repo }}:latest" >> $GITHUB_ENV echo "Ali_Tag=${{ secrets.FASTGPT_ALI_IMAGE_PREFIX }}/${{ matrix.sub_routes.repo }}:${VERSION}" >> $GITHUB_ENV
echo "Ali_Latest=${{ secrets.FASTGPT_ALI_IMAGE_PREFIX }}/${{ matrix.sub_routes.repo }}:latest" >> $GITHUB_ENV echo "Ali_Latest=${{ secrets.FASTGPT_ALI_IMAGE_PREFIX }}/${{ matrix.sub_routes.repo }}:latest" >> $GITHUB_ENV
echo "Docker_Hub_Tag=${{ secrets.DOCKER_IMAGE_NAME }}/${{ matrix.sub_routes.repo }}:latest" >> $GITHUB_ENV echo "Docker_Hub_Tag=${{ secrets.DOCKER_IMAGE_NAME }}/${{ matrix.sub_routes.repo }}:${VERSION}" >> $GITHUB_ENV
echo "Docker_Hub_Latest=${{ secrets.DOCKER_IMAGE_NAME }}/${{ matrix.sub_routes.repo }}:latest" >> $GITHUB_ENV echo "Docker_Hub_Latest=${{ secrets.DOCKER_IMAGE_NAME }}/${{ matrix.sub_routes.repo }}:latest" >> $GITHUB_ENV
else
echo "Git_Tag=ghcr.io/${{ github.repository_owner }}/${{ matrix.sub_routes.repo }}:${{ github.ref_name }}" >> $GITHUB_ENV
echo "Git_Latest=ghcr.io/${{ github.repository_owner }}/${{ matrix.sub_routes.repo }}:latest" >> $GITHUB_ENV
echo "Ali_Tag=${{ secrets.FASTGPT_ALI_IMAGE_PREFIX }}/${{ matrix.sub_routes.repo }}:${{ github.ref_name }}" >> $GITHUB_ENV
echo "Ali_Latest=${{ secrets.FASTGPT_ALI_IMAGE_PREFIX }}/${{ matrix.sub_routes.repo }}:latest" >> $GITHUB_ENV
echo "Docker_Hub_Tag=${{ secrets.DOCKER_IMAGE_NAME }}/${{ matrix.sub_routes.repo }}:${{ github.ref_name }}" >> $GITHUB_ENV
echo "Docker_Hub_Latest=${{ secrets.DOCKER_IMAGE_NAME }}/${{ matrix.sub_routes.repo }}:latest" >> $GITHUB_ENV
fi
- name: Create manifest list and push - name: Create manifest list and push
working-directory: ${{ runner.temp }}/digests working-directory: ${{ runner.temp }}/digests
......
...@@ -18,7 +18,7 @@ jobs: ...@@ -18,7 +18,7 @@ jobs:
steps: steps:
# install env # install env
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v4
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Set up Docker Buildx - name: Set up Docker Buildx
......
...@@ -7,7 +7,26 @@ on: ...@@ -7,7 +7,26 @@ on:
tags: tags:
- 'v*' - 'v*'
jobs: jobs:
validate-version:
runs-on: ubuntu-24.04
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- name: Validate release version
id: version
env:
VERSION: ${{ github.ref_name }}
REF_TYPE: ${{ github.ref_type }}
CURRENT_REF: ${{ github.ref }}
run: |
if [[ "$REF_TYPE" != "tag" || ! "$VERSION" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "::error::Release workflow must run on a tag like v1.2.3. Current ref: ${CURRENT_REF}"
exit 1
fi
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
build-fastgpt-mcp_server-images: build-fastgpt-mcp_server-images:
needs: validate-version
permissions: permissions:
packages: write packages: write
contents: read contents: read
...@@ -23,7 +42,7 @@ jobs: ...@@ -23,7 +42,7 @@ jobs:
steps: steps:
# install env # install env
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v4
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Set up Docker Buildx - name: Set up Docker Buildx
...@@ -80,7 +99,7 @@ jobs: ...@@ -80,7 +99,7 @@ jobs:
contents: read contents: read
attestations: write attestations: write
id-token: write id-token: write
needs: build-fastgpt-mcp_server-images needs: [validate-version, build-fastgpt-mcp_server-images]
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
steps: steps:
- name: Login to GitHub Container Registry - name: Login to GitHub Container Registry
...@@ -113,21 +132,13 @@ jobs: ...@@ -113,21 +132,13 @@ jobs:
- name: Set image name and tag - name: Set image name and tag
run: | run: |
if [[ "${{ github.ref_name }}" == "main" ]]; then VERSION="${{ needs.validate-version.outputs.version }}"
echo "Git_Tag=ghcr.io/${{ github.repository_owner }}/fastgpt-mcp_server:latest" >> $GITHUB_ENV echo "Git_Tag=ghcr.io/${{ github.repository_owner }}/fastgpt-mcp_server:${VERSION}" >> $GITHUB_ENV
echo "Git_Latest=ghcr.io/${{ github.repository_owner }}/fastgpt-mcp_server:latest" >> $GITHUB_ENV echo "Git_Latest=ghcr.io/${{ github.repository_owner }}/fastgpt-mcp_server:latest" >> $GITHUB_ENV
echo "Ali_Tag=${{ secrets.FASTGPT_ALI_IMAGE_PREFIX }}/fastgpt-mcp_server:latest" >> $GITHUB_ENV echo "Ali_Tag=${{ secrets.FASTGPT_ALI_IMAGE_PREFIX }}/fastgpt-mcp_server:${VERSION}" >> $GITHUB_ENV
echo "Ali_Latest=${{ secrets.FASTGPT_ALI_IMAGE_PREFIX }}/fastgpt-mcp_server:latest" >> $GITHUB_ENV echo "Ali_Latest=${{ secrets.FASTGPT_ALI_IMAGE_PREFIX }}/fastgpt-mcp_server:latest" >> $GITHUB_ENV
echo "Docker_Hub_Tag=${{ secrets.DOCKER_IMAGE_NAME }}/fastgpt-mcp_server:latest" >> $GITHUB_ENV echo "Docker_Hub_Tag=${{ secrets.DOCKER_IMAGE_NAME }}/fastgpt-mcp_server:${VERSION}" >> $GITHUB_ENV
echo "Docker_Hub_Latest=${{ secrets.DOCKER_IMAGE_NAME }}/fastgpt-mcp_server:latest" >> $GITHUB_ENV echo "Docker_Hub_Latest=${{ secrets.DOCKER_IMAGE_NAME }}/fastgpt-mcp_server:latest" >> $GITHUB_ENV
else
echo "Git_Tag=ghcr.io/${{ github.repository_owner }}/fastgpt-mcp_server:${{ github.ref_name }}" >> $GITHUB_ENV
echo "Git_Latest=ghcr.io/${{ github.repository_owner }}/fastgpt-mcp_server:latest" >> $GITHUB_ENV
echo "Ali_Tag=${{ secrets.FASTGPT_ALI_IMAGE_PREFIX }}/fastgpt-mcp_server:${{ github.ref_name }}" >> $GITHUB_ENV
echo "Ali_Latest=${{ secrets.FASTGPT_ALI_IMAGE_PREFIX }}/fastgpt-mcp_server:latest" >> $GITHUB_ENV
echo "Docker_Hub_Tag=${{ secrets.DOCKER_IMAGE_NAME }}/fastgpt-mcp_server:${{ github.ref_name }}" >> $GITHUB_ENV
echo "Docker_Hub_Latest=${{ secrets.DOCKER_IMAGE_NAME }}/fastgpt-mcp_server:latest" >> $GITHUB_ENV
fi
- name: Create manifest list and push - name: Create manifest list and push
working-directory: ${{ runner.temp }}/digests working-directory: ${{ runner.temp }}/digests
......
...@@ -12,11 +12,30 @@ permissions: ...@@ -12,11 +12,30 @@ permissions:
id-token: write id-token: write
jobs: jobs:
validate-version:
runs-on: ubuntu-24.04
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- name: Validate release version
id: version
env:
VERSION: ${{ github.ref_name }}
REF_TYPE: ${{ github.ref_type }}
CURRENT_REF: ${{ github.ref }}
run: |
if [[ "$REF_TYPE" != "tag" || ! "$VERSION" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "::error::Release workflow must run on a tag like v1.2.3. Current ref: ${CURRENT_REF}"
exit 1
fi
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
build-fastgpt-sso-service-images: build-fastgpt-sso-service-images:
runs-on: buildjet-2vcpu-ubuntu-2204 needs: validate-version
runs-on: ubuntu-24.04
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v4
with: with:
fetch-depth: 1 fetch-depth: 1
- name: Update submodules - name: Update submodules
...@@ -33,9 +52,9 @@ jobs: ...@@ -33,9 +52,9 @@ jobs:
run: | run: |
sudo apt update && sudo apt install -y nodejs npm sudo apt update && sudo apt install -y nodejs npm
- name: Set up QEMU - name: Set up QEMU
uses: docker/setup-qemu-action@v2 uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2 uses: docker/setup-buildx-action@v3
with: with:
driver-opts: network=host driver-opts: network=host
- name: Cache Docker layers - name: Cache Docker layers
...@@ -46,30 +65,24 @@ jobs: ...@@ -46,30 +65,24 @@ jobs:
restore-keys: | restore-keys: |
${{ runner.os }}-buildx- ${{ runner.os }}-buildx-
- name: Login to GitHub Container Registry - name: Login to GitHub Container Registry
uses: docker/login-action@v2 uses: docker/login-action@v3
with: with:
registry: ghcr.io registry: ghcr.io
username: labring username: labring
password: ${{ secrets.GITHUB_TOKEN }} password: ${{ secrets.GITHUB_TOKEN }}
- name: Login to Ali Hub - name: Login to Ali Hub
uses: docker/login-action@v2 uses: docker/login-action@v3
with: with:
registry: registry.cn-hangzhou.aliyuncs.com registry: registry.cn-hangzhou.aliyuncs.com
username: ${{ secrets.FASTGPT_ALI_IMAGE_USER }} username: ${{ secrets.FASTGPT_ALI_IMAGE_USER }}
password: ${{ secrets.FASTGPT_ALI_IMAGE_PSW }} password: ${{ secrets.FASTGPT_ALI_IMAGE_PSW }}
- name: Set image tags - name: Set image tags
run: | run: |
if [[ "${{ github.ref_name }}" == "main" ]]; then VERSION="${{ needs.validate-version.outputs.version }}"
echo "Git_Latest=ghcr.io/labring/fastgpt-sso-service:latest" >> $GITHUB_ENV echo "Git_Tag=ghcr.io/labring/fastgpt-sso-service:${VERSION}" >> $GITHUB_ENV
echo "Git_Tag=ghcr.io/labring/fastgpt-sso-service:latest" >> $GITHUB_ENV echo "Git_Latest=ghcr.io/labring/fastgpt-sso-service:latest" >> $GITHUB_ENV
echo "Ali_Latest=${{ secrets.FASTGPT_ALI_IMAGE_PREFIX }}/fastgpt-sso-service:latest" >> $GITHUB_ENV echo "Ali_Tag=${{ secrets.FASTGPT_ALI_IMAGE_PREFIX }}/fastgpt-sso-service:${VERSION}" >> $GITHUB_ENV
echo "Ali_Tag=${{ secrets.FASTGPT_ALI_IMAGE_PREFIX }}/fastgpt-sso-service:latest" >> $GITHUB_ENV echo "Ali_Latest=${{ secrets.FASTGPT_ALI_IMAGE_PREFIX }}/fastgpt-sso-service:latest" >> $GITHUB_ENV
else
echo "Git_Tag=ghcr.io/labring/fastgpt-sso-service:${{ github.ref_name }}" >> $GITHUB_ENV
echo "Git_Latest=ghcr.io/labring/fastgpt-sso-service:latest" >> $GITHUB_ENV
echo "Ali_Tag=${{ secrets.FASTGPT_ALI_IMAGE_PREFIX }}/fastgpt-sso-service:${{ github.ref_name }}" >> $GITHUB_ENV
echo "Ali_Latest=${{ secrets.FASTGPT_ALI_IMAGE_PREFIX }}/fastgpt-sso-service:latest" >> $GITHUB_ENV
fi
- name: Build and publish image - name: Build and publish image
run: | run: |
......
...@@ -7,7 +7,26 @@ on: ...@@ -7,7 +7,26 @@ on:
workflow_dispatch: workflow_dispatch:
jobs: jobs:
validate-version:
runs-on: ubuntu-24.04
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- name: Validate release version
id: version
env:
VERSION: ${{ github.ref_name }}
REF_TYPE: ${{ github.ref_type }}
CURRENT_REF: ${{ github.ref }}
run: |
if [[ "$REF_TYPE" != "tag" || ! "$VERSION" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "::error::Release workflow must run on a tag like v1.2.3. Current ref: ${CURRENT_REF}"
exit 1
fi
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
helm: helm:
needs: validate-version
permissions: permissions:
packages: write packages: write
contents: read contents: read
...@@ -20,14 +39,11 @@ jobs: ...@@ -20,14 +39,11 @@ jobs:
with: with:
fetch-tags: true fetch-tags: true
fetch-depth: 0 fetch-depth: 0
- name: Set output
id: vars
run: echo "tag=$(git describe --tags)" >> $GITHUB_OUTPUT
- name: Release Helm - name: Release Helm
run: | run: |
echo ${{ secrets.GITHUB_TOKEN }} | helm registry login ghcr.io -u ${{ github.repository_owner }} --password-stdin echo ${{ secrets.GITHUB_TOKEN }} | helm registry login ghcr.io -u ${{ github.repository_owner }} --password-stdin
export APP_VERSION=${{ steps.vars.outputs.tag }} export APP_VERSION=${{ needs.validate-version.outputs.version }}
export HELM_VERSION=${{ steps.vars.outputs.tag }} export HELM_VERSION=${{ needs.validate-version.outputs.version }}
export HELM_REPO=ghcr.io/${{ github.repository_owner }} export HELM_REPO=ghcr.io/${{ github.repository_owner }}
helm dependency update deploy/helm/fastgpt helm dependency update deploy/helm/fastgpt
helm package deploy/helm/fastgpt --version ${HELM_VERSION}-helm --app-version ${APP_VERSION} -d bin helm package deploy/helm/fastgpt --version ${HELM_VERSION}-helm --app-version ${APP_VERSION} -d bin
......
...@@ -12,18 +12,83 @@ concurrency: ...@@ -12,18 +12,83 @@ concurrency:
permissions: permissions:
contents: read contents: read
packages: write
attestations: write
id-token: write
pull-requests: write
issues: write
actions: read
jobs: jobs:
push: check_pr_author:
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
# Only push when the build succeeded # Only inspect the upstream PR when the build succeeded.
if: ${{ github.event.workflow_run.conclusion == 'success' }} if: ${{ github.event.workflow_run.conclusion == 'success' }}
permissions:
contents: read
pull-requests: read
outputs:
trusted: ${{ steps.trust.outputs.trusted }}
number: ${{ steps.trust.outputs.number }}
sha: ${{ steps.trust.outputs.sha }}
steps:
- name: Check trusted PR author
id: trust
uses: actions/github-script@v7
with:
script: |
const allowedAssociations = new Set(['OWNER', 'MEMBER', 'COLLABORATOR']);
const workflowRun = context.payload.workflow_run;
let prNumber = workflowRun.pull_requests?.[0]?.number;
if (!prNumber) {
const headOwner = workflowRun.head_repository?.owner?.login;
const headBranch = workflowRun.head_branch;
if (headOwner && headBranch) {
core.info(`workflow_run payload did not include a PR number; looking up PR by ${headOwner}:${headBranch}.`);
const { data: pullRequests } = await github.rest.pulls.list({
owner: context.repo.owner,
repo: context.repo.repo,
state: 'open',
head: `${headOwner}:${headBranch}`
});
const matchedPullRequest = pullRequests.find((pullRequest) => pullRequest.head.sha === workflowRun.head_sha) ?? pullRequests[0];
prNumber = matchedPullRequest?.number;
}
}
if (!prNumber) {
core.warning('No pull request was found on the workflow_run payload. Skipping privileged docs preview publish.');
core.setOutput('trusted', 'false');
return;
}
const { data: pullRequest } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: prNumber
});
const trusted = allowedAssociations.has(pullRequest.author_association);
core.setOutput('trusted', trusted ? 'true' : 'false');
core.setOutput('number', String(pullRequest.number));
core.setOutput('sha', pullRequest.head.sha);
if (trusted) {
core.info(`PR #${pullRequest.number} author association is ${pullRequest.author_association}; privileged docs preview publish is allowed.`);
} else {
core.warning(`PR #${pullRequest.number} author association is ${pullRequest.author_association}; skipping privileged docs preview publish.`);
}
push:
needs: check_pr_author
runs-on: ubuntu-24.04
# Only trusted repository members/collaborators can promote PR-built artifacts.
if: ${{ needs.check_pr_author.outputs.trusted == 'true' }}
permissions:
contents: read
packages: write
attestations: write
id-token: write
pull-requests: write
issues: write
actions: read
steps: steps:
- name: Download build artifact - name: Download build artifact
...@@ -34,12 +99,6 @@ jobs: ...@@ -34,12 +99,6 @@ jobs:
run-id: ${{ github.event.workflow_run.id }} run-id: ${{ github.event.workflow_run.id }}
github-token: ${{ secrets.GITHUB_TOKEN }} github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Read PR metadata
id: pr
run: |
echo "number=$(cat /tmp/pr-number.txt)" >> "$GITHUB_OUTPUT"
echo "sha=$(cat /tmp/pr-sha.txt)" >> "$GITHUB_OUTPUT"
- name: Load Docker image - name: Load Docker image
run: docker load --input /tmp/docs-image.tar run: docker load --input /tmp/docs-image.tar
...@@ -55,9 +114,9 @@ jobs: ...@@ -55,9 +114,9 @@ jobs:
- name: Tag and push Docker image - name: Tag and push Docker image
run: | run: |
docker tag fastgpt-docs-pr:${{ steps.pr.outputs.sha }} \ docker tag fastgpt-docs-pr:${{ needs.check_pr_author.outputs.sha }} \
ghcr.io/${{ github.repository_owner }}/fastgpt-docs-pr:${{ steps.pr.outputs.sha }} ghcr.io/${{ github.repository_owner }}/fastgpt-docs-pr:${{ needs.check_pr_author.outputs.sha }}
docker push ghcr.io/${{ github.repository_owner }}/fastgpt-docs-pr:${{ steps.pr.outputs.sha }} docker push ghcr.io/${{ github.repository_owner }}/fastgpt-docs-pr:${{ needs.check_pr_author.outputs.sha }}
- name: Update deployment image - name: Update deployment image
env: env:
...@@ -69,10 +128,10 @@ jobs: ...@@ -69,10 +128,10 @@ jobs:
chmod 600 "$KUBECONFIG_FILE" chmod 600 "$KUBECONFIG_FILE"
kubectl --kubeconfig "$KUBECONFIG_FILE" set image deployment/fastgpt-docs-preview \ kubectl --kubeconfig "$KUBECONFIG_FILE" set image deployment/fastgpt-docs-preview \
fastgpt-docs-preview=ghcr.io/${{ github.repository_owner }}/fastgpt-docs-pr:${{ steps.pr.outputs.sha }} fastgpt-docs-preview=ghcr.io/${{ github.repository_owner }}/fastgpt-docs-pr:${{ needs.check_pr_author.outputs.sha }}
kubectl --kubeconfig "$KUBECONFIG_FILE" annotate deployment/fastgpt-docs-preview \ kubectl --kubeconfig "$KUBECONFIG_FILE" annotate deployment/fastgpt-docs-preview \
originImageName="ghcr.io/${{ github.repository_owner }}/fastgpt-docs-pr:${{ steps.pr.outputs.sha }}" --overwrite originImageName="ghcr.io/${{ github.repository_owner }}/fastgpt-docs-pr:${{ needs.check_pr_author.outputs.sha }}" --overwrite
- name: Format preview timestamp - name: Format preview timestamp
id: preview_time id: preview_time
...@@ -80,11 +139,11 @@ jobs: ...@@ -80,11 +139,11 @@ jobs:
echo "value=$(TZ='Asia/Shanghai' date '+%Y-%m-%d %H:%M:%S (UTC+8)')" >> "$GITHUB_OUTPUT" echo "value=$(TZ='Asia/Shanghai' date '+%Y-%m-%d %H:%M:%S (UTC+8)')" >> "$GITHUB_OUTPUT"
- name: Add PR comment on success - name: Add PR comment on success
if: success() && steps.pr.outputs.number != '' if: success() && needs.check_pr_author.outputs.number != ''
uses: actions/github-script@v7 uses: actions/github-script@v7
with: with:
script: | script: |
const prNumber = parseInt('${{ steps.pr.outputs.number }}'); const prNumber = parseInt('${{ needs.check_pr_author.outputs.number }}');
const marker = '<!-- fastgpt-docs-preview -->'; const marker = '<!-- fastgpt-docs-preview -->';
const { data: comments } = await github.rest.issues.listComments({ const { data: comments } = await github.rest.issues.listComments({
...@@ -103,7 +162,7 @@ jobs: ...@@ -103,7 +162,7 @@ jobs:
🔗 [👀 Click here to visit preview](https://pueuoharpgcl.sealoshzh.site) 🔗 [👀 Click here to visit preview](https://pueuoharpgcl.sealoshzh.site)
\`\`\` \`\`\`
ghcr.io/${{ github.repository_owner }}/fastgpt-docs-pr:${{ steps.pr.outputs.sha }} ghcr.io/${{ github.repository_owner }}/fastgpt-docs-pr:${{ needs.check_pr_author.outputs.sha }}
\`\`\` \`\`\`
🕒 Time: ${{ steps.preview_time.outputs.value }} 🕒 Time: ${{ steps.preview_time.outputs.value }}
......
...@@ -14,11 +14,87 @@ permissions: ...@@ -14,11 +14,87 @@ permissions:
contents: read contents: read
jobs: jobs:
detect_changes:
runs-on: ubuntu-24.04
permissions:
contents: read
pull-requests: read
outputs:
should_build: ${{ steps.preview_matrix.outputs.should_build }}
matrix: ${{ steps.preview_matrix.outputs.matrix }}
steps:
- name: Build preview image matrix
id: preview_matrix
uses: actions/github-script@v7
with:
script: |
const pullNumber = context.payload.pull_request.number;
const changedFiles = await github.paginate(github.rest.pulls.listFiles, {
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: pullNumber,
per_page: 100
});
const fileNames = changedFiles.map((file) => file.filename);
const hasPath = (paths) => fileNames.some((fileName) =>
paths.some((path) => fileName === path || fileName.startsWith(`${path}/`))
);
const images = [];
const addImage = (image) => images.push(image);
if (hasPath([
'projects/app',
'packages',
'sdk',
'package.json',
'pnpm-lock.yaml',
'pnpm-workspace.yaml',
'tsconfig.json',
'.npmrc',
'turbo.json'
])) {
addImage({
image: 'fastgpt',
image_name: 'fastgpt',
dockerfile: 'projects/app/Dockerfile',
description: 'fastgpt-pr image'
});
}
if (hasPath(['projects/code-sandbox'])) {
addImage({
image: 'code-sandbox',
image_name: 'fastgpt-code-sandbox',
dockerfile: 'projects/code-sandbox/Dockerfile',
description: 'fastgpt-code-sandbox-pr image'
});
}
if (hasPath(['projects/mcp_server'])) {
addImage({
image: 'mcp_server',
image_name: 'fastgpt-mcp-server',
dockerfile: 'projects/mcp_server/Dockerfile',
description: 'fastgpt-mcp_server-pr image'
});
}
const matrix = images.length > 0
? { include: images }
: { include: [{ image: 'noop', image_name: 'noop', dockerfile: 'noop', description: 'noop' }] };
core.info(`Preview images selected: ${images.map((image) => image.image).join(', ') || 'none'}`);
core.setOutput('should_build', images.length > 0 ? 'true' : 'false');
core.setOutput('matrix', JSON.stringify(matrix));
build: build:
needs: detect_changes
if: ${{ needs.detect_changes.outputs.should_build == 'true' }}
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
strategy: strategy:
matrix: matrix: ${{ fromJSON(needs.detect_changes.outputs.matrix) }}
image: [fastgpt, code-sandbox, mcp_server]
fail-fast: false fail-fast: false
steps: steps:
...@@ -28,23 +104,6 @@ jobs: ...@@ -28,23 +104,6 @@ jobs:
ref: ${{ github.event.pull_request.head.sha }} ref: ${{ github.event.pull_request.head.sha }}
repository: ${{ github.event.pull_request.head.repo.full_name }} repository: ${{ github.event.pull_request.head.repo.full_name }}
- name: Set image config
id: config
run: |
if [[ "${{ matrix.image }}" == "fastgpt" ]]; then
echo "DOCKERFILE=projects/app/Dockerfile" >> $GITHUB_OUTPUT
echo "DESCRIPTION=fastgpt-pr image" >> $GITHUB_OUTPUT
echo "IMAGE_NAME=fastgpt" >> $GITHUB_OUTPUT
elif [[ "${{ matrix.image }}" == "code-sandbox" ]]; then
echo "DOCKERFILE=projects/code-sandbox/Dockerfile" >> $GITHUB_OUTPUT
echo "DESCRIPTION=fastgpt-code-sandbox-pr image" >> $GITHUB_OUTPUT
echo "IMAGE_NAME=fastgpt-code-sandbox" >> $GITHUB_OUTPUT
elif [[ "${{ matrix.image }}" == "mcp_server" ]]; then
echo "DOCKERFILE=projects/mcp_server/Dockerfile" >> $GITHUB_OUTPUT
echo "DESCRIPTION=fastgpt-mcp_server-pr image" >> $GITHUB_OUTPUT
echo "IMAGE_NAME=fastgpt-mcp-server" >> $GITHUB_OUTPUT
fi
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3 uses: docker/setup-buildx-action@v3
...@@ -52,15 +111,15 @@ jobs: ...@@ -52,15 +111,15 @@ jobs:
uses: docker/build-push-action@v6 uses: docker/build-push-action@v6
with: with:
context: . context: .
file: ${{ steps.config.outputs.DOCKERFILE }} file: ${{ matrix.dockerfile }}
platforms: linux/amd64 platforms: linux/amd64
push: false push: false
tags: ${{ steps.config.outputs.IMAGE_NAME }}-pr:${{ github.event.pull_request.head.sha }} tags: ${{ matrix.image_name }}-pr:${{ github.event.pull_request.head.sha }}
labels: | labels: |
org.opencontainers.image.source=https://github.com/${{ github.repository_owner }}/FastGPT org.opencontainers.image.source=https://github.com/${{ github.repository_owner }}/FastGPT
org.opencontainers.image.description=${{ steps.config.outputs.DESCRIPTION }} org.opencontainers.image.description=${{ matrix.description }}
org.opencontainers.image.revision=${{ github.event.pull_request.head.sha }} org.opencontainers.image.revision=${{ github.event.pull_request.head.sha }}
outputs: type=docker,dest=/tmp/${{ steps.config.outputs.IMAGE_NAME }}-image.tar outputs: type=docker,dest=/tmp/${{ matrix.image_name }}-image.tar
cache-from: type=gha,scope=${{ matrix.image }} cache-from: type=gha,scope=${{ matrix.image }}
cache-to: type=gha,mode=max,scope=${{ matrix.image }} cache-to: type=gha,mode=max,scope=${{ matrix.image }}
...@@ -75,7 +134,7 @@ jobs: ...@@ -75,7 +134,7 @@ jobs:
with: with:
name: preview-${{ matrix.image }}-image name: preview-${{ matrix.image }}-image
path: | path: |
/tmp/${{ steps.config.outputs.IMAGE_NAME }}-image.tar /tmp/${{ matrix.image_name }}-image.tar
/tmp/pr-number.txt /tmp/pr-number.txt
/tmp/pr-sha.txt /tmp/pr-sha.txt
/tmp/image-type.txt /tmp/image-type.txt
......
...@@ -12,51 +12,127 @@ concurrency: ...@@ -12,51 +12,127 @@ concurrency:
permissions: permissions:
contents: read contents: read
packages: write
attestations: write
id-token: write
pull-requests: write
issues: write
actions: read
jobs: jobs:
push: check_pr_author:
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
# Only push when the build succeeded # Only inspect the upstream PR when the build succeeded.
if: ${{ github.event.workflow_run.conclusion == 'success' }} if: ${{ github.event.workflow_run.conclusion == 'success' }}
permissions:
contents: read
pull-requests: read
actions: read
outputs:
trusted: ${{ steps.trust.outputs.trusted }}
should_publish: ${{ steps.trust.outputs.should_publish }}
number: ${{ steps.trust.outputs.number }}
sha: ${{ steps.trust.outputs.sha }}
matrix: ${{ steps.trust.outputs.matrix }}
steps:
- name: Check trusted PR author
id: trust
uses: actions/github-script@v7
with:
script: |
const allowedAssociations = new Set(['OWNER', 'MEMBER', 'COLLABORATOR']);
const emptyMatrix = JSON.stringify({
include: [{ image: 'noop', artifact_name: 'noop', image_name: 'noop' }]
});
const workflowRun = context.payload.workflow_run;
let prNumber = workflowRun.pull_requests?.[0]?.number;
core.setOutput('trusted', 'false');
core.setOutput('should_publish', 'false');
core.setOutput('matrix', emptyMatrix);
if (!prNumber) {
const headOwner = workflowRun.head_repository?.owner?.login;
const headBranch = workflowRun.head_branch;
if (headOwner && headBranch) {
core.info(`workflow_run payload did not include a PR number; looking up PR by ${headOwner}:${headBranch}.`);
const { data: pullRequests } = await github.rest.pulls.list({
owner: context.repo.owner,
repo: context.repo.repo,
state: 'open',
head: `${headOwner}:${headBranch}`
});
const matchedPullRequest = pullRequests.find((pullRequest) => pullRequest.head.sha === workflowRun.head_sha) ?? pullRequests[0];
prNumber = matchedPullRequest?.number;
}
}
if (!prNumber) {
core.warning('No pull request was found on the workflow_run payload. Skipping privileged FastGPT preview publish.');
return;
}
const { data: pullRequest } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: prNumber
});
const trusted = allowedAssociations.has(pullRequest.author_association);
core.setOutput('trusted', trusted ? 'true' : 'false');
core.setOutput('number', String(pullRequest.number));
core.setOutput('sha', pullRequest.head.sha);
if (!trusted) {
core.warning(`PR #${pullRequest.number} author association is ${pullRequest.author_association}; skipping privileged FastGPT preview publish.`);
return;
}
const artifactConfigs = [
{ image: 'fastgpt', artifact_name: 'preview-fastgpt-image', image_name: 'fastgpt' },
{ image: 'code-sandbox', artifact_name: 'preview-code-sandbox-image', image_name: 'fastgpt-code-sandbox' },
{ image: 'mcp_server', artifact_name: 'preview-mcp_server-image', image_name: 'fastgpt-mcp-server' }
];
const artifacts = await github.paginate(github.rest.actions.listWorkflowRunArtifacts, {
owner: context.repo.owner,
repo: context.repo.repo,
run_id: workflowRun.id,
per_page: 100
});
const artifactNames = new Set(artifacts.map((artifact) => artifact.name));
const images = artifactConfigs.filter((artifactConfig) =>
artifactNames.has(artifactConfig.artifact_name)
);
const matrix = images.length > 0 ? { include: images } : JSON.parse(emptyMatrix);
core.setOutput('should_publish', images.length > 0 ? 'true' : 'false');
core.setOutput('matrix', JSON.stringify(matrix));
core.info(`PR #${pullRequest.number} author association is ${pullRequest.author_association}; preview images to publish: ${images.map((image) => image.image).join(', ') || 'none'}.`);
push:
needs: check_pr_author
runs-on: ubuntu-24.04
# Only trusted repository members/collaborators can promote PR-built artifacts.
if: ${{ needs.check_pr_author.outputs.trusted == 'true' && needs.check_pr_author.outputs.should_publish == 'true' }}
permissions:
contents: read
packages: write
attestations: write
id-token: write
pull-requests: write
issues: write
actions: read
strategy: strategy:
matrix: matrix: ${{ fromJSON(needs.check_pr_author.outputs.matrix) }}
image: [fastgpt, code-sandbox, mcp_server]
fail-fast: false fail-fast: false
steps: steps:
- name: Set image config
id: config
run: |
if [[ "${{ matrix.image }}" == "fastgpt" ]]; then
echo "IMAGE_NAME=fastgpt" >> $GITHUB_OUTPUT
elif [[ "${{ matrix.image }}" == "code-sandbox" ]]; then
echo "IMAGE_NAME=fastgpt-code-sandbox" >> $GITHUB_OUTPUT
elif [[ "${{ matrix.image }}" == "mcp_server" ]]; then
echo "IMAGE_NAME=fastgpt-mcp-server" >> $GITHUB_OUTPUT
fi
- name: Download build artifact - name: Download build artifact
uses: actions/download-artifact@v4 uses: actions/download-artifact@v4
with: with:
name: preview-${{ matrix.image }}-image name: ${{ matrix.artifact_name }}
path: /tmp path: /tmp
run-id: ${{ github.event.workflow_run.id }} run-id: ${{ github.event.workflow_run.id }}
github-token: ${{ secrets.GITHUB_TOKEN }} github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Read PR metadata
id: pr
run: |
echo "number=$(cat /tmp/pr-number.txt)" >> "$GITHUB_OUTPUT"
echo "sha=$(cat /tmp/pr-sha.txt)" >> "$GITHUB_OUTPUT"
- name: Load Docker image - name: Load Docker image
run: docker load --input /tmp/${{ steps.config.outputs.IMAGE_NAME }}-image.tar run: docker load --input /tmp/${{ matrix.image_name }}-image.tar
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3 uses: docker/setup-buildx-action@v3
...@@ -70,8 +146,8 @@ jobs: ...@@ -70,8 +146,8 @@ jobs:
- name: Tag and push Docker image - name: Tag and push Docker image
run: | run: |
SHA="${{ steps.pr.outputs.sha }}" SHA="${{ needs.check_pr_author.outputs.sha }}"
docker tag ${{ steps.config.outputs.IMAGE_NAME }}-pr:${SHA} \ docker tag ${{ matrix.image_name }}-pr:${SHA} \
ghcr.io/${{ github.repository_owner }}/fastgpt-pr:${{ matrix.image }}_${SHA} ghcr.io/${{ github.repository_owner }}/fastgpt-pr:${{ matrix.image }}_${SHA}
docker push ghcr.io/${{ github.repository_owner }}/fastgpt-pr:${{ matrix.image }}_${SHA} docker push ghcr.io/${{ github.repository_owner }}/fastgpt-pr:${{ matrix.image }}_${SHA}
...@@ -81,11 +157,11 @@ jobs: ...@@ -81,11 +157,11 @@ jobs:
echo "value=$(TZ='Asia/Shanghai' date '+%Y-%m-%d %H:%M:%S (UTC+8)')" >> "$GITHUB_OUTPUT" echo "value=$(TZ='Asia/Shanghai' date '+%Y-%m-%d %H:%M:%S (UTC+8)')" >> "$GITHUB_OUTPUT"
- name: Add PR comment on success - name: Add PR comment on success
if: success() && steps.pr.outputs.number != '' if: success() && needs.check_pr_author.outputs.number != ''
uses: actions/github-script@v7 uses: actions/github-script@v7
with: with:
script: | script: |
const prNumber = parseInt('${{ steps.pr.outputs.number }}'); const prNumber = parseInt('${{ needs.check_pr_author.outputs.number }}');
const marker = '<!-- fastgpt-preview-${{ matrix.image }} -->'; const marker = '<!-- fastgpt-preview-${{ matrix.image }} -->';
const { data: comments } = await github.rest.issues.listComments({ const { data: comments } = await github.rest.issues.listComments({
...@@ -102,7 +178,7 @@ jobs: ...@@ -102,7 +178,7 @@ jobs:
✅ **Build Successful** - Preview ${{ matrix.image }} Image for this PR: ✅ **Build Successful** - Preview ${{ matrix.image }} Image for this PR:
\`\`\` \`\`\`
ghcr.io/${{ github.repository_owner }}/fastgpt-pr:${{ matrix.image }}_${{ steps.pr.outputs.sha }} ghcr.io/${{ github.repository_owner }}/fastgpt-pr:${{ matrix.image }}_${{ needs.check_pr_author.outputs.sha }}
\`\`\` \`\`\`
🕒 Time: ${{ steps.preview_time.outputs.value }} 🕒 Time: ${{ steps.preview_time.outputs.value }}
......
...@@ -5,13 +5,21 @@ on: ...@@ -5,13 +5,21 @@ on:
paths: paths:
- "pro" - "pro"
- "pro/**" - "pro/**"
- "packages/**" - "packages/global/**"
- "sdk/**" - "packages/service/**"
- "packages/web/**"
- "sdk/otel/**"
- "sdk/storage/**"
- "package.json"
- "pnpm-lock.yaml" - "pnpm-lock.yaml"
- "pnpm-workspace.yaml" - "pnpm-workspace.yaml"
- "tsconfig.json"
- "vitest.config.mts"
- "eslint.config.mjs"
- "turbo.json" - "turbo.json"
- ".npmrc"
- ".gitmodules" - ".gitmodules"
- ".github/workflows/fastgpt-pro-test.yaml" - ".github/workflows/test-fastgpt-pro.yaml"
workflow_dispatch: workflow_dispatch:
concurrency: concurrency:
......
name: 'FastGPT-Test' name: 'FastGPT-Test'
on: on:
pull_request: pull_request:
paths:
- 'packages/global/**'
- 'packages/service/**'
- 'packages/web/**'
- 'projects/app/**'
- 'sdk/**'
- 'test/**'
- 'package.json'
- 'pnpm-lock.yaml'
- 'pnpm-workspace.yaml'
- 'turbo.json'
- 'tsconfig.json'
- 'vitest.config.mts'
- 'eslint.config.mjs'
- '.npmrc'
- '.github/workflows/test-fastgpt.yaml'
workflow_dispatch: workflow_dispatch:
# Only one build per PR branch at a time # Only one build per PR branch at a time
...@@ -11,12 +27,78 @@ concurrency: ...@@ -11,12 +27,78 @@ concurrency:
permissions: permissions:
# Required to checkout the code # Required to checkout the code
contents: read contents: read
# Required to put a comment into the pull-request
issues: write
pull-requests: write
jobs: jobs:
detect-changes:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
outputs:
run_global: ${{ steps.scope.outputs.run_global }}
run_service: ${{ steps.scope.outputs.run_service }}
run_app: ${{ steps.scope.outputs.run_app }}
should_report: ${{ steps.scope.outputs.should_report }}
steps:
- name: Detect affected test scopes
id: scope
uses: actions/github-script@v7
with:
script: |
const setOutputs = ({ global, service, app }) => {
const shouldReport = global || service || app;
core.setOutput('run_global', global ? 'true' : 'false');
core.setOutput('run_service', service ? 'true' : 'false');
core.setOutput('run_app', app ? 'true' : 'false');
core.setOutput('should_report', shouldReport ? 'true' : 'false');
core.info(`Test scopes selected: global=${global}, service=${service}, app=${app}`);
};
if (context.eventName !== 'pull_request') {
setOutputs({ global: true, service: true, app: true });
return;
}
const changedFiles = await github.paginate(github.rest.pulls.listFiles, {
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.payload.pull_request.number,
per_page: 100
});
const fileNames = changedFiles.map((file) => file.filename);
const hasPath = (paths) => fileNames.some((fileName) =>
paths.some((path) => fileName === path || fileName.startsWith(`${path}/`))
);
const affectsAll = hasPath([
'package.json',
'pnpm-lock.yaml',
'pnpm-workspace.yaml',
'turbo.json',
'tsconfig.json',
'vitest.config.mts',
'eslint.config.mjs',
'.npmrc',
'test',
'.github/workflows/test-fastgpt.yaml'
]);
const runGlobal = affectsAll || hasPath(['packages/global']);
const runService = affectsAll || hasPath(['packages/global', 'packages/service', 'sdk']);
const runApp = affectsAll || hasPath([
'packages/global',
'packages/service',
'packages/web',
'projects/app',
'sdk'
]);
setOutputs({ global: runGlobal, service: runService, app: runApp });
test-global: test-global:
needs: detect-changes
if: ${{ needs.detect-changes.outputs.run_global == 'true' }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
...@@ -49,6 +131,8 @@ jobs: ...@@ -49,6 +131,8 @@ jobs:
packages/global/coverage/coverage-summary.json packages/global/coverage/coverage-summary.json
test-service: test-service:
needs: detect-changes
if: ${{ needs.detect-changes.outputs.run_service == 'true' }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
...@@ -81,6 +165,8 @@ jobs: ...@@ -81,6 +165,8 @@ jobs:
packages/service/coverage/coverage-summary.json packages/service/coverage/coverage-summary.json
test-app: test-app:
needs: detect-changes
if: ${{ needs.detect-changes.outputs.run_app == 'true' }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
...@@ -113,8 +199,13 @@ jobs: ...@@ -113,8 +199,13 @@ jobs:
report-coverage: report-coverage:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: [test-global, test-service, test-app] needs: [detect-changes, test-global, test-service, test-app]
if: always() if: ${{ always() && needs.detect-changes.outputs.should_report == 'true' }}
permissions:
contents: read
# Required to put a comment into the pull-request
issues: write
pull-requests: write
steps: steps:
- name: 'Download Coverage Artifacts' - name: 'Download Coverage Artifacts'
uses: actions/download-artifact@v4 uses: actions/download-artifact@v4
...@@ -211,8 +302,11 @@ jobs: ...@@ -211,8 +302,11 @@ jobs:
- name: 'Check Test Results' - name: 'Check Test Results'
run: | run: |
if [ "${{ needs.test-global.result }}" != "success" ] || if { [ "${{ needs.test-global.result }}" != "success" ] &&
[ "${{ needs.test-service.result }}" != "success" ] || [ "${{ needs.test-global.result }}" != "skipped" ]; } ||
[ "${{ needs.test-app.result }}" != "success" ]; then { [ "${{ needs.test-service.result }}" != "success" ] &&
[ "${{ needs.test-service.result }}" != "skipped" ]; } ||
{ [ "${{ needs.test-app.result }}" != "success" ] &&
[ "${{ needs.test-app.result }}" != "skipped" ]; }; then
exit 1 exit 1
fi fi
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment