Skip to content

feat(s3): add short access links and SDK core #2137

feat(s3): add short access links and SDK core

feat(s3): add short access links and SDK core #2137

Workflow file for this run

name: 'FastGPT-Test'
on:
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:
# Only one build per PR branch at a time
concurrency:
group: 'test-fastgpt-${{ github.event.pull_request.number || github.ref }}'
cancel-in-progress: true
permissions:
# Required to checkout the code
contents: read
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:
needs: detect-changes
if: ${{ needs.detect-changes.outputs.run_global == 'true' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.ref || github.ref }}
repository: ${{ github.event.pull_request.head.repo.full_name ||
github.repository }}
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: '24'
cache: 'pnpm'
- name: 'Install Deps'
run: pnpm install --frozen-lockfile
- name: 'Test Global'
run: pnpm test:global
- name: 'Upload Coverage (Global)'
if: always() && hashFiles('packages/global/coverage/coverage-summary.json') !=
''
uses: actions/upload-artifact@v4
with:
name: coverage-global
path: |
packages/global/coverage/coverage-final.json
packages/global/coverage/coverage-summary.json
test-service:
needs: detect-changes
if: ${{ needs.detect-changes.outputs.run_service == 'true' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.ref || github.ref }}
repository: ${{ github.event.pull_request.head.repo.full_name ||
github.repository }}
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: '24'
cache: 'pnpm'
- name: 'Install Deps'
run: pnpm install --frozen-lockfile
- name: 'Test Service'
run: pnpm test:service
- name: 'Upload Coverage (Service)'
if: always() && hashFiles('packages/service/coverage/coverage-summary.json') !=
''
uses: actions/upload-artifact@v4
with:
name: coverage-service
path: |
packages/service/coverage/coverage-final.json
packages/service/coverage/coverage-summary.json
test-app:
needs: detect-changes
if: ${{ needs.detect-changes.outputs.run_app == 'true' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.ref || github.ref }}
repository: ${{ github.event.pull_request.head.repo.full_name ||
github.repository }}
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: '24'
cache: 'pnpm'
- name: 'Install Deps'
run: pnpm install --frozen-lockfile
- name: 'Test App'
run: pnpm test:app
- name: 'Upload Coverage (App)'
if: always() && hashFiles('projects/app/coverage/coverage-summary.json') != ''
uses: actions/upload-artifact@v4
with:
name: coverage-app
path: |
projects/app/coverage/coverage-final.json
projects/app/coverage/coverage-summary.json
report-coverage:
runs-on: ubuntu-latest
needs: [detect-changes, test-global, test-service, test-app]
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:
- name: 'Download Coverage Artifacts'
uses: actions/download-artifact@v4
with:
path: coverage-artifacts
pattern: coverage-*
- name: 'Report Coverage'
if: github.event_name == 'pull_request'
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const path = require('path');
const marker = '<!-- fastgpt-coverage-report -->';
const packages = [
{ name: 'Global', dir: 'coverage-global' },
{ name: 'Service', dir: 'coverage-service' },
{ name: 'App', dir: 'coverage-app' }
];
const formatPct = (value) => {
if (typeof value !== 'number') return 'N/A';
return `${value.toFixed(2)}%`;
};
const rows = packages.map((pkg) => {
const summaryPath = path.join(
process.cwd(),
'coverage-artifacts',
pkg.dir,
'coverage-summary.json'
);
if (!fs.existsSync(summaryPath)) {
return `| ${pkg.name} | N/A | N/A | N/A | N/A |`;
}
const summary = JSON.parse(fs.readFileSync(summaryPath, 'utf8'));
const total = summary.total || {};
return [
`| ${pkg.name}`,
formatPct(total.statements?.pct),
formatPct(total.branches?.pct),
formatPct(total.functions?.pct),
`${formatPct(total.lines?.pct)} |`
].join(' | ');
});
const body = [
marker,
'## Coverage Report',
'',
'| Package | Statements | Branches | Functions | Lines |',
'| --- | ---: | ---: | ---: | ---: |',
...rows
].join('\n');
await core.summary.addRaw(body).write();
const { owner, repo } = context.repo;
const issue_number = context.payload.pull_request.number;
try {
const comments = await github.rest.issues.listComments({
owner,
repo,
issue_number,
per_page: 100
});
const existing = comments.data.find((comment) =>
comment.body?.includes(marker)
);
if (existing) {
await github.rest.issues.updateComment({
owner,
repo,
comment_id: existing.id,
body
});
} else {
await github.rest.issues.createComment({
owner,
repo,
issue_number,
body
});
}
} catch (error) {
core.warning(`Failed to publish coverage comment: ${error.message}`);
}
- name: 'Check Test Results'
run: |
if { [ "${{ needs.test-global.result }}" != "success" ] &&
[ "${{ needs.test-global.result }}" != "skipped" ]; } ||
{ [ "${{ needs.test-service.result }}" != "success" ] &&
[ "${{ needs.test-service.result }}" != "skipped" ]; } ||
{ [ "${{ needs.test-app.result }}" != "success" ] &&
[ "${{ needs.test-app.result }}" != "skipped" ]; }; then
exit 1
fi