Merge staging-new and bump versions

Signed-off-by: Artem Savchenko <armisav@gmail.com>
This commit is contained in:
Artem Savchenko
2026-04-12 13:38:53 +07:00
1017 changed files with 27314 additions and 14207 deletions
+80 -78
View File
@@ -1,6 +1,6 @@
{
"name": "@hcengineering/pod-github",
"version": "0.7.382",
"version": "0.7.411",
"main": "lib/index.js",
"svelte": "src/index.ts",
"types": "types/index.d.ts",
@@ -31,7 +31,7 @@
},
"devDependencies": {
"cross-env": "~7.0.3",
"@hcengineering/platform-rig": "workspace:^0.7.382",
"@hcengineering/platform-rig": "workspace:^0.7.411",
"@types/node": "^22.18.1",
"@typescript-eslint/eslint-plugin": "^6.21.0",
"eslint-plugin-import": "^2.26.0",
@@ -60,38 +60,40 @@
"@types/jest": "^29.5.5"
},
"dependencies": {
"@hcengineering/core": "workspace:^0.7.382",
"@hcengineering/account": "workspace:^0.7.382",
"@hcengineering/account-client": "workspace:^0.7.382",
"@hcengineering/platform": "workspace:^0.7.382",
"@hcengineering/server-client": "workspace:^0.7.382",
"@hcengineering/server-token": "workspace:^0.7.382",
"@hcengineering/server-core": "workspace:^0.7.382",
"@hcengineering/server-storage": "workspace:^0.7.382",
"@hcengineering/mongo": "workspace:^0.7.382",
"@hcengineering/client": "workspace:^0.7.382",
"@hcengineering/chunter": "workspace:^0.7.382",
"@hcengineering/contact": "workspace:^0.7.382",
"@hcengineering/client-resources": "workspace:^0.7.382",
"@hcengineering/tracker": "workspace:^0.7.382",
"@hcengineering/query": "workspace:^0.7.382",
"@hcengineering/text": "workspace:^0.7.382",
"@hcengineering/text-markdown": "workspace:^0.7.382",
"@hcengineering/github": "workspace:^0.7.382",
"@hcengineering/attachment": "workspace:^0.7.382",
"@hcengineering/core": "workspace:^0.7.411",
"@hcengineering/account": "workspace:^0.7.411",
"@hcengineering/account-client": "workspace:^0.7.411",
"@hcengineering/platform": "workspace:^0.7.411",
"@hcengineering/server-client": "workspace:^0.7.411",
"@hcengineering/server-token": "workspace:^0.7.411",
"@hcengineering/server-core": "workspace:^0.7.411",
"@hcengineering/server-storage": "workspace:^0.7.411",
"@hcengineering/mongo": "workspace:^0.7.411",
"@hcengineering/client": "workspace:^0.7.411",
"@hcengineering/chunter": "workspace:^0.7.411",
"@hcengineering/contact": "workspace:^0.7.411",
"@hcengineering/client-resources": "workspace:^0.7.411",
"@hcengineering/tracker": "workspace:^0.7.411",
"@hcengineering/query": "workspace:^0.7.411",
"@hcengineering/text": "workspace:^0.7.411",
"@hcengineering/text-markdown": "workspace:^0.7.411",
"@hcengineering/github": "workspace:^0.7.411",
"@hcengineering/attachment": "workspace:^0.7.411",
"dotenv": "^16.4.5",
"octokit": "^3.1.1",
"@octokit/webhooks": "^12.0.3",
"@octokit/types": "^12.0.0",
"graphql": "^16.8.0",
"fast-equals": "^5.2.2",
"@hcengineering/minio": "workspace:^0.7.382",
"@hcengineering/minio": "workspace:^0.7.411",
"markdown-it": "^14.0.0",
"@tiptap/html": "^2.11.7",
"@tiptap/core": "^2.11.7",
"@tiptap/pm": "^2.11.7",
"@tiptap/starter-kit": "^2.11.7",
"@tiptap/extension-highlight": "^2.11.7",
"@tiptap/extension-subscript": "^2.11.7",
"@tiptap/extension-superscript": "^2.11.7",
"@tiptap/extension-placeholder": "^2.11.7",
"@tiptap/extension-mention": "^2.11.7",
"@tiptap/extension-typography": "^2.11.7",
@@ -110,66 +112,66 @@
"@tiptap/extension-table-row": "^2.11.7",
"@tiptap/extension-code": "^2.11.7",
"@tiptap/extension-bubble-menu": "^2.11.7",
"@hcengineering/task": "workspace:^0.7.382",
"@hcengineering/task": "workspace:^0.7.411",
"express": "^4.21.2",
"cors": "^2.8.5",
"body-parser": "^1.20.3",
"mongodb": "^6.16.0",
"@hcengineering/setting": "workspace:^0.7.382",
"@hcengineering/preference": "workspace:^0.7.382",
"@hcengineering/login": "workspace:^0.7.382",
"@hcengineering/view": "workspace:^0.7.382",
"@hcengineering/recruit": "workspace:^0.7.382",
"@hcengineering/activity": "workspace:^0.7.382",
"@hcengineering/telegram": "workspace:^0.7.382",
"@hcengineering/workbench": "workspace:^0.7.382",
"@hcengineering/lead": "workspace:^0.7.382",
"@hcengineering/gmail": "workspace:^0.7.382",
"@hcengineering/inventory": "workspace:^0.7.382",
"@hcengineering/templates": "workspace:^0.7.382",
"@hcengineering/notification": "workspace:^0.7.382",
"@hcengineering/tags": "workspace:^0.7.382",
"@hcengineering/calendar": "workspace:^0.7.382",
"@hcengineering/board": "workspace:^0.7.382",
"@hcengineering/hr": "workspace:^0.7.382",
"@hcengineering/bitrix": "workspace:^0.7.382",
"@hcengineering/request": "workspace:^0.7.382",
"@hcengineering/drive": "workspace:^0.7.382",
"@hcengineering/support": "workspace:^0.7.382",
"@hcengineering/collaborator-client": "workspace:^0.7.382",
"@hcengineering/document": "workspace:^0.7.382",
"@hcengineering/login-assets": "workspace:^0.7.382",
"@hcengineering/view-assets": "workspace:^0.7.382",
"@hcengineering/task-assets": "workspace:^0.7.382",
"@hcengineering/chunter-assets": "workspace:^0.7.382",
"@hcengineering/recruit-assets": "workspace:^0.7.382",
"@hcengineering/setting-assets": "workspace:^0.7.382",
"@hcengineering/contact-assets": "workspace:^0.7.382",
"@hcengineering/activity-assets": "workspace:^0.7.382",
"@hcengineering/telegram-assets": "workspace:^0.7.382",
"@hcengineering/workbench-assets": "workspace:^0.7.382",
"@hcengineering/attachment-assets": "workspace:^0.7.382",
"@hcengineering/lead-assets": "workspace:^0.7.382",
"@hcengineering/gmail-assets": "workspace:^0.7.382",
"@hcengineering/inventory-assets": "workspace:^0.7.382",
"@hcengineering/templates-assets": "workspace:^0.7.382",
"@hcengineering/notification-assets": "workspace:^0.7.382",
"@hcengineering/preference-assets": "workspace:^0.7.382",
"@hcengineering/tags-assets": "workspace:^0.7.382",
"@hcengineering/calendar-assets": "workspace:^0.7.382",
"@hcengineering/tracker-assets": "workspace:^0.7.382",
"@hcengineering/board-assets": "workspace:^0.7.382",
"@hcengineering/hr-assets": "workspace:^0.7.382",
"@hcengineering/bitrix-assets": "workspace:^0.7.382",
"@hcengineering/request-assets": "workspace:^0.7.382",
"@hcengineering/drive-assets": "workspace:^0.7.382",
"@hcengineering/support-assets": "workspace:^0.7.382",
"@hcengineering/github-assets": "workspace:^0.7.382",
"@hcengineering/document-assets": "workspace:^0.7.382",
"@hcengineering/time": "workspace:^0.7.382",
"@hcengineering/server-guest-resources": "workspace:^0.7.382",
"@hcengineering/analytics": "workspace:^0.7.382",
"@hcengineering/analytics-service": "workspace:^0.7.382",
"@hcengineering/setting": "workspace:^0.7.411",
"@hcengineering/preference": "workspace:^0.7.411",
"@hcengineering/login": "workspace:^0.7.411",
"@hcengineering/view": "workspace:^0.7.411",
"@hcengineering/recruit": "workspace:^0.7.411",
"@hcengineering/activity": "workspace:^0.7.411",
"@hcengineering/telegram": "workspace:^0.7.411",
"@hcengineering/workbench": "workspace:^0.7.411",
"@hcengineering/lead": "workspace:^0.7.411",
"@hcengineering/gmail": "workspace:^0.7.411",
"@hcengineering/inventory": "workspace:^0.7.411",
"@hcengineering/templates": "workspace:^0.7.411",
"@hcengineering/notification": "workspace:^0.7.411",
"@hcengineering/tags": "workspace:^0.7.411",
"@hcengineering/calendar": "workspace:^0.7.411",
"@hcengineering/board": "workspace:^0.7.411",
"@hcengineering/hr": "workspace:^0.7.411",
"@hcengineering/bitrix": "workspace:^0.7.411",
"@hcengineering/request": "workspace:^0.7.411",
"@hcengineering/drive": "workspace:^0.7.411",
"@hcengineering/support": "workspace:^0.7.411",
"@hcengineering/collaborator-client": "workspace:^0.7.411",
"@hcengineering/document": "workspace:^0.7.411",
"@hcengineering/login-assets": "workspace:^0.7.411",
"@hcengineering/view-assets": "workspace:^0.7.411",
"@hcengineering/task-assets": "workspace:^0.7.411",
"@hcengineering/chunter-assets": "workspace:^0.7.411",
"@hcengineering/recruit-assets": "workspace:^0.7.411",
"@hcengineering/setting-assets": "workspace:^0.7.411",
"@hcengineering/contact-assets": "workspace:^0.7.411",
"@hcengineering/activity-assets": "workspace:^0.7.411",
"@hcengineering/telegram-assets": "workspace:^0.7.411",
"@hcengineering/workbench-assets": "workspace:^0.7.411",
"@hcengineering/attachment-assets": "workspace:^0.7.411",
"@hcengineering/lead-assets": "workspace:^0.7.411",
"@hcengineering/gmail-assets": "workspace:^0.7.411",
"@hcengineering/inventory-assets": "workspace:^0.7.411",
"@hcengineering/templates-assets": "workspace:^0.7.411",
"@hcengineering/notification-assets": "workspace:^0.7.411",
"@hcengineering/preference-assets": "workspace:^0.7.411",
"@hcengineering/tags-assets": "workspace:^0.7.411",
"@hcengineering/calendar-assets": "workspace:^0.7.411",
"@hcengineering/tracker-assets": "workspace:^0.7.411",
"@hcengineering/board-assets": "workspace:^0.7.411",
"@hcengineering/hr-assets": "workspace:^0.7.411",
"@hcengineering/bitrix-assets": "workspace:^0.7.411",
"@hcengineering/request-assets": "workspace:^0.7.411",
"@hcengineering/drive-assets": "workspace:^0.7.411",
"@hcengineering/support-assets": "workspace:^0.7.411",
"@hcengineering/github-assets": "workspace:^0.7.411",
"@hcengineering/document-assets": "workspace:^0.7.411",
"@hcengineering/time": "workspace:^0.7.411",
"@hcengineering/server-guest-resources": "workspace:^0.7.411",
"@hcengineering/analytics": "workspace:^0.7.411",
"@hcengineering/analytics-service": "workspace:^0.7.411",
"ws": "^8.18.2"
}
}
@@ -0,0 +1,111 @@
import type { MeasureContext, WorkspaceInfoWithStatus, WorkspaceUuid } from '@hcengineering/core'
import { GithubWorkerWorkspaceState, getGithubWorkerState } from '../workspaceUtils'
const WS = '00000000-0000-0000-0000-000000000001' as WorkspaceUuid
const DAY_MS = 24 * 60 * 60 * 1000
function createMockCtx (): MeasureContext {
return {
warn: jest.fn(),
info: jest.fn(),
error: jest.fn()
} as unknown as MeasureContext
}
function baseInfo (overrides: Partial<WorkspaceInfoWithStatus> = {}): WorkspaceInfoWithStatus {
return {
uuid: WS,
name: 'ws',
url: 'ws-url',
createdOn: 0,
versionMajor: 0,
versionMinor: 7,
versionPatch: 0,
mode: 'active',
processingAttemps: 0,
...overrides
}
}
describe('getGithubWorkerState', () => {
it('returns Skip and warns when uuid is absent', () => {
const ctx = createMockCtx()
const checked = new Set<string>()
const info = { ...baseInfo(), uuid: undefined as unknown as WorkspaceUuid }
const state = getGithubWorkerState(ctx, WS, info, 3, checked)
expect(state).toBe(GithubWorkerWorkspaceState.Skip)
expect(ctx.warn).toHaveBeenCalled()
})
it('returns Skip when workspace is disabled', () => {
const ctx = createMockCtx()
const state = getGithubWorkerState(ctx, WS, baseInfo({ isDisabled: true, mode: 'active' }), 3, new Set())
expect(state).toBe(GithubWorkerWorkspaceState.Skip)
expect(ctx.info).toHaveBeenCalled()
})
it.each(['pending-deletion', 'deleting', 'deleted'] as const)('returns Skip for mode %s', (mode) => {
const ctx = createMockCtx()
expect(getGithubWorkerState(ctx, WS, baseInfo({ mode }), 3, new Set())).toBe(GithubWorkerWorkspaceState.Skip)
})
it.each(['archived', 'archiving-pending-backup', 'archiving-clean'] as const)(
'returns Skip for archiving %s',
(mode) => {
const ctx = createMockCtx()
expect(getGithubWorkerState(ctx, WS, baseInfo({ mode }), 3, new Set())).toBe(GithubWorkerWorkspaceState.Skip)
}
)
it.each(['upgrading', 'creating', 'pending-creation'] as const)('returns Wait for mode %s', (mode) => {
const ctx = createMockCtx()
expect(getGithubWorkerState(ctx, WS, baseInfo({ mode }), 3, new Set())).toBe(GithubWorkerWorkspaceState.Wait)
expect(ctx.warn).toHaveBeenCalled()
})
it('returns Wait when last visit exceeds inactivity interval', () => {
const ctx = createMockCtx()
const nowMs = 1_700_000_000_000
const lastVisit = nowMs - 4 * DAY_MS
expect(getGithubWorkerState(ctx, WS, baseInfo({ mode: 'active', lastVisit }), 3, new Set(), nowMs)).toBe(
GithubWorkerWorkspaceState.Wait
)
})
it('returns Connect when within inactivity interval', () => {
const ctx = createMockCtx()
const nowMs = 1_700_000_000_000
const lastVisit = nowMs - 2 * DAY_MS
expect(getGithubWorkerState(ctx, WS, baseInfo({ mode: 'active', lastVisit }), 3, new Set(), nowMs)).toBe(
GithubWorkerWorkspaceState.Connect
)
})
it('does not apply inactivity gate when interval is 0', () => {
const ctx = createMockCtx()
const nowMs = 1_700_000_000_000
const lastVisit = nowMs - 365 * DAY_MS
expect(getGithubWorkerState(ctx, WS, baseInfo({ mode: 'active', lastVisit }), 0, new Set(), nowMs)).toBe(
GithubWorkerWorkspaceState.Connect
)
})
it('missing lastVisit uses epoch → Wait inactive when interval > 0', () => {
const ctx = createMockCtx()
const nowMs = 1_700_000_000_000
expect(getGithubWorkerState(ctx, WS, baseInfo({ mode: 'active' }), 3, new Set(), nowMs)).toBe(
GithubWorkerWorkspaceState.Wait
)
})
it('logs inactive warning only once per workspace id', () => {
const ctx = createMockCtx()
const checked = new Set<string>()
const nowMs = 1_700_000_000_000
const info = baseInfo({ mode: 'active', lastVisit: nowMs - 10 * DAY_MS })
getGithubWorkerState(ctx, WS, info, 3, checked, nowMs)
getGithubWorkerState(ctx, WS, info, 3, checked, nowMs)
expect(ctx.warn).toHaveBeenCalledTimes(1)
})
})
+23 -33
View File
@@ -11,8 +11,6 @@ import core, {
Client,
ClientConnectEvent,
DocumentUpdate,
isActiveMode,
isDeletingMode,
MeasureContext,
PersonId,
RateLimiter,
@@ -46,6 +44,7 @@ import { type StorageAdapter } from '@hcengineering/server-core'
import { join } from 'path'
import { createPlatformClient } from './client'
import config from './config'
import { GithubWorkerWorkspaceState, getGithubWorkerState } from './workspaceUtils'
import { registerLoaders } from './loaders'
import { createNotification } from './notifications'
import { errorToObj } from './sync/utils'
@@ -68,6 +67,8 @@ interface IntegrationDataValue {
installationId: number | number[]
}
export { GithubWorkerWorkspaceState, getGithubWorkerState } from './workspaceUtils'
export class PlatformWorker {
private readonly clients = new Map<WorkspaceUuid, GithubWorker>()
@@ -948,32 +949,6 @@ export class PlatformWorker {
checkedWorkspaces = new Set<string>()
checkWorkspaceIsActive (workspace: WorkspaceUuid, workspaceInfo: WorkspaceInfoWithStatus): boolean {
if (workspaceInfo?.uuid === undefined) {
this.ctx.error('No workspace exists for workspaceId', { workspace })
return false
}
if (workspaceInfo?.isDisabled === true || isDeletingMode(workspaceInfo?.mode)) {
this.ctx.warn('Workspace is disabled', { workspace })
return false
}
if (!isActiveMode(workspaceInfo?.mode)) {
this.ctx.warn('Workspace is in maitenance, skipping for now.', { workspace, mode: workspaceInfo?.mode })
return true
}
const lastVisit = (Date.now() - (workspaceInfo.lastVisit ?? 0)) / (3600 * 24 * 1000) // In days
if (config.WorkspaceInactivityInterval > 0 && lastVisit > config.WorkspaceInactivityInterval) {
if (!this.checkedWorkspaces.has(workspace)) {
this.checkedWorkspaces.add(workspace)
this.ctx.warn('Workspace is inactive for too long, skipping for now.', { workspace })
}
return true
}
return false
}
checkReconnect (workspace: WorkspaceUuid, event: ClientConnectEvent, worker: GithubWorker): void {
if (event === ClientConnectEvent.Refresh || event === ClientConnectEvent.Upgraded) {
void this.clients
@@ -989,9 +964,15 @@ export class PlatformWorker {
getAccountClient(config.AccountsURL, token)
.getWorkspaceInfo()
.then((wsInfo) => {
const res = this.checkWorkspaceIsActive(workspace, wsInfo)
if (!res) {
this.ctx.warn('Workspace is inactive, removing from clients list.', { workspace })
const state = getGithubWorkerState(
this.ctx,
workspace,
wsInfo,
config.WorkspaceInactivityInterval,
this.checkedWorkspaces
)
if (state === GithubWorkerWorkspaceState.Skip) {
this.ctx.warn('Github worker state is skip, removing from clients list.', { workspace })
this.clients.delete(workspace)
void worker?.close().catch((err) => {
this.ctx.error('Failed to close workspace', { workspace, error: err })
@@ -1053,11 +1034,20 @@ export class PlatformWorker {
rechecks.push(workspace)
continue
}
const needRecheck = this.checkWorkspaceIsActive(workspace, returnedInfo)
if (needRecheck) {
const state = getGithubWorkerState(
this.ctx,
workspace,
returnedInfo,
config.WorkspaceInactivityInterval,
this.checkedWorkspaces
)
if (state === GithubWorkerWorkspaceState.Wait) {
rechecks.push(workspace)
continue
}
if (state === GithubWorkerWorkspaceState.Skip) {
continue
}
await rateLimiter.add(async () => {
try {
const branding = Object.values(this.brandingMap).find((b) => b.key === returnedInfo?.branding) ?? null
@@ -24,7 +24,15 @@ import {
githubExternalSyncVersion,
githubSyncVersion
} from '../types'
import { collectUpdate, deleteObjects, ensureGraphQLOctokit, errorToObj, getSince, isGHWriteAllowed } from './utils'
import {
collectUpdate,
deleteObjects,
ensureGraphQLOctokit,
ensureRESTOctokit,
errorToObj,
getSince,
isGHWriteAllowed
} from './utils'
import { Analytics } from '@hcengineering/analytics'
import { IssueComment, IssueCommentCreatedEvent, IssueCommentEvent } from '@octokit/webhooks-types'
@@ -353,7 +361,10 @@ export class CommentSyncManager implements DocSyncManager {
if (Object.keys(platformUpdate).length > 0) {
// Check and update body with external
const okit = (await this.provider.getOctokit(ctx, existing.modifiedBy)) ?? container.container.octokit
const okit = ensureRESTOctokit(
(await this.provider.getOctokit(ctx, existing.modifiedBy)) ?? container.container.octokit,
container
)
const mdown = await this.provider.getMarkdown(existingComment.message)
if (mdown.trim().length > 0) {
await okit.rest.issues.updateComment({
@@ -426,7 +437,10 @@ export class CommentSyncManager implements DocSyncManager {
return {}
}
const chatMessage = existing as ChatMessage
const okit = (await this.provider.getOctokit(ctx, chatMessage.modifiedBy)) ?? container.container.octokit
const okit = ensureRESTOctokit(
(await this.provider.getOctokit(ctx, chatMessage.modifiedBy)) ?? container.container.octokit,
container
)
// No external version yet, create it.
try {
@@ -29,7 +29,6 @@ import github, {
GithubIntegrationRepository,
GithubIssueStateReason,
GithubProject,
IntegrationRepositoryData,
GithubIssue as TGithubIssue
} from '@hcengineering/github'
import task, { TaskType, calcRank } from '@hcengineering/task'
@@ -523,9 +522,7 @@ export class IssueSyncManager extends IssueSyncManagerBase implements DocSyncMan
info.repository as Ref<GithubIntegrationRepository>,
container.project,
taskTypes[0]._id,
repo as GithubIntegrationRepository & {
repository: IntegrationRepositoryData
},
repo,
!markdownCompatible
)
},
@@ -50,6 +50,17 @@ export function ensureGraphQLOctokit (okit: Octokit | undefined, container: Cont
return container.container.octokit
}
/**
* Ensures an Octokit instance has the REST API available.
* If the provided okit doesn't have rest.issues, falls back to container.octokit which is guaranteed to have it.
*/
export function ensureRESTOctokit (okit: Octokit | undefined, container: ContainerFocus): Octokit {
if (okit !== undefined && typeof (okit as any).rest?.issues?.createComment === 'function') {
return okit
}
return container.container.octokit
}
/**
* @public
*/
+1
View File
@@ -87,6 +87,7 @@ import { ReviewThreadSyncManager } from './sync/reviewThreads'
import { ReviewSyncManager } from './sync/reviews'
import { appendGuestLinkToImage } from './sync/guest'
import { UsersSyncManager, fetchViewerDetails } from './sync/users'
import { appendGuestLinkToImage } from './sync/guest'
import { errorToObj } from './sync/utils'
import {
ContainerFocus,
@@ -0,0 +1,69 @@
//
// Copyright © 2026 Hardcore Engineering Inc.
//
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. You may
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
//
import {
isActiveMode,
isArchivingMode,
isDeletingMode,
type MeasureContext,
type WorkspaceInfoWithStatus,
type WorkspaceUuid
} from '@hcengineering/core'
/** Whether this pod should run a GithubWorker for the workspace. */
export enum GithubWorkerWorkspaceState {
/** Active workspace — connect and run worker. */
Connect = 'connect',
/** Not ready yet (upgrade, creation, …) or too inactive — recheck later; keep existing worker. */
Wait = 'wait',
/** Disabled, deleting, deleted, or archiving — do not run; drop worker if present. */
Skip = 'skip'
}
export function getGithubWorkerState (
ctx: MeasureContext,
workspace: WorkspaceUuid,
workspaceInfo: WorkspaceInfoWithStatus,
inactivityIntervalDays: number,
checkedWorkspaces: Set<string>,
nowMs: number = Date.now()
): GithubWorkerWorkspaceState {
if (workspaceInfo?.uuid === undefined) {
ctx.warn('No workspace exists for workspaceId', { workspace })
return GithubWorkerWorkspaceState.Skip
}
if (workspaceInfo.isDisabled === true || isDeletingMode(workspaceInfo.mode) || isArchivingMode(workspaceInfo.mode)) {
ctx.info('Workspace is disabled, deleting, or archived — skipping github worker', {
workspace,
mode: workspaceInfo.mode,
isDisabled: workspaceInfo.isDisabled
})
return GithubWorkerWorkspaceState.Skip
}
if (!isActiveMode(workspaceInfo.mode)) {
ctx.warn('Workspace is in maintenance, skipping for now.', { workspace, mode: workspaceInfo.mode })
return GithubWorkerWorkspaceState.Wait
}
const lastVisitDays = (nowMs - (workspaceInfo.lastVisit ?? 0)) / (3600 * 24 * 1000)
if (inactivityIntervalDays > 0 && lastVisitDays > inactivityIntervalDays) {
if (!checkedWorkspaces.has(workspace)) {
checkedWorkspaces.add(workspace)
ctx.warn('Workspace is inactive for too long, skipping for now.', { workspace })
}
return GithubWorkerWorkspaceState.Wait
}
return GithubWorkerWorkspaceState.Connect
}