Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions common/config/rush/command-line.json
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,14 @@
"safeForSimultaneousRushProcesses": true,
"shellCommand": "./common/scripts/docker.sh"
},
{
"commandKind": "global",
"name": "docker:patch",
"summary": "Build and push docker images with a custom version",
"description": "Allows building and pushing docker images with a manually specified version tag. Usage: rush docker:patch --version <version> [rush-args]",
"safeForSimultaneousRushProcesses": true,
"shellCommand": "./common/scripts/docker_patch.sh"
},
{
"commandKind": "global",
"name": "docker-server",
Expand Down Expand Up @@ -424,6 +432,22 @@
"longName": "--branch",
"description": "Force formatting of branch",
"associatedCommands": ["fast-format"]
},
{
"parameterKind": "string",
"argumentName": "VERSION",
"required": false,
"longName": "--version",
"description": "The version tag to use for docker images",
"associatedCommands": ["docker:patch"]
},
{
"parameterKind": "string",
"argumentName": "PLATFORM",
"required": false,
"longName": "--platform",
"description": "The target platform for docker build (e.g., linux/amd64). Defaults to linux/amd64.",
"associatedCommands": ["docker:patch"]
}
// {
// /**
Expand Down
2 changes: 1 addition & 1 deletion common/scripts/docker_build.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env bash

version=$(git rev-parse HEAD)
version=${DOCKER_VERSION:-$(git rev-parse HEAD)}

# Check for cleanup flag from environment
cleanup=false
Expand Down
44 changes: 44 additions & 0 deletions common/scripts/docker_patch.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#!/usr/bin/env bash

# This script allows building and pushing docker images with a custom version tag.
# It can be run interactively or with the --version flag.

VERSION=""
PLATFORM="linux/amd64"
REMAINING_ARGS=()

while [[ $# -gt 0 ]]; do
case $1 in
--version)
VERSION="$2"
shift 2
;;
--platform)
PLATFORM="$2"
shift 2
;;
*)
REMAINING_ARGS+=("$1")
shift
;;
esac
done

if [ -z "$VERSION" ]; then
read -p "Enter version tag for docker images: " VERSION
fi

if [ -z "$VERSION" ]; then
echo "Error: Version tag is required."
exit 1
fi

export DOCKER_VERSION="$VERSION"
export DOCKER_EXTRA="--platform=$PLATFORM"
echo "Starting docker build and push for version: $DOCKER_VERSION ($PLATFORM)"

# We use 'node common/scripts/install-run-rush.js' to ensure we use the right rush version
node "$(dirname "$0")/install-run-rush.js" docker:build "${REMAINING_ARGS[@]}"
node "$(dirname "$0")/install-run-rush.js" docker:push "${REMAINING_ARGS[@]}"

echo "Docker patch completed for version: $DOCKER_VERSION"
2 changes: 1 addition & 1 deletion common/scripts/docker_tag.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env bash

version=$(git describe --tags --abbrev=0)
version=${DOCKER_VERSION:-$(git describe --tags --abbrev=0)}
rev_version=$(git rev-parse HEAD)

if [ "x$2" = "xstaging" ]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@
<script lang="ts">
import { Ref } from '@hcengineering/core'
import { getClient } from '@hcengineering/presentation'
import { Label } from '@hcengineering/ui'
import { State } from '@hcengineering/process'
import plugin from '../plugin'

export let value: Ref<State>

Expand All @@ -26,4 +28,6 @@

{#if currentState}
{currentState.title}
{:else if value === null}
<span class="opacity-50"><Label label={plugin.string.Started} /></span>
{/if}
72 changes: 41 additions & 31 deletions plugins/process-resources/src/exporter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import core, {
type RefTo,
type ArrOf,
type ModelDb,
type Hierarchy
type Hierarchy,
type Type
} from '@hcengineering/core'
import { getClient } from '@hcengineering/presentation'
import { type Process, type Transition } from '@hcengineering/process'
Expand Down Expand Up @@ -54,12 +55,50 @@ export function exportProcess (proc: Doc): {
processParams(tr.triggerParams, processDoc.masterTag, docs, required, m, h)
for (const action of tr.actions) {
processParams(action.params, processDoc.masterTag, docs, required, m, h)
if (action.results !== undefined) {
for (const res of action.results) {
processType(res.type, docs, required, m, h)
}
}
}
}

if (processDoc.context !== undefined) {
for (const key in processDoc.context) {
const ctx = processDoc.context[key as any]
if (ctx.type !== undefined) {
processType(ctx.type, docs, required, m, h)
}
}
}

if (processDoc.resultType !== undefined) {
processType(processDoc.resultType, docs, required, m, h)
}

return { docs, required }
}

function processType (type: Type<any>, docs: Doc[], required: Array<Ref<Class<Doc>>>, m: ModelDb, h: Hierarchy): void {
if (type._class === core.class.EnumOf) {
const enumRef = (type as EnumOf).of
const enumDoc = m.findObject(enumRef)
if (enumDoc !== undefined && !docs.some((d) => d._id === enumDoc._id)) {
docs.push(enumDoc)
}
}
if (type._class === core.class.RefTo) {
const to = (type as RefTo<Doc>).to
if (h.isDerived(to, card.class.Card) && !required.includes(to)) {
required.push(to)
}
}
if (type._class === core.class.ArrOf) {
const of = (type as ArrOf<Doc>).of
processType(of, docs, required, m, h)
}
}

function processParams (
params: Record<string, any> | undefined,
masterTag: Ref<MasterTag>,
Expand All @@ -85,36 +124,7 @@ function processParams (
}
const attr = h.findAttribute(masterTag, key)
if (attr !== undefined) {
const type = attr.type
if (type._class === core.class.EnumOf) {
const enumRef = (type as EnumOf).of
const enumDoc = m.findObject(enumRef)
if (enumDoc !== undefined && !docs.some((d) => d._id === enumDoc._id)) {
docs.push(enumDoc)
}
}
if (type._class === core.class.RefTo) {
const to = (type as RefTo<Doc>).to
if (h.isDerived(to, card.class.Card) && !required.includes(to)) {
required.push(to)
}
}
if (type._class === core.class.ArrOf) {
const of = (type as ArrOf<Doc>).of
if (of._class === core.class.EnumOf) {
const enumRef = (of as EnumOf).of
const enumDoc = m.findObject(enumRef)
if (enumDoc !== undefined && !docs.some((d) => d._id === enumDoc._id)) {
docs.push(enumDoc)
}
}
if (of._class === core.class.RefTo) {
const to = (of as RefTo<Doc>).to
if (h.isDerived(to, card.class.Card) && !required.includes(to)) {
required.push(to)
}
}
}
processType(attr.type, docs, required, m, h)
}
}
}
Expand Down
18 changes: 14 additions & 4 deletions plugins/process-resources/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import core, {
type Doc,
type DocumentQuery,
type DocumentUpdate,
findProperty,
generateId,
matchQuery,
type Ref,
Expand Down Expand Up @@ -564,7 +565,7 @@ export async function getSubProcessesUserInput (
const mockExecution: Execution = {
_id: generateId(),
process: processId,
currentState: initTransition.to,
currentState: null as any,
card,
rollback: [],
context,
Expand Down Expand Up @@ -629,7 +630,7 @@ export async function createExecution (
const mockExecution: Execution = {
_id: executionId,
process: _id,
currentState: initTransition.to,
currentState: null as any,
card,
rollback: [],
context: getEmptyContext(),
Expand All @@ -647,7 +648,7 @@ export async function createExecution (
space,
{
process: _id,
currentState: initTransition.to,
currentState: null as any,
card,
rollback: [],
context: result?.context ?? getEmptyContext(),
Expand Down Expand Up @@ -710,7 +711,16 @@ export function todoTranstionCheck (
context: Record<string, any>
): boolean {
if (params._id === undefined) return false
return context.todo?._id === params._id
return context.todo?._id === params._id && checkResult(context, params.result)
}

function checkResult (context: Record<string, any>, results: Record<string, any> | undefined): boolean {
if (results === undefined) return true
for (const [key, value] of Object.entries(results)) {
const res = findProperty([context as any], key, value)
if (res.length === 0) return false
}
return true
}

export function timeTransitionCheck (
Expand Down
7 changes: 2 additions & 5 deletions server-plugins/process-resources/src/functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -408,9 +408,6 @@ export async function RunSubProcess (
const res: Tx[] = []
const resultContext: SuccessExecutionContext[] = []
const rollback: Tx[] = []
const initTransition = control.client
.getModel()
.findAllSync(process.class.Transition, { process: target._id, from: null })[0]
for (const _card of Array.isArray(card) ? card : [card]) {
if (target.parallelExecutionForbidden === true) {
const currentExecution = await control.client.findAll(process.class.Execution, {
Expand All @@ -432,7 +429,7 @@ export async function RunSubProcess (
execution.space,
{
process: processId,
currentState: initTransition.to,
currentState: null as any,
card: _card,
context,
status: ExecutionStatus.Active,
Expand Down Expand Up @@ -802,7 +799,7 @@ async function createExecution (
execution.space,
{
process: proc,
currentState: initTransition.to,
currentState: null as any,
card: _id,
rollback: [],
context: {},
Expand Down
25 changes: 22 additions & 3 deletions services/process/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,8 @@ async function findTransitions (
process.class.Transition,
{
process: execution.process,
trigger: { $in: record.event }
from: null,
trigger: process.trigger.OnExecutionStart
},
{ sort: { rank: SortingOrder.Ascending } }
)
Expand Down Expand Up @@ -346,6 +347,17 @@ async function execute (execution: Execution, transition: Transition, control: P
control.ctx.info('Execution already in progress', { execution: execution._id, transition: transition._id })
return
}

const fresh = await control.client.findOne(process.class.Execution, { _id: execution._id })
if (fresh === undefined || fresh.currentState !== execution.currentState) {
control.ctx.info('Skipping stale transition execution', {
execution: execution._id,
expectedState: execution.currentState,
actualState: fresh?.currentState
})
return
}

activeExecutions.add(execution._id)
try {
await executeTransition(execution, transition, control)
Expand Down Expand Up @@ -497,13 +509,20 @@ async function executeTransition (
const apply = client.txFactory.createTxApplyIf(
core.space.Tx,
`${execution._id}_${transition._id}`,
[],
[{ _class: process.class.Execution, query: { _id: execution._id, currentState: execution.currentState } }],
[],
res as TxCUD<Doc>[],
'process',
true
)
await client.tx(apply)
const result = (await client.tx(apply)) as any
if (result.success === false) {
control.ctx.info('Transition apply failed (likely already processed)', {
execution: execution._id,
transition: transition._id
})
break
}
await sendEvent(control, execution, transition, card, isDone)
TxProcessor.applyUpdate(execution, executionUpdate)
if (execution.parentId !== undefined) {
Expand Down
Loading