Skip to content

Commit e4fc820

Browse files
authored
Merge pull request #503 from NillionNetwork/feat/validate-semver
feat: allow enforcing semver artifact versions in api
2 parents 996cc57 + 0a74338 commit e4fc820

File tree

3 files changed

+26
-3
lines changed

3 files changed

+26
-3
lines changed

nilcc-api/src/artifact/artifact.service.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1+
import semver from "semver";
12
import type { QueryRunner, Repository } from "typeorm";
2-
import { EntityAlreadyExists, isUniqueConstraint } from "#/common/errors";
3+
import {
4+
ArtifactVersionNotSemver,
5+
EntityAlreadyExists,
6+
isUniqueConstraint,
7+
} from "#/common/errors";
38
import type { AppBindings } from "#/env";
49
import type { EnableArtifactRequest } from "./artifact.dto";
510
import { ArtifactEntity } from "./artifact.entity";
@@ -19,6 +24,12 @@ export class ArtifactService {
1924
bindings: AppBindings,
2025
request: EnableArtifactRequest,
2126
): Promise<ArtifactEntity> {
27+
if (
28+
bindings.config.requireArtifactsSemver &&
29+
!semver.valid(request.version)
30+
) {
31+
throw new ArtifactVersionNotSemver();
32+
}
2233
const repository = this.getRepository(bindings);
2334
const metadata = await bindings.services.artifactsClient.fetchMetadata(
2435
request.version,

nilcc-api/src/common/errors.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,16 @@ export class MetalInstanceManagingWorkloads extends AppError {
3232

3333
export class ArtifactVersionDoesNotExist extends AppError {
3434
override kind = "ARTIFACT_VERSION_DOES_NOT_EXIST";
35+
override statusCode: ContentfulStatusCode = StatusCodes.BAD_REQUEST;
3536
override description = "Artifact version does not exist";
3637
}
3738

39+
export class ArtifactVersionNotSemver extends AppError {
40+
override kind = "ARTIFACT_VERSION_NOT_SEMVER";
41+
override statusCode: ContentfulStatusCode = StatusCodes.BAD_REQUEST;
42+
override description = "Artifact version does not follow semver format";
43+
}
44+
3845
export class InvalidDockerCompose extends AppError {
3946
override kind = "INVALID_DOCKER_COMPOSE";
4047
override statusCode: ContentfulStatusCode = StatusCodes.BAD_REQUEST;

nilcc-api/src/env.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,9 @@ export const LOG_LEVELS = ["debug", "info", "warn", "error"] as const;
2727

2828
export const FeatureFlag = {
2929
OPENAPI_SPEC: "openapi",
30-
PROMETHEUS_METRICS: "prometheus-metrics",
3130
LOCALSTACK: "localstack",
3231
PRETTY_LOGS: "pretty-logs",
3332
HTTP_ERROR_STACKTRACE: "http-error-stacktrace",
34-
AUTO_MIGRATIONS: "auto-migrations",
3533
} as const;
3634

3735
export type FeatureFlag = (typeof FeatureFlag)[keyof typeof FeatureFlag];
@@ -106,6 +104,7 @@ export const EnvVarsSchema = z.object({
106104
metalInstancesEndpointPort: z.number().default(443),
107105
metalInstancesIdleThresholdSeconds: z.number().default(120),
108106
artifactsBaseUrl: z.string(),
107+
requireArtifactsSemver: z.boolean(),
109108
});
110109

111110
export type EnvVars = z.infer<typeof EnvVarsSchema>;
@@ -129,6 +128,7 @@ declare global {
129128
APP_METAL_INSTANCES_ENDPOINT_PORT?: string;
130129
APP_METAL_INSTANCES_IDLE_THRESHOLD_SECONDS?: string;
131130
APP_ARTIFACTS_BASE_URL: string;
131+
APP_REQUIRE_ARTIFACTS_SEMVER?: string;
132132
}
133133
}
134134
}
@@ -217,6 +217,8 @@ async function buildServices(
217217
export function parseConfigFromEnv(overrides: Partial<EnvVars>): EnvVars {
218218
const tryNumber = (n: string | undefined) =>
219219
n !== undefined ? Number(n) : undefined;
220+
const tryBoolean = (n: string | undefined) =>
221+
n !== undefined ? Boolean(n) : false;
220222
const config = EnvVarsSchema.parse({
221223
dbUri: process.env.APP_DB_URI,
222224
enabledFeatures: process.env.APP_ENABLED_FEATURES,
@@ -238,6 +240,9 @@ export function parseConfigFromEnv(overrides: Partial<EnvVars>): EnvVars {
238240
process.env.APP_METAL_INSTANCES_IDLE_THRESHOLD_SECONDS,
239241
),
240242
artifactsBaseUrl: process.env.APP_ARTIFACTS_BASE_URL,
243+
requireArtifactsSemver: tryBoolean(
244+
process.env.APP_REQUIRE_ARTIFACTS_SEMVER,
245+
),
241246
});
242247

243248
return {

0 commit comments

Comments
 (0)