Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
5 changes: 5 additions & 0 deletions workers/main/.env.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
REDMINE_DB_HOST=localhost
REDMINE_DB_USER=testuser
REDMINE_DB_PASSWORD=testpassword
REDMINE_DB_NAME=testdb
DEBUG=
913 changes: 385 additions & 528 deletions workers/main/package-lock.json

Large diffs are not rendered by default.

9 changes: 6 additions & 3 deletions workers/main/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,30 @@
"devDependencies": {
"@eslint/js": "9.27.0",
"@types/node": "22.15.21",
"@temporalio/testing": "1.11.8",
"@vitest/coverage-v8": "3.1.3",
"c8": "10.1.3",
"dotenv": "16.5.0",
"eslint": "9.27.0",
"eslint-config-prettier": "10.1.5",
"eslint-import-resolver-typescript": "4.3.5",
"eslint-plugin-import": "2.31.0",
"eslint-plugin-prettier": "5.4.0",
"eslint-plugin-simple-import-sort": "12.1.1",
"prettier": "3.5.3",
"source-map-support": "^0.5.21",
"ts-node": "10.9.1",
"typescript": "5.8.3",
"typescript-eslint": "8.32.1",
"uuid": "11.1.0",
"vite": "6.3.5",
"vitest": "3.1.3",
"source-map-support": "^0.5.21"
"vitest": "3.1.3"
},
"dependencies": {
"@temporalio/activity": "1.11.8",
"@temporalio/client": "1.11.8",
"@temporalio/worker": "1.11.8",
"@temporalio/workflow": "1.11.8",
"@temporalio/activity": "1.11.8",
"mysql2": "3.14.1",
"zod": "3.25.17"
}
Expand Down
58 changes: 58 additions & 0 deletions workers/main/src/__tests__/utils.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';

vi.mock('../common/../configs', () => ({
validationResult: { success: true },
}));

import * as configs from '../common/../configs';
import { validateEnv } from '../common/utils';

type ValidationResult = {
success: boolean;
error?: { issues: { path: unknown[]; message: string }[] };
};
function setValidationResult(result: ValidationResult) {
(configs as { validationResult: ValidationResult }).validationResult = result;
}

describe('validateEnv', () => {
let errorSpy: ReturnType<typeof vi.spyOn>;
let exitSpy: ReturnType<typeof vi.spyOn>;

beforeEach(() => {
errorSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
exitSpy = vi.spyOn(process, 'exit').mockImplementation(() => {
throw new Error('exit');
}) as unknown as ReturnType<typeof vi.spyOn>;
});

afterEach(() => {
errorSpy.mockRestore();
exitSpy.mockRestore();
});

it('does nothing if validationResult.success is true', () => {
setValidationResult({ success: true });
expect(() => validateEnv()).not.toThrow();
expect(errorSpy).not.toHaveBeenCalled();
expect(exitSpy).not.toHaveBeenCalled();
});

it('logs error and exits if validationResult.success is false', () => {
setValidationResult({
success: false,
error: {
issues: [
{ path: ['FOO'], message: 'is required' },
{ path: [], message: 'unknown' },
],
},
});
expect(() => validateEnv()).toThrow('exit');
expect(errorSpy).toHaveBeenCalledWith(
'Missing or invalid environment variable: FOO (is required)\n' +
'Missing or invalid environment variable: (unknown variable) (unknown)',
);
expect(exitSpy).toHaveBeenCalledWith(1);
});
});
15 changes: 15 additions & 0 deletions workers/main/src/common/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { validationResult } from '../configs';

export function validateEnv() {
if (!validationResult.success) {
const errorMessage = validationResult.error.issues
.map(
({ path, message }) =>
`Missing or invalid environment variable: ${path.join('.') || '(unknown variable)'} (${message})`,
)
.join('\n');

console.error(errorMessage);
process.exit(1);
}
}
Comment thread
anatolyshipitz marked this conversation as resolved.
2 changes: 2 additions & 0 deletions workers/main/src/configs/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { redmineDatabaseSchema } from './redmineDatabase';
import { temporalSchema } from './temporal';
import { workerSchema } from './worker';

export const validationResult = temporalSchema
.merge(workerSchema)
.merge(redmineDatabaseSchema)
.safeParse(process.env);
15 changes: 15 additions & 0 deletions workers/main/src/configs/redmineDatabase.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { z } from 'zod';

export const redmineDatabaseConfig = {
host: process.env.REDMINE_DB_HOST,
user: process.env.REDMINE_DB_USER,
password: process.env.REDMINE_DB_PASSWORD,
database: process.env.REDMINE_DB_NAME,
};
Comment thread
anatolyshipitz marked this conversation as resolved.

export const redmineDatabaseSchema = z.object({
REDMINE_DB_HOST: z.string(),
REDMINE_DB_USER: z.string(),
REDMINE_DB_PASSWORD: z.string(),
REDMINE_DB_NAME: z.string(),
});
3 changes: 0 additions & 3 deletions workers/main/src/configs/worker.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
import { WorkerOptions } from '@temporalio/worker';
import path from 'path';
import { z } from 'zod';

export const workerConfig: WorkerOptions = {
taskQueue: 'main-queue',
workflowsPath:
process.env.WORKFLOWS_PATH || path.join(__dirname, '../workflows'),
};

export const workerSchema = z.object({
Expand Down
9 changes: 3 additions & 6 deletions workers/main/vitest.config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import dotenv from 'dotenv';
import { defineConfig } from 'vitest/config';

dotenv.config({ path: '.env.test' });

export default defineConfig({
test: {
globals: true,
Expand All @@ -11,12 +14,6 @@ export default defineConfig({
all: true,
include: ['src/**/*.ts'],
exclude: ['src/__tests__/**', 'src/dist/**'],
thresholds: {
statements: 70,
branches: 70,
functions: 70,
lines: 70,
},
},
},
});