Skip to content

Commit

Permalink
Implement node version
Browse files Browse the repository at this point in the history
  • Loading branch information
Siegrift committed Oct 20, 2023
1 parent 534639f commit 48f290f
Show file tree
Hide file tree
Showing 10 changed files with 55 additions and 9 deletions.
6 changes: 2 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,7 @@ FROM node:18-alpine as pusher
WORKDIR /app
ENV NODE_ENV=production
COPY --from=deployed-pusher /app/deployed-pusher .
# Enabling source maps adds small runtime overhead, but improves debugging experience and the performance is worth it.
ENTRYPOINT ["node", "--enable-source-maps", "dist/index.js"]
ENTRYPOINT ["node", "dist/src/index.js"]

# Create a separate stage for api package. We create a temporary stage for deployment and then copy the result into
# the final stage. Only the production dependencies and package implementation is part of this last stage.
Expand All @@ -51,5 +50,4 @@ FROM node:18-alpine as api
WORKDIR /app
ENV NODE_ENV=production
COPY --from=deployed-api /app/deployed-api .
# Enabling source maps adds small runtime overhead, but improves debugging experience and the performance is worth it.
ENTRYPOINT ["node", "--enable-source-maps", "dist/index.js"]
ENTRYPOINT ["node", "dist/index.js"]
2 changes: 1 addition & 1 deletion packages/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"eslint:fix": "eslint . --ext .js,.ts --fix",
"prettier:check": "prettier --check \"./**/*.{js,ts,md,json}\"",
"prettier:fix": "prettier --write \"./**/*.{js,ts,md,json}\"",
"start-prod": "node --enable-source-maps dist/index.js",
"start-prod": "node dist/index.js",
"test": "jest",
"tsc": "tsc --project ."
},
Expand Down
8 changes: 8 additions & 0 deletions packages/pusher/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,14 @@ Refer to the [OIS documentation](https://dapi-docs.api3.org/reference/ois/latest
Refer to Airnode's
[API credentials](https://dapi-docs.api3.org/reference/airnode/latest/deployment-files/config-json.html#apicredentials).

#### `nodeSettings`

Contains general deployment parameters of the pusher.

##### `nodeVersion`

The version of the pusher. The version specified in the config must match the version of the pusher at deployment time.

## Deployment

TODO: Write example how to deploy on AWS
Expand Down
5 changes: 4 additions & 1 deletion packages/pusher/config/pusher.example.json
Original file line number Diff line number Diff line change
Expand Up @@ -93,5 +93,8 @@
"securitySchemeName": "NodarySecurityScheme1ApiKey",
"securitySchemeValue": "${NODARY_API_KEY}"
}
]
],
"nodeSettings": {
"nodeVersion": "0.1.0"
}
}
4 changes: 2 additions & 2 deletions packages/pusher/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "pusher",
"version": "1.0.0",
"version": "0.1.0",
"engines": {
"node": "^18.14.0",
"pnpm": "^8.8.0"
Expand All @@ -15,7 +15,7 @@
"eslint:fix": "eslint . --ext .js,.ts --fix",
"prettier:check": "prettier --check \"./**/*.{js,ts,md,yml,json}\"",
"prettier:fix": "prettier --write \"./**/*.{js,ts,md,yml,json}\"",
"start-prod": "node --enable-source-maps dist/index.js",
"start-prod": "node dist/src/index.js",
"test": "jest",
"tsc": "tsc --project ."
},
Expand Down
7 changes: 6 additions & 1 deletion packages/pusher/src/validation/config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import fs, { readFileSync } from 'node:fs';
import { join } from 'node:path';
import { cwd } from 'node:process';

import { go } from '@api3/promise-utils';
import dotenv from 'dotenv';
Expand All @@ -8,7 +9,11 @@ import { configSchema } from './schema';
import { interpolateSecrets, parseSecrets } from './utils';

export const loadConfig = async () => {
const configPath = join(__dirname, '../../config');
// When pusher is built the "/dist" file contains "src" folder and "package.json" and the config is expected to be
// located next to the "/dist" folder. When run in development, the config is expected to be located next to the "src"
// folder (one less import level). We resolve the config by CWD as a workaround. Since the pusher is dockerized, this
// is hidden from the user.
const configPath = join(cwd(), './config');
const rawSecrets = dotenv.parse(readFileSync(join(configPath, 'secrets.env'), 'utf8'));

const goLoadConfig = await go(async () => {
Expand Down
20 changes: 20 additions & 0 deletions packages/pusher/src/validation/schema.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,26 @@ test('validates example config', async () => {
);
});

test('ensures nodeVersion matches pusher version', async () => {
const invalidConfig: Config = {
...config,
nodeSettings: {
...config.nodeSettings,
nodeVersion: '0.0.1',
},
};

await expect(configSchema.parseAsync(invalidConfig)).rejects.toStrictEqual(
new ZodError([
{
code: 'custom',
message: 'Invalid node version',
path: ['nodeSettings', 'nodeVersion'],
},
])
);
});

test('ensures signed API names are unique', () => {
expect(() =>
signedApisSchema.parse([
Expand Down
7 changes: 7 additions & 0 deletions packages/pusher/src/validation/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import { ethers } from 'ethers';
import { isNil, uniqWith, isEqual } from 'lodash';
import { z, type SuperRefinement } from 'zod';

import packageJson from '../../package.json';

export const limiterConfig = z.object({ minTime: z.number(), maxConcurrency: z.number() });

export const parameterSchema = z
Expand Down Expand Up @@ -242,6 +244,10 @@ export const oisesSchema = z.array(oisSchema);

export const apisCredentialsSchema = z.array(config.apiCredentialsSchema);

export const nodeSettingsSchema = z.object({
nodeVersion: z.string().refine((version) => version === packageJson.version, 'Invalid node version'),
});

export const configSchema = z
.object({
airnodeWalletMnemonic: z.string().refine((mnemonic) => ethers.utils.isValidMnemonic(mnemonic), 'Invalid mnemonic'),
Expand All @@ -250,6 +256,7 @@ export const configSchema = z
chains: z.any(),
endpoints: endpointsSchema,
gateways: z.any(),
nodeSettings: nodeSettingsSchema,
ois: oisesSchema,
rateLimiting: rateLimitingSchema,
signedApis: signedApisSchema,
Expand Down
4 changes: 4 additions & 0 deletions packages/pusher/test/fixtures.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { AxiosResponse } from 'axios';

import packageJson from '../package.json';
import type { SignedResponse, TemplateResponse } from '../src/sign-template-data';
import type { Config } from '../src/validation/schema';

Expand Down Expand Up @@ -99,6 +100,9 @@ export const config: Config = {
securitySchemeValue: 'invalid-api-key',
},
],
nodeSettings: {
nodeVersion: packageJson.version,
},
};

export const nodaryTemplateRequestResponseData = {
Expand Down
1 change: 1 addition & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"exactOptionalPropertyTypes": true,
"noUncheckedIndexedAccess": true,
"noImplicitReturns": true,
"resolveJsonModule": true,

// Disabled because they are covered by Eslint rules
"noUnusedLocals": false,
Expand Down

0 comments on commit 48f290f

Please sign in to comment.