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

[RELEASE] Sassy Sycamore #14

Merged
merged 48 commits into from
Nov 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
39a4c6f
[TM-1249] Scaffolding for the research service.
roguenet Oct 24, 2024
797d479
[TM-1249] Include a note about running many services at once.
roguenet Oct 24, 2024
8be2754
[TM-1249] WIP polygon index endpoint definition.
roguenet Oct 25, 2024
39e91c3
[TM-1249] Add all filter options.
roguenet Oct 25, 2024
a95b94b
[TM-1249] Add pagination
roguenet Oct 25, 2024
f75bd50
[TM-1249] Document all the indicator types.
roguenet Oct 25, 2024
1e13db2
[TM-1249] Document update endpoint.
roguenet Oct 25, 2024
c54a308
Merge branch 'feat/TM-1354-delayed-jobs' into feat/TM-1249-research-s…
roguenet Oct 28, 2024
c6ac62c
Merge branch 'feat/TM-1354-delayed-jobs' into feat/TM-1249-research-s…
roguenet Oct 29, 2024
f838147
[TM-1249] DOCKER_HOST isn't needed anymore.
roguenet Oct 30, 2024
4b68376
Merge pull request #8 from wri/feat/TM-1249-research-service
roguenet Oct 30, 2024
9bb1a4d
[TM-1384] Include direct framework associations on users/me response.
roguenet Oct 31, 2024
d3a72b2
Merge pull request #10 from wri/feat/TM-1384-user-frameworks
roguenet Nov 1, 2024
7a88155
Merge pull request #11 from wri/main
roguenet Nov 1, 2024
176fecb
[TM-1451] Add npm scripts for typical start configurations.
roguenet Nov 5, 2024
66e7c54
[TM-1451] Match prettier config from the FE codebase.
roguenet Nov 6, 2024
de79a7c
[TM-1451] Improve validation
roguenet Nov 6, 2024
22a940a
[TM-1451] Build out database schema for site polygons and associated …
roguenet Nov 6, 2024
6c542a2
[TM-1451] Define indicator tables.
roguenet Nov 7, 2024
57396fe
[TM-1451] Work around a sequelize bug.
roguenet Nov 7, 2024
8778baa
[TM-1451] Make the JsonApiAttributes constructor more useful.
roguenet Nov 7, 2024
9ccfba4
[TM-1451] Add a note about the new package scripts for service subsets.
roguenet Nov 7, 2024
ee305a0
[TM-1451] Fix JsonApiAttributes improvement.
roguenet Nov 7, 2024
7ae8b0e
[TM-1451] Tighten up the JsonApiAttributes improvement.
roguenet Nov 7, 2024
9377bd2
[TM-1451] Implement site establishment tree species.
roguenet Nov 7, 2024
7c494d9
[TM-1451] Implement reporting periods.
roguenet Nov 7, 2024
f71127f
[TM-1451] Be resilient to a missing site.
roguenet Nov 7, 2024
45e298e
[TM-1451] Include polygon geometry.
roguenet Nov 8, 2024
dcee5d5
[TM-1451] Rename a few things for consistency and readability.
roguenet Nov 8, 2024
82a3ed4
[TM-1451] Set not required on all query params.
roguenet Nov 8, 2024
c2bbacf
[TM-1451] Implement API key authorization.
roguenet Nov 8, 2024
7c7bd50
[TM-1451] Implement site polygon policy.
roguenet Nov 8, 2024
7771803
[TM-1451] Be a little smarter about when we check for an api key.
roguenet Nov 8, 2024
d81afa1
[TM-1451] Include pagination details in API response.
roguenet Nov 8, 2024
21af11f
[TM-1451] Double the research service available CPU
roguenet Nov 8, 2024
3c118ae
[TM-1451] Bump it up a bit more.
roguenet Nov 8, 2024
cf0062d
[TM-1451] Unit test for service.getIndicators()
roguenet Nov 9, 2024
451c05a
[TM-1451] Unit test for getEstablishmentTreeSpecies
roguenet Nov 10, 2024
c74da72
[TM-1451] Unit test for getReportingPeriods.
roguenet Nov 10, 2024
69ac4fa
[TM-1451] Complete coverage for the service.
roguenet Nov 10, 2024
0a04907
[TM-1451] Controller error cases.
roguenet Nov 11, 2024
0a2867c
[TM-1451] Full coverage for the research service.
roguenet Nov 11, 2024
aa9a63e
[TM-1451] Coverage for the common lib.
roguenet Nov 11, 2024
35d9220
[TM-1451] Use run-many for lint / build
roguenet Nov 11, 2024
391cf2e
[TM-1448] Try triggering job service build from new action
roguenet Nov 12, 2024
d7a8f1a
[TM-1448] Update the README.
roguenet Nov 12, 2024
8cb5e77
Merge pull request #12 from wri/feat/TM-1451-get-site-polygons
roguenet Nov 13, 2024
ddbbfe6
Merge pull request #13 from wri/task/TM-1448-unified-deployment
roguenet Nov 13, 2024
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
3 changes: 1 addition & 2 deletions .env.local.sample
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
DOCKER_HOST=unix://$HOME/.docker/run/docker.sock

USER_SERVICE_PORT=4010
JOB_SERVICE_PORT=4020
RESEARCH_SERVICE_PORT=4030

DB_HOST=localhost
DB_PORT=3360
Expand Down
11 changes: 10 additions & 1 deletion .github/workflows/deploy-service.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,24 @@ name: Service Deploy
run-name: 'Service Deploy [service: ${{ inputs.service }}, env: ${{ inputs.env }}]'

on:
workflow_call:
inputs:
service:
required: true
type: string
env:
required: true
type: string
workflow_dispatch:
inputs:
service:
description: 'Service to deploy'
type: choice
required: true
options:
- user-service
- job-service
- research-service
- user-service
env:
description: 'Deployment target environment'
type: choice
Expand Down
43 changes: 43 additions & 0 deletions .github/workflows/deploy-services.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: Services Deploy (all)
run-name: 'Services Deploy (all) [env: ${{ inputs.env }}]'

on:
workflow_dispatch:
inputs:
env:
description: 'Deployment target environment'
type: choice
required: true
options:
- dev
- test
- staging
- prod

permissions:
id-token: write
contents: read

jobs:
job-service:
uses: ./.github/workflows/deploy-service.yml
with:
env: ${{ inputs.env }}
service: job-service
secrets: inherit

user-service:
uses: ./.github/workflows/deploy-service.yml
with:
env: ${{ inputs.env }}
service: user-service
secrets: inherit

research-service:
uses: ./.github/workflows/deploy-service.yml
with:
env: ${{ inputs.env }}
service: research-service
secrets: inherit


4 changes: 1 addition & 3 deletions .github/workflows/pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,7 @@ jobs:

- run: npm ci --legacy-peer-deps

- uses: nrwl/nx-set-shas@v4

- run: NX_CLOUD_DISTRIBUTED_EXECUTION=false npx nx affected -t lint build
- run: NX_CLOUD_DISTRIBUTED_EXECUTION=false npx nx run-many -t lint build

- uses: KengoTODA/actions-setup-docker-compose@v1
with:
Expand Down
10 changes: 9 additions & 1 deletion .prettierrc
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
{
"singleQuote": true
"arrowParens": "avoid",
"bracketSpacing": true,
"jsxBracketSameLine": false,
"printWidth": 120,
"semi": true,
"singleQuote": false,
"tabWidth": 2,
"trailingComma": "none",
"useTabs": false
}
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ Repository for the Microservices API backend of the TerraMatch service
* On Linux systems, the DOCKER_HOST value should be `unix:///var/run/docker.sock` instead of what's in the sample.
* To run all services:
* `nx run-many -t serve`
* The default maximum number of services it can run in parallel is 3. To run all of the services at once, use something like
`nx run-many --parallel=100 -t serve`, or you can cherry-pick which services you want to run instead with
`nx run-many -t serve --projects user-service jobs-service`.
* Some useful targets have been added to the root `package.json` for service sets. For instance, to run just the services needed
by the TM React front end, use `npm run fe-services`, or to run all use `npm run all`.
* In `.env` in your `wri-terramatch-website` repository, set your BE connection URL correctly by noting the config
in `.env.local.sample` for local development.
* The `NEXT_PUBLIC_API_BASE_URL` still points at the PHP BE directly
Expand All @@ -38,6 +43,8 @@ and main branches.
* In your local web repo, follow directions in `README.md` for setting up a new service.
* For deployment to AWS:
* Add a Dockerfile in the new app directory. A simple copy and modify from user-service is sufficient
* Add the new service name to the "service" workflow input options in `deploy-service.yml`
* Add a new job to `deploy-services.yml` to include the new services in the "all" service deployment workflow.
* In AWS:
* Add ECR repositories for each env (follow the naming scheme from user-service, e.g. `terramatch-microservices/foo-service-staging`, etc)
* Set the repo to Immutable
Expand Down
24 changes: 9 additions & 15 deletions apps/job-service/src/jobs/dto/delayed-job.dto.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,27 @@
import { JsonApiAttributes } from '@terramatch-microservices/common/dto/json-api-attributes';
import { JsonApiDto } from '@terramatch-microservices/common/decorators';
import { ApiProperty } from '@nestjs/swagger';
import { DelayedJob } from '@terramatch-microservices/database/entities';
import { JSON } from 'sequelize';
import { JsonApiAttributes } from "@terramatch-microservices/common/dto/json-api-attributes";
import { JsonApiDto } from "@terramatch-microservices/common/decorators";
import { ApiProperty } from "@nestjs/swagger";

const STATUSES = ['pending', 'failed', 'succeeded']
const STATUSES = ["pending", "failed", "succeeded"];
type Status = (typeof STATUSES)[number];

@JsonApiDto({ type: 'delayedJobs' })
@JsonApiDto({ type: "delayedJobs" })
export class DelayedJobDto extends JsonApiAttributes<DelayedJobDto> {
constructor(job: DelayedJob) {
const { status, statusCode, payload } = job;
super({ status, statusCode, payload });
}

@ApiProperty({
description: 'The current status of the job. If the status is not pending, the payload and statusCode will be provided.',
description:
"The current status of the job. If the status is not pending, the payload and statusCode will be provided.",
enum: STATUSES
})
status: Status;

@ApiProperty({
description: 'If the job is out of pending state, this is the HTTP status code for the completed process',
description: "If the job is out of pending state, this is the HTTP status code for the completed process",
nullable: true
})
statusCode: number | null;

@ApiProperty({
description: 'If the job is out of pending state, this is the JSON payload for the completed process',
description: "If the job is out of pending state, this is the JSON payload for the completed process",
nullable: true
})
payload: object | null;
Expand Down
28 changes: 13 additions & 15 deletions apps/job-service/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,31 @@
import { Logger, ValidationPipe } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { Logger, ValidationPipe } from "@nestjs/common";
import { NestFactory } from "@nestjs/core";

import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
import { TMLogService } from '@terramatch-microservices/common/util/tm-log.service';
import { AppModule } from './app.module';
import { DocumentBuilder, SwaggerModule } from "@nestjs/swagger";
import { TMLogService } from "@terramatch-microservices/common/util/tm-log.service";
import { AppModule } from "./app.module";

async function bootstrap() {
const app = await NestFactory.create(AppModule);

if (process.env.NODE_ENV === 'development') {
if (process.env.NODE_ENV === "development") {
// CORS is handled by the Api Gateway in AWS
app.enableCors();
}

const config = new DocumentBuilder()
.setTitle('TerraMatch Job Service')
.setDescription('APIs related to delayed jobs')
.setVersion('1.0')
.addTag('job-service')
.setTitle("TerraMatch Job Service")
.setDescription("APIs related to delayed jobs")
.setVersion("1.0")
.addTag("job-service")
.build();
const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup('job-service/documentation/api', app, document);
SwaggerModule.setup("job-service/documentation/api", app, document);

app.useGlobalPipes(new ValidationPipe());
app.useGlobalPipes(new ValidationPipe({ transform: true, transformOptions: { enableImplicitConversion: true } }));
app.useLogger(app.get(TMLogService));

const port = process.env.NODE_ENV === 'production'
? 80
: process.env.JOB_SERVICE_PORT ?? 4020;
const port = process.env.NODE_ENV === "production" ? 80 : process.env.JOB_SERVICE_PORT ?? 4020;
await app.listen(port);

Logger.log(`TerraMatch Job Service is running on: http://localhost:${port}`);
Expand Down
18 changes: 18 additions & 0 deletions apps/research-service-e2e/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"extends": ["../../.eslintrc.json"],
"ignorePatterns": ["!**/*"],
"overrides": [
{
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
"rules": {}
},
{
"files": ["*.ts", "*.tsx"],
"rules": {}
},
{
"files": ["*.js", "*.jsx"],
"rules": {}
}
]
}
19 changes: 19 additions & 0 deletions apps/research-service-e2e/jest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/* eslint-disable */
export default {
displayName: 'research-service-e2e',
preset: '../../jest.preset.js',
globalSetup: '<rootDir>/src/support/global-setup.ts',
globalTeardown: '<rootDir>/src/support/global-teardown.ts',
setupFiles: ['<rootDir>/src/support/test-setup.ts'],
testEnvironment: 'node',
transform: {
'^.+\\.[tj]s$': [
'ts-jest',
{
tsconfig: '<rootDir>/tsconfig.spec.json',
},
],
},
moduleFileExtensions: ['ts', 'js', 'html'],
coverageDirectory: '../../coverage/research-service-e2e',
};
17 changes: 17 additions & 0 deletions apps/research-service-e2e/project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "research-service-e2e",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"projectType": "application",
"implicitDependencies": ["research-service"],
"targets": {
"e2e": {
"executor": "@nx/jest:jest",
"outputs": ["{workspaceRoot}/coverage/{e2eProjectRoot}"],
"options": {
"jestConfig": "apps/research-service-e2e/jest.config.ts",
"passWithNoTests": true
},
"dependsOn": ["research-service:build"]
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import axios from 'axios';

describe('GET /api', () => {
it('should return a message', async () => {
const res = await axios.get(`/api`);

expect(res.status).toBe(200);
expect(res.data).toEqual({ message: 'Hello API' });
});
});
10 changes: 10 additions & 0 deletions apps/research-service-e2e/src/support/global-setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/* eslint-disable */
var __TEARDOWN_MESSAGE__: string;

module.exports = async function () {
// Start services that that the app needs to run (e.g. database, docker-compose, etc.).
console.log('\nSetting up...\n');

// Hint: Use `globalThis` to pass variables to global teardown.
globalThis.__TEARDOWN_MESSAGE__ = '\nTearing down...\n';
};
7 changes: 7 additions & 0 deletions apps/research-service-e2e/src/support/global-teardown.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/* eslint-disable */

module.exports = async function () {
// Put clean up logic here (e.g. stopping services, docker-compose, etc.).
// Hint: `globalThis` is shared between setup and teardown.
console.log(globalThis.__TEARDOWN_MESSAGE__);
};
10 changes: 10 additions & 0 deletions apps/research-service-e2e/src/support/test-setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/* eslint-disable */

import axios from 'axios';

module.exports = async function () {
// Configure axios for tests to use.
const host = process.env.HOST ?? 'localhost';
const port = process.env.PORT ?? '3000';
axios.defaults.baseURL = `http://${host}:${port}`;
};
13 changes: 13 additions & 0 deletions apps/research-service-e2e/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"extends": "../../tsconfig.base.json",
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.spec.json"
}
],
"compilerOptions": {
"esModuleInterop": true
}
}
9 changes: 9 additions & 0 deletions apps/research-service-e2e/tsconfig.spec.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"module": "commonjs",
"types": ["jest", "node"]
},
"include": ["jest.config.ts", "src/**/*.ts"]
}
18 changes: 18 additions & 0 deletions apps/research-service/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"extends": ["../../.eslintrc.json"],
"ignorePatterns": ["!**/*"],
"overrides": [
{
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
"rules": {}
},
{
"files": ["*.ts", "*.tsx"],
"rules": {}
},
{
"files": ["*.js", "*.jsx"],
"rules": {}
}
]
}
15 changes: 15 additions & 0 deletions apps/research-service/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
FROM terramatch-microservices-base:nx-base AS builder

ARG BUILD_FLAG
WORKDIR /app/builder
COPY . .
RUN npx nx build research-service ${BUILD_FLAG}

FROM terramatch-microservices-base:nx-base

ARG NODE_ENV
WORKDIR /app
COPY --from=builder /app/builder ./
ENV NODE_ENV=${NODE_ENV}

CMD ["node", "./dist/apps/research-service/main.js"]
12 changes: 12 additions & 0 deletions apps/research-service/jest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/* eslint-disable */
export default {
displayName: "research-service",
preset: "../../jest.preset.js",
testEnvironment: "node",
transform: {
"^.+\\.[tj]s$": ["ts-jest", { tsconfig: "<rootDir>/tsconfig.spec.json" }]
},
moduleFileExtensions: ["ts", "js", "html"],
coveragePathIgnorePatterns: [".dto.ts"],
coverageDirectory: "../../coverage/apps/research-service"
};
Loading
Loading