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
7 changes: 3 additions & 4 deletions apps/auth-cron/src/job.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import path from 'node:path';
import type { BundleDatabase } from '@map-colonies/auth-bundler';
import { computeRevision, createBundle, getVersionCommand } from '@map-colonies/auth-bundler';
import { createBundle, getVersionCommand } from '@map-colonies/auth-bundler';
import type { Environments } from '@map-colonies/auth-core';
import { getS3Client } from './s3';
import { compareVersionsToBundle } from './util';
Expand Down Expand Up @@ -30,16 +30,15 @@ export function getJob(bundleDatabase: BundleDatabase, environment: Environments

logger.debug({ msg: 'creating new bundle as ', bundleEnv: environment });

const revision = computeRevision(latestVersions);
const bundleContent = await bundleDatabase.getBundleFromVersions(latestVersions);

await createBundle(bundleContent, workdir, 'bundle.tar.gz', undefined, revision);
await createBundle(bundleContent, workdir, 'bundle.tar.gz');

const hash = await getS3Client(environment).uploadFile(path.join(workdir, 'bundle.tar.gz'));

if (shouldSaveBundleToDb) {
logger.debug({ msg: 'saving bundle metadata to the database', bundleEnv: environment });
await bundleDatabase.saveBundle(latestVersions, hash, revision);
await bundleDatabase.saveBundle(latestVersions, hash);
}

logger.info({ msg: 'created new bundle successfully', bundleEnv: environment });
Expand Down
4 changes: 0 additions & 4 deletions apps/auth-cron/tests/job.spec.mts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ describe('job.ts', function () {
createdAt: new Date(),
hash: 'avi',
metadata: null,
revision: 'revision',
});
bundleDbMock.getLatestVersions.mockResolvedValue({
assets: [{ name: 'avi', version: 1 }],
Expand All @@ -118,7 +117,6 @@ describe('job.ts', function () {
opaVersion: '0.52.0',
createdAt: new Date(),
metadata: null,
revision: 'revision',
});
bundleDbMock.getLatestVersions.mockResolvedValue({
assets: [{ name: 'avi', version: 1 }],
Expand Down Expand Up @@ -148,7 +146,6 @@ describe('job.ts', function () {
opaVersion: '0.52.0',
createdAt: new Date(),
metadata: null,
revision: 'revision',
});
bundleDbMock.getLatestVersions.mockResolvedValue({
assets: [{ name: 'avi', version: 1 }],
Expand Down Expand Up @@ -177,7 +174,6 @@ describe('job.ts', function () {
opaVersion: '0.51.0',
createdAt: new Date(),
metadata: null,
revision: 'revision',
});
bundleDbMock.getLatestVersions.mockResolvedValue({
assets: [{ name: 'avi', version: 1 }],
Expand Down
3 changes: 1 addition & 2 deletions packages/auth-bundler/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,7 @@
"handlebars": "4.7.7",
"pg": "catalog:",
"drizzle-orm": "catalog:",
"@map-colonies/drizzle-utils": "catalog:",
"fast-json-stable-stringify": "^2.1.0"
"@map-colonies/drizzle-utils": "catalog:"
},
"devDependencies": {
"@map-colonies/config": "catalog:",
Expand Down
3 changes: 1 addition & 2 deletions packages/auth-bundler/src/db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ export class BundleDatabase {
* @param hash The md5 hash of the created bundle tarball
* @returns The ID of the created bundle
*/
public async saveBundle(versions: BundleContentVersions, hash: string, revision: string): Promise<number> {
public async saveBundle(versions: BundleContentVersions, hash: string): Promise<number> {
logger?.debug('saving bundle to db');
const bundle: NewBundle = {
environment: versions.environment,
Expand All @@ -101,7 +101,6 @@ export class BundleDatabase {
keyVersion: versions.keyVersion,
hash,
opaVersion: await getVersionCommand(),
revision,
};

const res = await this.drizzle.insert(bundleTable).values(bundle).returning();
Expand Down
11 changes: 2 additions & 9 deletions packages/auth-bundler/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ export { setLogger } from './logger';
export { BundleDatabase } from './db';
export * from './types';
export { getVersionCommand } from './opa';
export { computeRevision } from './util';

/**
* This function creates an opa bundle tarball from the given content
Expand All @@ -34,13 +33,7 @@ export { computeRevision } from './util';
* @throws {@link OpaBundleCreationError} If the OPA bundle creation process failed.

*/
export async function createBundle(
content: BundleContent,
workDir: string,
bundlePath: string,
tests?: TestOptions,
revision?: string
): Promise<void> {
export async function createBundle(content: BundleContent, workDir: string, bundlePath: string, tests?: TestOptions): Promise<void> {
logger?.info({ msg: 'creating bundle', workDir, bundlePath });
if (!existsSync(workDir)) {
logger?.debug('workdir does not exists');
Expand Down Expand Up @@ -73,7 +66,7 @@ export async function createBundle(
}
}

const [creationCompleted, creationErr] = await createBundleCommand(workDir, bundlePath, revision);
const [creationCompleted, creationErr] = await createBundleCommand(workDir, bundlePath);

if (!creationCompleted) {
logger?.debug('failed creating bundle');
Expand Down
10 changes: 3 additions & 7 deletions packages/auth-bundler/src/opa.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,17 +67,13 @@ export async function testCoverageCommand(path: string): Promise<number> {
* Runs the build command to create a bundle tarball from the given directory
* @param filesPath The path of the files from which to create the bundle
* @param bundlePath The path in which to save the created bundle. note: the path is relative to filesPath.
* @param revision The revision string to associate with the bundle
* @returns true if the command ran successfully, false and the returned error otherwise
* @see {@link https://www.openpolicyagent.org/docs/latest/cli/#opa-build}
* @ignore
*/
export async function createBundleCommand(filesPath: string, bundlePath: string, revision?: string): Promise<[true, undefined] | [false, string]> {
const args = ['build', '-o', bundlePath, '-b', '.'];
if (revision !== undefined) {
args.push('--revision', revision);
}
const res = await execa('opa', args, { cwd: filesPath, reject: false });
export async function createBundleCommand(filesPath: string, bundlePath: string): Promise<[true, undefined] | [false, string]> {
const res = await execa('opa', ['build', '-o', bundlePath, '-b', '.'], { cwd: filesPath, reject: false });

if (!res.failed) {
return [true, undefined];
}
Expand Down
19 changes: 0 additions & 19 deletions packages/auth-bundler/src/util.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
import { createHash } from 'node:crypto';
import stringify from 'fast-json-stable-stringify';
import type { BundleContentVersions } from './types';

const HASH_LENGTH = 12;

export function extractNameAndVersion<T extends { name: string; version: number }>(entities: T[]): [string[], number[]] {
const names: string[] = [];
const versions: number[] = [];
Expand All @@ -13,16 +7,3 @@ export function extractNameAndVersion<T extends { name: string; version: number
}
return [names, versions];
}

export function computeRevision(versions: BundleContentVersions): string {
const sortedAssets = [...versions.assets].sort((a, b) => a.name.localeCompare(b.name));
const sortedConnections = [...versions.connections].sort((a, b) => a.name.localeCompare(b.name));
const canonical = stringify({
environment: versions.environment,
assets: sortedAssets,
connections: sortedConnections,
keyVersion: versions.keyVersion,
});
const shortHash = createHash('sha256').update(canonical).digest('hex').substring(0, HASH_LENGTH);
return `${versions.environment}-${shortHash}`;
}
6 changes: 3 additions & 3 deletions packages/auth-bundler/tests/db.spec.mts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ describe('db.ts', function () {

const db = new BundleDatabase(pool);

const res = await db.saveBundle({ assets: [], connections: [], environment: Environment.PROD, keyVersion: 3 }, 'xdxd', 'lol');
const res = await db.saveBundle({ assets: [], connections: [], environment: Environment.PROD, keyVersion: 3 }, 'xdxd');

expect(res).toBeGreaterThan(0);

Expand Down Expand Up @@ -134,8 +134,8 @@ describe('db.ts', function () {

it('should return the latest bundle ordered by id for the given environment', async function () {
await drizzle.insert(bundleTable).values([
{ environment: Environment.STAGE, hash: 'hash1', opaVersion: '0.52.0', assets: [], connections: [], revision: 'revision1' },
{ environment: Environment.STAGE, hash: 'hash2', opaVersion: '0.52.0', assets: [], connections: [], revision: 'revision2' },
{ environment: Environment.STAGE, hash: 'hash1', opaVersion: '0.52.0', assets: [], connections: [] },
{ environment: Environment.STAGE, hash: 'hash2', opaVersion: '0.52.0', assets: [], connections: [] },
]);

const db = new BundleDatabase(pool);
Expand Down
18 changes: 0 additions & 18 deletions packages/auth-bundler/tests/index.spec.mts
Original file line number Diff line number Diff line change
Expand Up @@ -79,23 +79,5 @@ describe('index.ts', function () {

await expect(promise).rejects.toThrow(OpaBundleCreationError);
});

it('should pass the revision to createBundleCommand when provided', async function () {
const createBundleCommandSpy = vi.spyOn(opa, 'createBundleCommand').mockResolvedValue([true, undefined]);
vi.spyOn(opa, 'validateBinaryExistCommand').mockResolvedValue(true);

await createBundle(bundleContent, baseFolder, 'bundle.tar.gz', { enable: false }, 'np-abc123def456');

expect(createBundleCommandSpy).toHaveBeenCalledWith(baseFolder, 'bundle.tar.gz', 'np-abc123def456');
});

it('should pass undefined revision to createBundleCommand when not provided', async function () {
const createBundleCommandSpy = vi.spyOn(opa, 'createBundleCommand').mockResolvedValue([true, undefined]);
vi.spyOn(opa, 'validateBinaryExistCommand').mockResolvedValue(true);

await createBundle(bundleContent, baseFolder, 'bundle.tar.gz', { enable: false });

expect(createBundleCommandSpy).toHaveBeenCalledWith(baseFolder, 'bundle.tar.gz', undefined);
});
});
});
15 changes: 0 additions & 15 deletions packages/auth-bundler/tests/opa.spec.mts
Original file line number Diff line number Diff line change
Expand Up @@ -138,21 +138,6 @@ describe('opa.ts', function () {

expect(err).toBe('oh no');
});

it('should include the --revision flag when revision is provided', async function () {
const execaSpy = vi.spyOn(execa, 'execa').mockResolvedValue({ failed: false } as ExecaChildProcess);
await createBundleCommand(baseFolder, 'bundle.tar.gz', 'np-abc123def456');

expect(execaSpy).toHaveBeenCalledWith('opa', expect.arrayContaining(['--revision', 'np-abc123def456']), expect.anything());
});

it('should not include the --revision flag when revision is not provided', async function () {
const execaSpy = vi.spyOn(execa, 'execa').mockResolvedValue({ failed: false } as ExecaChildProcess);
await createBundleCommand(baseFolder, 'bundle.tar.gz');

const calledArgs = execaSpy.mock.calls[0]?.[1] as string[];
expect(calledArgs).not.toContain('--revision');
});
});

describe('#getVersionCommand', function () {
Expand Down
46 changes: 1 addition & 45 deletions packages/auth-bundler/tests/util.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { describe, expect, it } from 'vitest';
import { computeRevision, extractNameAndVersion } from '@src/util';
import { Environment } from '../../auth-core/dist/entities';
import { extractNameAndVersion } from '@src/util';

describe('util.ts', function () {
describe('#extractNameAndVersion', function () {
Expand All @@ -18,47 +17,4 @@ describe('util.ts', function () {
]);
});
});

describe('#computeRevision', function () {
const versions = {
environment: Environment.NP,
assets: [
{ name: 'b', version: 2 },
{ name: 'a', version: 1 },
],
connections: [{ name: 'c', version: 1 }],
keyVersion: 1,
};

it('should return a string prefixed with the environment followed by a 12-char hex hash', function () {
expect(computeRevision(versions)).toMatch(/^np-[a-f0-9]{12}$/);
});

it('should be reproducible for the same versions', function () {
expect(computeRevision(versions)).toBe(computeRevision(versions));
});

it('should produce different revisions for different content versions', function () {
expect(computeRevision(versions)).not.toBe(computeRevision({ ...versions, keyVersion: 2 }));
});

it('should produce the same revision regardless of asset order', function () {
const reordered = { ...versions, assets: [...versions.assets].reverse() };

expect(computeRevision(versions)).toBe(computeRevision(reordered));
});

it('should produce the same revision regardless of connection order', function () {
const moreConnections = {
...versions,
connections: [
{ name: 'z', version: 1 },
{ name: 'a', version: 1 },
],
};
const reordered = { ...moreConnections, connections: [...moreConnections.connections].reverse() };

expect(computeRevision(moreConnections)).toBe(computeRevision(reordered));
});
});
});
2 changes: 1 addition & 1 deletion packages/auth-core/drizzle.config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { ConnectionConfig } from 'pg';
import { defineConfig } from 'drizzle-kit';
import { getConfig, initConfig } from './src/config.js';

import { createConnectionOptions } from '@map-colonies/drizzle-utils';
import { createConnectionOptions } from './src/db/utils/createConnection.js';
import { ConnectionOptions } from 'node:tls';

await initConfig();
Expand Down
1 change: 0 additions & 1 deletion packages/auth-core/src/entities/bundle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ export const bundleTable = authManagerSchema.table('bundle', {
createdAt: createdAtColumn,
keyVersion: integer(),
opaVersion: text().notNull(),
revision: text().notNull(),
});

export type Bundle = typeof bundleTable.$inferSelect;
Expand Down

This file was deleted.

Loading
Loading