Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add stage to Signed API #156

Merged
merged 3 commits into from
Dec 6, 2023
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
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,4 @@ RUN addgroup -S deployed-api && \
USER deployed-api

COPY --chown=deployed-api:deployed-api --from=deployed-api /app/deployed-api .
ENTRYPOINT ["node", "dist/index.js"]
ENTRYPOINT ["node", "dist/src/index.js"]
3 changes: 1 addition & 2 deletions packages/airnode-feed/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -347,8 +347,7 @@ lowercase alphanumeric characters and hyphens.
## Versioning and release

Airnode feed uses [semantic versioning](https://semver.org/). The version is specified in the `package.json` file. The
package is not published to NPM, but instead dockerized and published to Docker Hub. The image is called
[api3/airnode-feed](https://hub.docker.com/r/api3/airnode-feed).
package is not published to NPM, but instead dockerized and published to Docker Hub.

To release a new version:

Expand Down
8 changes: 4 additions & 4 deletions packages/airnode-feed/src/validation/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ import dotenv from 'dotenv';
import { configSchema } from './schema';
import { interpolateSecrets, parseSecrets } from './utils';

// When Airnode feed 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 Airnode feed is dockerized,
// this is hidden from the user.
// When Airnode feed 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 Airnode feed is
// dockerized, this is hidden from the user.
const getConfigPath = () => join(cwd(), './config');

export const loadRawConfig = () => JSON.parse(fs.readFileSync(join(getConfigPath(), 'airnode-feed.json'), 'utf8'));
Expand Down
13 changes: 11 additions & 2 deletions packages/api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,16 @@ or
"allowedAirnodes": ["0xB47E3D8734780430ee6EfeF3c5407090601Dcd15"]
```

##### `stage`

An identifier of the deployment stage. This is used to distinguish between different deployments of Signed API, for
example `dev`, `staging` or `production`. The stage value can have 256 characters at maximum and can only include
lowercase alphanumeric characters and hyphens.

##### `version`

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

## API

The API provides the following endpoints:
Expand All @@ -224,8 +234,7 @@ The API provides the following endpoints:
## Versioning and release

Signed API uses [semantic versioning](https://semver.org/). The version is specified in the `package.json` file. The
package is not published to NPM, but instead dockerized and published to Docker Hub. The image is called
[api3/signed-api](https://hub.docker.com/r/api3/signed-api).
package is not published to NPM, but instead dockerized and published to Docker Hub.

To release a new version:

Expand Down
4 changes: 3 additions & 1 deletion packages/api/config/signed-api.example.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,7 @@
"delaySeconds": 15
}
],
"allowedAirnodes": ["0xbF3137b0a7574563a23a8fC8badC6537F98197CC"]
"allowedAirnodes": ["0xbF3137b0a7574563a23a8fC8badC6537F98197CC"],
"stage": "local",
"version": "0.1.0"
}
2 changes: 1 addition & 1 deletion packages/api/deployment/cloudformation-template.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
"EntryPoint": [
"/bin/sh",
"-c",
"wget -O - <SIGNED_API_CONFIGURATION_URL> >> ./config/signed-api.json && node dist/index.js"
"wget -O - <SIGNED_API_CONFIGURATION_URL> >> ./config/signed-api.json && node dist/src/index.js"
],
"PortMappings": [
{
Expand Down
2 changes: 1 addition & 1 deletion packages/api/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "api",
"version": "1.0.0",
"version": "0.1.0",
"engines": {
"node": "^18.18.2",
"pnpm": "^8.11.0"
Expand Down
12 changes: 11 additions & 1 deletion packages/api/src/config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { readFileSync } from 'node:fs';
import { join } from 'node:path';
import { cwd } from 'node:process';

import { go } from '@api3/promise-utils';
import { S3 } from '@aws-sdk/client-s3';
Expand All @@ -22,12 +23,21 @@ export const fetchAndCacheConfig = async (): Promise<Config> => {
return config;
};

// When Signed API 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 Signed API is dockerized,
// this is hidden from the user.
const getConfigPath = () => join(cwd(), './config');

export const loadConfigFromFilesystem = () =>
JSON.parse(readFileSync(join(getConfigPath(), 'signed-api.json'), 'utf8'));

const fetchConfig = async (): Promise<any> => {
const env = loadEnv();
const source = env.CONFIG_SOURCE;
switch (source) {
case 'local': {
return JSON.parse(readFileSync(join(__dirname, '../config/signed-api.json'), 'utf8'));
return loadConfigFromFilesystem();
}
case 'aws-s3': {
return fetchConfigFromS3();
Expand Down
6 changes: 6 additions & 0 deletions packages/api/src/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { type LogFormat, logFormatOptions, logLevelOptions, type LogLevel } from
import { uniqBy } from 'lodash';
import { z } from 'zod';

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

export const evmAddressSchema = z.string().regex(/^0x[\dA-Fa-f]{40}$/, 'Must be a valid EVM address');

export const evmIdSchema = z.string().regex(/^0x[\dA-Fa-f]{64}$/, 'Must be a valid EVM ID');
Expand Down Expand Up @@ -35,6 +37,10 @@ export const configSchema = z.strictObject({
endpoints: endpointsSchema,
cache: cacheSchema.optional(),
allowedAirnodes: allowedAirnodesSchema,
stage: z
.string()
.regex(/^[\da-z-]{1,256}$/, 'Only lowercase letters, numbers and hyphens are allowed (max 256 characters)'),
version: z.string().refine((version) => version === packageJson.version, 'Invalid Signed API version'),
});

export type Config = z.infer<typeof configSchema>;
Expand Down
4 changes: 3 additions & 1 deletion packages/e2e/src/signed-api/signed-api.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,7 @@
"delaySeconds": 10
}
],
"allowedAirnodes": ["0xbF3137b0a7574563a23a8fC8badC6537F98197CC"]
"allowedAirnodes": ["0xbF3137b0a7574563a23a8fC8badC6537F98197CC"],
"stage": "e2e-test",
"version": "0.1.0"
}