mirror of
https://gitee.com/nocobase/nocobase.git
synced 2025-05-05 05:29:26 +08:00
Merge branch 'main' into next
This commit is contained in:
commit
1e3f988c48
4
.github/workflows/manual-merge.yml
vendored
4
.github/workflows/manual-merge.yml
vendored
@ -65,6 +65,10 @@ jobs:
|
||||
run: echo "user-id=$(gh api "/users/${{ steps.app-token.outputs.app-slug }}[bot]" --jq .id)" >> "$GITHUB_OUTPUT"
|
||||
env:
|
||||
GH_TOKEN: ${{ steps.app-token.outputs.token }}
|
||||
- name: Set user
|
||||
run: |
|
||||
git config --global user.name '${{ steps.app-token.outputs.app-slug }}[bot]'
|
||||
git config --global user.email '${{ steps.get-user-id.outputs.user-id }}+${{ steps.app-token.outputs.app-slug }}[bot]@users.noreply.github.com>'
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
|
@ -12,12 +12,28 @@ import { BelongsTo, HasOne } from 'sequelize';
|
||||
import { Collection, Model, modelAssociationByKey } from '@nocobase/database';
|
||||
import Application, { DefaultContext } from '@nocobase/server';
|
||||
import { Context as ActionContext, Next } from '@nocobase/actions';
|
||||
import PluginErrorHandler from '@nocobase/plugin-error-handler';
|
||||
|
||||
import WorkflowPlugin, { EventOptions, Trigger, WorkflowModel, toJSON } from '@nocobase/plugin-workflow';
|
||||
import WorkflowPlugin, {
|
||||
EXECUTION_STATUS,
|
||||
EventOptions,
|
||||
Trigger,
|
||||
WorkflowModel,
|
||||
toJSON,
|
||||
} from '@nocobase/plugin-workflow';
|
||||
import { joinCollectionName, parseCollectionName } from '@nocobase/data-source-manager';
|
||||
|
||||
interface Context extends ActionContext, DefaultContext {}
|
||||
|
||||
class RequestOnActionTriggerError extends Error {
|
||||
status = 400;
|
||||
messages: any[] = [];
|
||||
constructor(message) {
|
||||
super(message);
|
||||
this.name = 'RequestOnActionTriggerError';
|
||||
}
|
||||
}
|
||||
|
||||
export default class extends Trigger {
|
||||
static TYPE = 'action';
|
||||
|
||||
@ -39,6 +55,16 @@ export default class extends Trigger {
|
||||
}
|
||||
|
||||
workflow.app.dataSourceManager.use(triggerWorkflowActionMiddleware);
|
||||
|
||||
workflow.app.pm.get(PluginErrorHandler).errorHandler.register(
|
||||
(err) => err instanceof RequestOnActionTriggerError || err.name === 'RequestOnActionTriggerError',
|
||||
async (err, ctx) => {
|
||||
ctx.body = {
|
||||
errors: err.messages,
|
||||
};
|
||||
ctx.status = err.status;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
getTargetCollection(collection: Collection, association: string) {
|
||||
@ -168,7 +194,35 @@ export default class extends Trigger {
|
||||
}
|
||||
|
||||
for (const event of syncGroup) {
|
||||
await this.workflow.trigger(event[0], event[1]);
|
||||
const processor = await this.workflow.trigger(event[0], event[1], { httpContext: context });
|
||||
|
||||
// NOTE: workflow trigger failed
|
||||
if (!processor) {
|
||||
return context.throw(500);
|
||||
}
|
||||
|
||||
const { lastSavedJob, nodesMap } = processor;
|
||||
const lastNode = nodesMap.get(lastSavedJob?.nodeId);
|
||||
// NOTE: passthrough
|
||||
if (processor.execution.status === EXECUTION_STATUS.RESOLVED) {
|
||||
if (lastNode?.type === 'end') {
|
||||
return;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// NOTE: intercept
|
||||
if (processor.execution.status < EXECUTION_STATUS.STARTED) {
|
||||
if (lastNode?.type !== 'end') {
|
||||
return context.throw(500, 'Workflow on your action failed, please contact the administrator');
|
||||
}
|
||||
|
||||
const err = new RequestOnActionTriggerError('Request failed');
|
||||
err.status = 400;
|
||||
err.messages = context.state.messages;
|
||||
return context.throw(err.status, err);
|
||||
}
|
||||
// NOTE: should not be pending
|
||||
return context.throw(500, 'Workflow on your action hangs, please contact the administrator');
|
||||
}
|
||||
|
||||
for (const event of asyncGroup) {
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
import { omit } from 'lodash';
|
||||
import Database from '@nocobase/database';
|
||||
import { EXECUTION_STATUS } from '@nocobase/plugin-workflow';
|
||||
import { EXECUTION_STATUS, JOB_STATUS } from '@nocobase/plugin-workflow';
|
||||
import { getApp, sleep } from '@nocobase/plugin-workflow-test';
|
||||
import { MockServer } from '@nocobase/test';
|
||||
|
||||
@ -30,7 +30,7 @@ describe('workflow > action-trigger', () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
app = await getApp({
|
||||
plugins: ['users', 'auth', 'acl', 'data-source-manager', 'system-settings', Plugin],
|
||||
plugins: ['users', 'auth', 'acl', 'data-source-manager', 'system-settings', 'error-handler', Plugin],
|
||||
acl: true,
|
||||
});
|
||||
await app.pm.get('auth').install();
|
||||
@ -529,6 +529,72 @@ describe('workflow > action-trigger', () => {
|
||||
expect(e3s.length).toBe(1);
|
||||
expect(e3s[0].status).toBe(EXECUTION_STATUS.RESOLVED);
|
||||
});
|
||||
|
||||
it('execution failed on node error', async () => {
|
||||
const workflow = await WorkflowModel.create({
|
||||
enabled: true,
|
||||
type: 'action',
|
||||
sync: true,
|
||||
config: {
|
||||
collection: 'posts',
|
||||
},
|
||||
});
|
||||
|
||||
const n1 = await workflow.createNode({
|
||||
type: 'error',
|
||||
});
|
||||
|
||||
const res1 = await userAgents[0].resource('posts').create({
|
||||
values: { title: 't1' },
|
||||
triggerWorkflows: `${workflow.key}`,
|
||||
});
|
||||
expect(res1.status).toBe(500);
|
||||
});
|
||||
|
||||
it('execution failed on end node success', async () => {
|
||||
const workflow = await WorkflowModel.create({
|
||||
enabled: true,
|
||||
type: 'action',
|
||||
sync: true,
|
||||
config: {
|
||||
collection: 'posts',
|
||||
},
|
||||
});
|
||||
|
||||
const n1 = await workflow.createNode({
|
||||
type: 'end',
|
||||
});
|
||||
|
||||
const res1 = await userAgents[0].resource('posts').create({
|
||||
values: { title: 't1' },
|
||||
triggerWorkflows: `${workflow.key}`,
|
||||
});
|
||||
expect(res1.status).toBe(200);
|
||||
});
|
||||
|
||||
it('execution failed on end node success', async () => {
|
||||
const workflow = await WorkflowModel.create({
|
||||
enabled: true,
|
||||
type: 'action',
|
||||
sync: true,
|
||||
config: {
|
||||
collection: 'posts',
|
||||
},
|
||||
});
|
||||
|
||||
const n1 = await workflow.createNode({
|
||||
type: 'end',
|
||||
config: {
|
||||
endStatus: JOB_STATUS.FAILED,
|
||||
},
|
||||
});
|
||||
|
||||
const res1 = await userAgents[0].resource('posts').create({
|
||||
values: { title: 't1' },
|
||||
triggerWorkflows: `${workflow.key}`,
|
||||
});
|
||||
expect(res1.status).toBe(400);
|
||||
});
|
||||
});
|
||||
|
||||
describe('global workflow', () => {
|
||||
|
Loading…
x
Reference in New Issue
Block a user