mirror of
https://github.com/standardnotes/server
synced 2026-04-25 09:01:21 -04:00
Compare commits
67 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0dbc929c8e | |||
| 0c5305acf6 | |||
| 34139efafb | |||
| eb53c3896f | |||
| 2af4c6fb55 | |||
| d66f784538 | |||
| f127241857 | |||
| 5b0d9dd394 | |||
| ee29d18484 | |||
| 2255f856f9 | |||
| f2415527f0 | |||
| 59eb70ce62 | |||
| 1d18725bc5 | |||
| d4af1d743e | |||
| 9d1a357b5b | |||
| 5160cc36dd | |||
| f05e1dbdf0 | |||
| 7b797f0cba | |||
| f823826044 | |||
| 9589403c9d | |||
| 2757b18e17 | |||
| 6e8481bb2f | |||
| 72760d942e | |||
| 88d4d211b8 | |||
| abfa373083 | |||
| 23b05caea2 | |||
| d3f4027c3c | |||
| f8433c106f | |||
| 39d7a09cdf | |||
| 771a555b4f | |||
| 4ea7309001 | |||
| 126e6a3c2f | |||
| 53be3a2f83 | |||
| 655409d078 | |||
| 43f68900ff | |||
| 01597a2518 | |||
| fd7a38ead1 | |||
| f777e1f168 | |||
| 23ced9427f | |||
| c9fd718af4 | |||
| 072c2770b1 | |||
| 54e4775ca3 | |||
| d4849cb4c2 | |||
| 38cd19281f | |||
| 1eaaa31c4e | |||
| 256f070700 | |||
| 400f3593b2 | |||
| 475a9559cf | |||
| cbf7d8c7a4 | |||
| 2d7cee9d14 | |||
| ef05946832 | |||
| 24a9078b22 | |||
| c5d19ad0b2 | |||
| f004653286 | |||
| 4850807ac1 | |||
| 526a21dde3 | |||
| 9a3ab6d1c1 | |||
| 6bde0ec7ab | |||
| 5b1d755670 | |||
| e58d2ec233 | |||
| 6742655a04 | |||
| 02b36a1c11 | |||
| 363c236d3e | |||
| c49634ae18 | |||
| 8fd06c4c8c | |||
| 935661ed35 | |||
| 6764250f6d |
@@ -1,161 +0,0 @@
|
||||
name: Api Gateway
|
||||
|
||||
concurrency:
|
||||
group: api_gateway
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '*standardnotes/api-gateway*'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
node-version-file: '.nvmrc'
|
||||
|
||||
- name: Build
|
||||
run: yarn build
|
||||
|
||||
- name: Lint
|
||||
run: yarn lint:api-gateway
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Publish Docker image for E2E testing
|
||||
run: |
|
||||
yarn docker build @standardnotes/api-gateway -t standardnotes/api-gateway:${{ github.sha }}
|
||||
docker push standardnotes/api-gateway:${{ github.sha }}
|
||||
|
||||
- name: Run E2E test suite
|
||||
uses: convictional/trigger-workflow-and-wait@v1.6.3
|
||||
with:
|
||||
owner: standardnotes
|
||||
repo: e2e
|
||||
github_token: ${{ secrets.CI_PAT_TOKEN }}
|
||||
workflow_file_name: testing-with-stable-client.yml
|
||||
wait_interval: 30
|
||||
client_payload: '{"api_gateway_image_tag": "${{ github.sha }}"}'
|
||||
propagate_failure: true
|
||||
trigger_workflow: true
|
||||
wait_workflow: true
|
||||
|
||||
publish-aws-ecr:
|
||||
needs: test
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
node-version-file: '.nvmrc'
|
||||
- name: Build locally
|
||||
run: yarn build
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-east-1
|
||||
- name: Login to Amazon ECR
|
||||
id: login-ecr
|
||||
uses: aws-actions/amazon-ecr-login@v1
|
||||
- name: Build, tag, and push image to Amazon ECR
|
||||
id: build-image
|
||||
env:
|
||||
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
|
||||
ECR_REPOSITORY: api-gateway
|
||||
IMAGE_TAG: ${{ github.sha }}
|
||||
run: |
|
||||
yarn docker build @standardnotes/api-gateway -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
|
||||
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
|
||||
docker tag $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG $ECR_REGISTRY/$ECR_REPOSITORY:latest
|
||||
docker push $ECR_REGISTRY/$ECR_REPOSITORY:latest
|
||||
|
||||
publish-docker-hub:
|
||||
needs: test
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
node-version-file: '.nvmrc'
|
||||
- name: Build locally
|
||||
run: yarn build
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
- name: Publish Docker image as stable
|
||||
run: |
|
||||
yarn docker build @standardnotes/api-gateway -t standardnotes/api-gateway:latest
|
||||
docker push standardnotes/api-gateway:latest
|
||||
|
||||
deploy-web:
|
||||
needs: publish-aws-ecr
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-east-1
|
||||
- name: Download task definition
|
||||
run: |
|
||||
aws ecs describe-task-definition --task-definition api-gateway-prod --query taskDefinition > task-definition.json
|
||||
- name: Fill in the new version in the Amazon ECS task definition
|
||||
run: |
|
||||
jq '(.containerDefinitions[] | select(.name=="api-gateway-prod") | .environment[] | select(.name=="VERSION")).value = "${{ github.sha }}"' task-definition.json > tmp.json && mv tmp.json task-definition.json
|
||||
- name: Fill in the new image ID in the Amazon ECS task definition
|
||||
id: task-def-prod
|
||||
uses: aws-actions/amazon-ecs-render-task-definition@v1
|
||||
with:
|
||||
task-definition: task-definition.json
|
||||
container-name: api-gateway-prod
|
||||
image: ${{ secrets.AWS_ECR_REGISTRY }}/api-gateway:${{ github.sha }}
|
||||
- name: Deploy Amazon ECS task definition
|
||||
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
|
||||
with:
|
||||
task-definition: ${{ steps.task-def-prod.outputs.task-definition }}
|
||||
service: api-gateway-prod
|
||||
cluster: prod
|
||||
wait-for-service-stability: true
|
||||
|
||||
newrelic:
|
||||
needs: deploy-web
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Create New Relic deployment marker for Web
|
||||
uses: newrelic/deployment-marker-action@v1
|
||||
with:
|
||||
accountId: ${{ secrets.NEW_RELIC_ACCOUNT_ID }}
|
||||
apiKey: ${{ secrets.NEW_RELIC_API_KEY }}
|
||||
applicationId: ${{ secrets.NEW_RELIC_APPLICATION_ID_API_GATEWAY_WEB_PROD }}
|
||||
revision: "${{ github.sha }}"
|
||||
description: "Automated Deployment via Github Actions"
|
||||
user: "${{ github.actor }}"
|
||||
@@ -0,0 +1,37 @@
|
||||
name: Api Gateway
|
||||
|
||||
concurrency:
|
||||
group: api_gateway
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '*standardnotes/api-gateway*'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
call_server_application_workflow:
|
||||
name: Server Application
|
||||
uses: standardnotes/server/.github/workflows/common-server-application.yml@main
|
||||
with:
|
||||
service_name: api-gateway
|
||||
workspace_name: "@standardnotes/api-gateway"
|
||||
e2e_tag_parameter_name: api_gateway_image_tag
|
||||
deploy_worker: false
|
||||
package_path: packages/api-gateway
|
||||
secrets: inherit
|
||||
|
||||
newrelic:
|
||||
needs: call_server_application_workflow
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Create New Relic deployment marker for Web
|
||||
uses: newrelic/deployment-marker-action@v1
|
||||
with:
|
||||
accountId: ${{ secrets.NEW_RELIC_ACCOUNT_ID }}
|
||||
apiKey: ${{ secrets.NEW_RELIC_API_KEY }}
|
||||
applicationId: ${{ secrets.NEW_RELIC_APPLICATION_ID_API_GATEWAY_WEB_PROD }}
|
||||
revision: "${{ github.sha }}"
|
||||
description: "Automated Deployment via Github Actions"
|
||||
user: "${{ github.actor }}"
|
||||
@@ -1,206 +0,0 @@
|
||||
name: Auth Server
|
||||
|
||||
concurrency:
|
||||
group: auth
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '*standardnotes/auth-server*'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
node-version-file: '.nvmrc'
|
||||
|
||||
- name: Build
|
||||
run: yarn build
|
||||
|
||||
- name: Lint
|
||||
run: yarn lint:auth
|
||||
|
||||
- name: Test
|
||||
run: yarn test:auth
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Publish Docker image for E2E testing
|
||||
run: |
|
||||
yarn docker build @standardnotes/auth-server -t standardnotes/auth:${{ github.sha }}
|
||||
docker push standardnotes/auth:${{ github.sha }}
|
||||
|
||||
- name: Run E2E test suite
|
||||
uses: convictional/trigger-workflow-and-wait@v1.6.3
|
||||
with:
|
||||
owner: standardnotes
|
||||
repo: e2e
|
||||
github_token: ${{ secrets.CI_PAT_TOKEN }}
|
||||
workflow_file_name: testing-with-stable-client.yml
|
||||
wait_interval: 30
|
||||
client_payload: '{"auth_image_tag": "${{ github.sha }}"}'
|
||||
propagate_failure: true
|
||||
trigger_workflow: true
|
||||
wait_workflow: true
|
||||
|
||||
publish-aws-ecr:
|
||||
needs: test
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
node-version-file: '.nvmrc'
|
||||
- name: Build locally
|
||||
run: yarn build
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-east-1
|
||||
- name: Login to Amazon ECR
|
||||
id: login-ecr
|
||||
uses: aws-actions/amazon-ecr-login@v1
|
||||
- name: Build, tag, and push image to Amazon ECR
|
||||
id: build-image
|
||||
env:
|
||||
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
|
||||
ECR_REPOSITORY: auth
|
||||
IMAGE_TAG: ${{ github.sha }}
|
||||
run: |
|
||||
yarn docker build @standardnotes/auth-server -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
|
||||
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
|
||||
docker tag $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG $ECR_REGISTRY/$ECR_REPOSITORY:latest
|
||||
docker push $ECR_REGISTRY/$ECR_REPOSITORY:latest
|
||||
|
||||
publish-docker-hub:
|
||||
needs: test
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
node-version-file: '.nvmrc'
|
||||
- name: Build locally
|
||||
run: yarn build
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
- name: Publish Docker image as stable
|
||||
run: |
|
||||
yarn docker build @standardnotes/auth-server -t standardnotes/auth:latest
|
||||
docker push standardnotes/auth:latest
|
||||
|
||||
deploy-web:
|
||||
needs: publish-aws-ecr
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-east-1
|
||||
- name: Download task definition
|
||||
run: |
|
||||
aws ecs describe-task-definition --task-definition auth-prod --query taskDefinition > task-definition.json
|
||||
- name: Fill in the new version in the Amazon ECS task definition
|
||||
run: |
|
||||
jq '(.containerDefinitions[] | select(.name=="auth-prod") | .environment[] | select(.name=="VERSION")).value = "${{ github.sha }}"' task-definition.json > tmp.json && mv tmp.json task-definition.json
|
||||
- name: Fill in the new image ID in the Amazon ECS task definition
|
||||
id: task-def-prod
|
||||
uses: aws-actions/amazon-ecs-render-task-definition@v1
|
||||
with:
|
||||
task-definition: task-definition.json
|
||||
container-name: auth-prod
|
||||
image: ${{ secrets.AWS_ECR_REGISTRY }}/auth:${{ github.sha }}
|
||||
- name: Deploy Amazon ECS task definition
|
||||
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
|
||||
with:
|
||||
task-definition: ${{ steps.task-def-prod.outputs.task-definition }}
|
||||
service: auth-prod
|
||||
cluster: prod
|
||||
wait-for-service-stability: true
|
||||
|
||||
deploy-worker:
|
||||
needs: publish-aws-ecr
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-east-1
|
||||
- name: Download task definition
|
||||
run: |
|
||||
aws ecs describe-task-definition --task-definition auth-worker-prod --query taskDefinition > task-definition.json
|
||||
- name: Fill in the new version in the Amazon ECS task definition
|
||||
run: |
|
||||
jq '(.containerDefinitions[] | select(.name=="auth-worker-prod") | .environment[] | select(.name=="VERSION")).value = "${{ github.sha }}"' task-definition.json > tmp.json && mv tmp.json task-definition.json
|
||||
- name: Fill in the new image ID in the Amazon ECS task definition
|
||||
id: task-def-prod
|
||||
uses: aws-actions/amazon-ecs-render-task-definition@v1
|
||||
with:
|
||||
task-definition: task-definition.json
|
||||
container-name: auth-worker-prod
|
||||
image: ${{ secrets.AWS_ECR_REGISTRY }}/auth:${{ github.sha }}
|
||||
- name: Deploy Amazon ECS task definition
|
||||
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
|
||||
with:
|
||||
task-definition: ${{ steps.task-def-prod.outputs.task-definition }}
|
||||
service: auth-worker-prod
|
||||
cluster: prod
|
||||
wait-for-service-stability: true
|
||||
|
||||
newrelic:
|
||||
needs: [ deploy-web, deploy-worker ]
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Create New Relic deployment marker for Web
|
||||
uses: newrelic/deployment-marker-action@v1
|
||||
with:
|
||||
accountId: ${{ secrets.NEW_RELIC_ACCOUNT_ID }}
|
||||
apiKey: ${{ secrets.NEW_RELIC_API_KEY }}
|
||||
applicationId: ${{ secrets.NEW_RELIC_APPLICATION_ID_AUTH_WEB_PROD }}
|
||||
revision: "${{ github.sha }}"
|
||||
description: "Automated Deployment via Github Actions"
|
||||
user: "${{ github.actor }}"
|
||||
- name: Create New Relic deployment marker for Worker
|
||||
uses: newrelic/deployment-marker-action@v1
|
||||
with:
|
||||
accountId: ${{ secrets.NEW_RELIC_ACCOUNT_ID }}
|
||||
apiKey: ${{ secrets.NEW_RELIC_API_KEY }}
|
||||
applicationId: ${{ secrets.NEW_RELIC_APPLICATION_ID_AUTH_WORKER_PROD }}
|
||||
revision: "${{ github.sha }}"
|
||||
description: "Automated Deployment via Github Actions"
|
||||
user: "${{ github.actor }}"
|
||||
@@ -0,0 +1,46 @@
|
||||
name: Auth Server
|
||||
|
||||
concurrency:
|
||||
group: auth
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '*standardnotes/auth-server*'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
call_server_application_workflow:
|
||||
name: Server Application
|
||||
uses: standardnotes/server/.github/workflows/common-server-application.yml@main
|
||||
with:
|
||||
service_name: auth
|
||||
workspace_name: "@standardnotes/auth-server"
|
||||
e2e_tag_parameter_name: auth_image_tag
|
||||
package_path: packages/auth
|
||||
secrets: inherit
|
||||
|
||||
newrelic:
|
||||
needs: call_server_application_workflow
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Create New Relic deployment marker for Web
|
||||
uses: newrelic/deployment-marker-action@v1
|
||||
with:
|
||||
accountId: ${{ secrets.NEW_RELIC_ACCOUNT_ID }}
|
||||
apiKey: ${{ secrets.NEW_RELIC_API_KEY }}
|
||||
applicationId: ${{ secrets.NEW_RELIC_APPLICATION_ID_AUTH_WEB_PROD }}
|
||||
revision: "${{ github.sha }}"
|
||||
description: "Automated Deployment via Github Actions"
|
||||
user: "${{ github.actor }}"
|
||||
- name: Create New Relic deployment marker for Worker
|
||||
uses: newrelic/deployment-marker-action@v1
|
||||
with:
|
||||
accountId: ${{ secrets.NEW_RELIC_ACCOUNT_ID }}
|
||||
apiKey: ${{ secrets.NEW_RELIC_API_KEY }}
|
||||
applicationId: ${{ secrets.NEW_RELIC_APPLICATION_ID_AUTH_WORKER_PROD }}
|
||||
revision: "${{ github.sha }}"
|
||||
description: "Automated Deployment via Github Actions"
|
||||
user: "${{ github.actor }}"
|
||||
@@ -0,0 +1,55 @@
|
||||
name: Reusable Server Application Deployment Workflow
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
service_name:
|
||||
required: true
|
||||
type: string
|
||||
docker_image:
|
||||
required: true
|
||||
type: string
|
||||
secrets:
|
||||
AWS_ACCESS_KEY_ID:
|
||||
required: true
|
||||
AWS_SECRET_ACCESS_KEY:
|
||||
required: true
|
||||
AWS_ECR_REGISTRY:
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-east-1
|
||||
|
||||
- name: Download task definition
|
||||
run: |
|
||||
aws ecs describe-task-definition --task-definition ${{ inputs.service_name }}-prod --query taskDefinition > task-definition.json
|
||||
|
||||
- name: Fill in the new version in the Amazon ECS task definition
|
||||
run: |
|
||||
jq '(.containerDefinitions[] | select(.name=="${{ inputs.service_name }}-prod") | .environment[] | select(.name=="VERSION")).value = "${{ github.sha }}"' task-definition.json > tmp.json && mv tmp.json task-definition.json
|
||||
|
||||
- name: Fill in the new image ID in the Amazon ECS task definition
|
||||
id: task-def-prod
|
||||
uses: aws-actions/amazon-ecs-render-task-definition@v1
|
||||
with:
|
||||
task-definition: task-definition.json
|
||||
container-name: ${{ inputs.service_name }}-prod
|
||||
image: ${{ secrets.AWS_ECR_REGISTRY }}/${{ inputs.docker_image }}
|
||||
|
||||
- name: Deploy Amazon ECS task definition
|
||||
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
|
||||
with:
|
||||
task-definition: ${{ steps.task-def-prod.outputs.task-definition }}
|
||||
service: ${{ inputs.service_name }}-prod
|
||||
cluster: prod
|
||||
wait-for-service-stability: true
|
||||
@@ -0,0 +1,96 @@
|
||||
name: Reusable Publish Docker Image Workflow
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
service_name:
|
||||
required: true
|
||||
type: string
|
||||
bundle_dir:
|
||||
required: true
|
||||
type: string
|
||||
package_path:
|
||||
required: true
|
||||
type: string
|
||||
workspace_name:
|
||||
required: true
|
||||
type: string
|
||||
secrets:
|
||||
DOCKER_USERNAME:
|
||||
required: true
|
||||
DOCKER_PASSWORD:
|
||||
required: true
|
||||
AWS_ACCESS_KEY_ID:
|
||||
required: true
|
||||
AWS_SECRET_ACCESS_KEY:
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Cache build
|
||||
id: cache-build
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
packages/**/dist
|
||||
${{ inputs.bundle_dir }}
|
||||
key: ${{ runner.os }}-${{ inputs.service_name }}-build-${{ github.sha }}
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
node-version-file: '.nvmrc'
|
||||
|
||||
- name: Build
|
||||
if: steps.cache-build.outputs.cache-hit != 'true'
|
||||
run: yarn build ${{ inputs.package_path }}
|
||||
|
||||
- name: Bundle
|
||||
if: steps.cache-build.outputs.cache-hit != 'true'
|
||||
run: yarn workspace ${{ inputs.workspace_name }} bundle --no-compress --output-directory ${{ inputs.bundle_dir }}
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-east-1
|
||||
|
||||
- name: Login to Amazon ECR
|
||||
id: login-ecr
|
||||
uses: aws-actions/amazon-ecr-login@v1
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@master
|
||||
with:
|
||||
platforms: all
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@master
|
||||
|
||||
- name: Publish Docker image
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
builder: ${{ steps.buildx.outputs.name }}
|
||||
context: ${{ inputs.bundle_dir }}
|
||||
file: ${{ inputs.bundle_dir }}/${{ inputs.package_path }}/Dockerfile
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: |
|
||||
standardnotes/${{ inputs.service_name }}:latest
|
||||
standardnotes/${{ inputs.service_name }}:${{ github.sha }}
|
||||
${{ steps.login-ecr.outputs.registry }}/${{ inputs.service_name }}:${{ github.sha }}
|
||||
${{ steps.login-ecr.outputs.registry }}/${{ inputs.service_name }}:latest
|
||||
@@ -0,0 +1,236 @@
|
||||
name: Reusable Server Application Workflow
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
service_name:
|
||||
required: true
|
||||
type: string
|
||||
workspace_name:
|
||||
required: true
|
||||
type: string
|
||||
deploy_web:
|
||||
required: false
|
||||
default: true
|
||||
type: boolean
|
||||
deploy_worker:
|
||||
required: false
|
||||
default: true
|
||||
type: boolean
|
||||
e2e_tag_parameter_name:
|
||||
required: false
|
||||
type: string
|
||||
package_path:
|
||||
required: true
|
||||
type: string
|
||||
secrets:
|
||||
DOCKER_USERNAME:
|
||||
required: true
|
||||
DOCKER_PASSWORD:
|
||||
required: true
|
||||
CI_PAT_TOKEN:
|
||||
required: true
|
||||
AWS_ACCESS_KEY_ID:
|
||||
required: true
|
||||
AWS_SECRET_ACCESS_KEY:
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
outputs:
|
||||
temp_dir: ${{ steps.bundle-dir.outputs.temp_dir }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Create Bundle Dir
|
||||
id: bundle-dir
|
||||
run: echo "temp_dir=$(mktemp -d -t ${{ inputs.service_name }}-${{ github.sha }}-XXXXXXX)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Cache build
|
||||
id: cache-build
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
packages/**/dist
|
||||
${{ steps.bundle-dir.outputs.temp_dir }}
|
||||
key: ${{ runner.os }}-${{ inputs.service_name }}-build-${{ github.sha }}
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
node-version-file: '.nvmrc'
|
||||
|
||||
- name: Build
|
||||
run: yarn build ${{ inputs.package_path }}
|
||||
|
||||
- name: Bundle
|
||||
run: yarn workspace ${{ inputs.workspace_name }} bundle --no-compress --output-directory ${{ steps.bundle-dir.outputs.temp_dir }}
|
||||
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
needs: build
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Cache build
|
||||
id: cache-build
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
packages/**/dist
|
||||
${{ needs.build.outputs.temp_dir }}
|
||||
key: ${{ runner.os }}-${{ inputs.service_name }}-build-${{ github.sha }}
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
node-version-file: '.nvmrc'
|
||||
|
||||
- name: Build
|
||||
if: steps.cache-build.outputs.cache-hit != 'true'
|
||||
run: yarn build ${{ inputs.package_path }}
|
||||
|
||||
- name: Lint
|
||||
run: yarn lint:${{ inputs.service_name }}
|
||||
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
needs: build
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Cache build
|
||||
id: cache-build
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
packages/**/dist
|
||||
${{ needs.build.outputs.temp_dir }}
|
||||
key: ${{ runner.os }}-${{ inputs.service_name }}-build-${{ github.sha }}
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
node-version-file: '.nvmrc'
|
||||
|
||||
- name: Build
|
||||
if: steps.cache-build.outputs.cache-hit != 'true'
|
||||
run: yarn build ${{ inputs.package_path }}
|
||||
|
||||
- name: Test
|
||||
run: yarn test ${{ inputs.package_path }}
|
||||
|
||||
e2e:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
needs: build
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Cache build
|
||||
id: cache-build
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
packages/**/dist
|
||||
${{ needs.build.outputs.temp_dir }}
|
||||
key: ${{ runner.os }}-${{ inputs.service_name }}-build-${{ github.sha }}
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
node-version-file: '.nvmrc'
|
||||
|
||||
- name: Build
|
||||
if: steps.cache-build.outputs.cache-hit != 'true'
|
||||
run: yarn build ${{ inputs.package_path }}
|
||||
|
||||
- name: Bundle
|
||||
if: steps.cache-build.outputs.cache-hit != 'true'
|
||||
run: yarn workspace ${{ inputs.workspace_name }} bundle --no-compress --output-directory ${{ needs.build.outputs.temp_dir }}
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@master
|
||||
with:
|
||||
platforms: all
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@master
|
||||
|
||||
- name: Publish Docker image for E2E testing
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
builder: ${{ steps.buildx.outputs.name }}
|
||||
context: ${{ needs.build.outputs.temp_dir }}
|
||||
file: ${{ needs.build.outputs.temp_dir }}/${{ inputs.package_path }}/Dockerfile
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: standardnotes/${{ inputs.service_name }}:${{ github.sha }}
|
||||
|
||||
- name: Run E2E test suite
|
||||
uses: convictional/trigger-workflow-and-wait@v1.6.3
|
||||
with:
|
||||
owner: standardnotes
|
||||
repo: e2e
|
||||
github_token: ${{ secrets.CI_PAT_TOKEN }}
|
||||
workflow_file_name: testing-with-stable-client.yml
|
||||
wait_interval: 30
|
||||
client_payload: '{"${{ inputs.e2e_tag_parameter_name }}": "${{ github.sha }}"}'
|
||||
propagate_failure: true
|
||||
trigger_workflow: true
|
||||
wait_workflow: true
|
||||
|
||||
publish:
|
||||
needs: [ build, test, lint, e2e ]
|
||||
|
||||
name: Publish Docker Image
|
||||
uses: standardnotes/server/.github/workflows/common-docker-image.yml@main
|
||||
with:
|
||||
service_name: ${{ inputs.service_name }}
|
||||
bundle_dir: ${{ needs.build.outputs.temp_dir }}
|
||||
package_path: ${{ inputs.package_path }}
|
||||
workspace_name: ${{ inputs.workspace_name }}
|
||||
secrets: inherit
|
||||
|
||||
deploy-web:
|
||||
if: ${{ inputs.deploy_web }}
|
||||
|
||||
needs: publish
|
||||
|
||||
name: Deploy Web
|
||||
uses: standardnotes/server/.github/workflows/common-deploy.yml@main
|
||||
with:
|
||||
service_name: ${{ inputs.service_name }}
|
||||
docker_image: ${{ inputs.service_name }}:${{ github.sha }}
|
||||
secrets: inherit
|
||||
|
||||
deploy-worker:
|
||||
if: ${{ inputs.deploy_worker }}
|
||||
|
||||
needs: publish
|
||||
|
||||
name: Deploy Worker
|
||||
uses: standardnotes/server/.github/workflows/common-deploy.yml@main
|
||||
with:
|
||||
service_name: ${{ inputs.service_name }}-worker
|
||||
docker_image: ${{ inputs.service_name }}:${{ github.sha }}
|
||||
secrets: inherit
|
||||
@@ -1,136 +0,0 @@
|
||||
name: Event Store
|
||||
|
||||
concurrency:
|
||||
group: event-store
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '*standardnotes/event-store*'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
node-version-file: '.nvmrc'
|
||||
- run: yarn build
|
||||
- run: yarn lint:event-store
|
||||
- run: yarn test:event-store
|
||||
|
||||
publish-aws-ecr:
|
||||
needs: test
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
node-version-file: '.nvmrc'
|
||||
- name: Build locally
|
||||
run: yarn build
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-east-1
|
||||
- name: Login to Amazon ECR
|
||||
id: login-ecr
|
||||
uses: aws-actions/amazon-ecr-login@v1
|
||||
- name: Build, tag, and push image to Amazon ECR
|
||||
id: build-image
|
||||
env:
|
||||
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
|
||||
ECR_REPOSITORY: event-store
|
||||
IMAGE_TAG: ${{ github.sha }}
|
||||
run: |
|
||||
yarn docker build @standardnotes/event-store -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
|
||||
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
|
||||
docker tag $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG $ECR_REGISTRY/$ECR_REPOSITORY:latest
|
||||
docker push $ECR_REGISTRY/$ECR_REPOSITORY:latest
|
||||
|
||||
publish-docker-hub:
|
||||
needs: test
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
node-version-file: '.nvmrc'
|
||||
- name: Build locally
|
||||
run: yarn build
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
- name: Build, tag, and push image to Docker Hub
|
||||
run: |
|
||||
yarn docker build @standardnotes/event-store -t standardnotes/event-store:${{ github.sha }}
|
||||
docker push standardnotes/event-store:${{ github.sha }}
|
||||
docker tag standardnotes/event-store:${{ github.sha }} standardnotes/event-store:latest
|
||||
docker push standardnotes/event-store:latest
|
||||
|
||||
deploy-worker:
|
||||
needs: publish-aws-ecr
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-east-1
|
||||
- name: Download task definition
|
||||
run: |
|
||||
aws ecs describe-task-definition --task-definition event-store-prod --query taskDefinition > task-definition.json
|
||||
- name: Fill in the new version in the Amazon ECS task definition
|
||||
run: |
|
||||
jq '(.containerDefinitions[] | select(.name=="event-store-prod") | .environment[] | select(.name=="VERSION")).value = "${{ github.sha }}"' task-definition.json > tmp.json && mv tmp.json task-definition.json
|
||||
- name: Fill in the new image ID in the Amazon ECS task definition
|
||||
id: task-def-prod
|
||||
uses: aws-actions/amazon-ecs-render-task-definition@v1
|
||||
with:
|
||||
task-definition: task-definition.json
|
||||
container-name: event-store-prod
|
||||
image: ${{ secrets.AWS_ECR_REGISTRY }}/event-store:${{ github.sha }}
|
||||
- name: Deploy Amazon ECS task definition
|
||||
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
|
||||
with:
|
||||
task-definition: ${{ steps.task-def-prod.outputs.task-definition }}
|
||||
service: event-store-prod
|
||||
cluster: prod
|
||||
wait-for-service-stability: true
|
||||
|
||||
newrelic:
|
||||
needs: [ deploy-worker ]
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Create New Relic deployment marker for Worker
|
||||
uses: newrelic/deployment-marker-action@v1
|
||||
with:
|
||||
accountId: ${{ secrets.NEW_RELIC_ACCOUNT_ID }}
|
||||
apiKey: ${{ secrets.NEW_RELIC_API_KEY }}
|
||||
applicationId: ${{ secrets.NEW_RELIC_APPLICATION_ID_EVENT_STORE_PROD }}
|
||||
revision: "${{ github.sha }}"
|
||||
description: "Automated Deployment via Github Actions"
|
||||
user: "${{ github.actor }}"
|
||||
@@ -0,0 +1,39 @@
|
||||
name: Event Store
|
||||
|
||||
concurrency:
|
||||
group: event-store
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '*standardnotes/event-store*'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
call_server_application_workflow:
|
||||
name: Server Application
|
||||
uses: standardnotes/server/.github/workflows/common-server-application.yml@main
|
||||
with:
|
||||
service_name: event-store
|
||||
workspace_name: "@standardnotes/event-store"
|
||||
e2e_tag_parameter_name: event_store_image_tag
|
||||
deploy_web: false
|
||||
package_path: packages/event-store
|
||||
secrets: inherit
|
||||
|
||||
newrelic:
|
||||
needs: call_server_application_workflow
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Create New Relic deployment marker for Worker
|
||||
uses: newrelic/deployment-marker-action@v1
|
||||
with:
|
||||
accountId: ${{ secrets.NEW_RELIC_ACCOUNT_ID }}
|
||||
apiKey: ${{ secrets.NEW_RELIC_API_KEY }}
|
||||
applicationId: ${{ secrets.NEW_RELIC_APPLICATION_ID_EVENT_STORE_PROD }}
|
||||
revision: "${{ github.sha }}"
|
||||
description: "Automated Deployment via Github Actions"
|
||||
user: "${{ github.actor }}"
|
||||
@@ -1,206 +0,0 @@
|
||||
name: Files Server
|
||||
|
||||
concurrency:
|
||||
group: files
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '*standardnotes/files-server*'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
node-version-file: '.nvmrc'
|
||||
|
||||
- name: Build
|
||||
run: yarn build
|
||||
|
||||
- name: Lint
|
||||
run: yarn lint:files
|
||||
|
||||
- name: Test
|
||||
run: yarn test:files
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Publish Docker image for E2E testing
|
||||
run: |
|
||||
yarn docker build @standardnotes/files-server -t standardnotes/files:${{ github.sha }}
|
||||
docker push standardnotes/files:${{ github.sha }}
|
||||
|
||||
- name: Run E2E test suite
|
||||
uses: convictional/trigger-workflow-and-wait@v1.6.3
|
||||
with:
|
||||
owner: standardnotes
|
||||
repo: e2e
|
||||
github_token: ${{ secrets.CI_PAT_TOKEN }}
|
||||
workflow_file_name: testing-with-stable-client.yml
|
||||
wait_interval: 30
|
||||
client_payload: '{"files_image_tag": "${{ github.sha }}"}'
|
||||
propagate_failure: true
|
||||
trigger_workflow: true
|
||||
wait_workflow: true
|
||||
|
||||
publish-aws-ecr:
|
||||
needs: test
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
node-version-file: '.nvmrc'
|
||||
- name: Build locally
|
||||
run: yarn build
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-east-1
|
||||
- name: Login to Amazon ECR
|
||||
id: login-ecr
|
||||
uses: aws-actions/amazon-ecr-login@v1
|
||||
- name: Build, tag, and push image to Amazon ECR
|
||||
id: build-image
|
||||
env:
|
||||
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
|
||||
ECR_REPOSITORY: files
|
||||
IMAGE_TAG: ${{ github.sha }}
|
||||
run: |
|
||||
yarn docker build @standardnotes/files-server -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
|
||||
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
|
||||
docker tag $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG $ECR_REGISTRY/$ECR_REPOSITORY:latest
|
||||
docker push $ECR_REGISTRY/$ECR_REPOSITORY:latest
|
||||
|
||||
publish-docker-hub:
|
||||
needs: test
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
node-version-file: '.nvmrc'
|
||||
- name: Build locally
|
||||
run: yarn build
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
- name: Build, tag, and push image to Docker Hub
|
||||
run: |
|
||||
yarn docker build @standardnotes/files-server -t standardnotes/files:latest
|
||||
docker push standardnotes/files:latest
|
||||
|
||||
deploy-web:
|
||||
needs: publish-aws-ecr
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-east-1
|
||||
- name: Download task definition
|
||||
run: |
|
||||
aws ecs describe-task-definition --task-definition files-prod --query taskDefinition > task-definition.json
|
||||
- name: Fill in the new version in the Amazon ECS task definition
|
||||
run: |
|
||||
jq '(.containerDefinitions[] | select(.name=="files-prod") | .environment[] | select(.name=="VERSION")).value = "${{ github.sha }}"' task-definition.json > tmp.json && mv tmp.json task-definition.json
|
||||
- name: Fill in the new image ID in the Amazon ECS task definition
|
||||
id: task-def-prod
|
||||
uses: aws-actions/amazon-ecs-render-task-definition@v1
|
||||
with:
|
||||
task-definition: task-definition.json
|
||||
container-name: files-prod
|
||||
image: ${{ secrets.AWS_ECR_REGISTRY }}/files:${{ github.sha }}
|
||||
- name: Deploy Amazon ECS task definition
|
||||
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
|
||||
with:
|
||||
task-definition: ${{ steps.task-def-prod.outputs.task-definition }}
|
||||
service: files-prod
|
||||
cluster: prod
|
||||
wait-for-service-stability: true
|
||||
|
||||
deploy-worker:
|
||||
needs: publish-aws-ecr
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-east-1
|
||||
- name: Download task definition
|
||||
run: |
|
||||
aws ecs describe-task-definition --task-definition files-worker-prod --query taskDefinition > task-definition.json
|
||||
- name: Fill in the new version in the Amazon ECS task definition
|
||||
run: |
|
||||
jq '(.containerDefinitions[] | select(.name=="files-worker-prod") | .environment[] | select(.name=="VERSION")).value = "${{ github.sha }}"' task-definition.json > tmp.json && mv tmp.json task-definition.json
|
||||
- name: Fill in the new image ID in the Amazon ECS task definition
|
||||
id: task-def-prod
|
||||
uses: aws-actions/amazon-ecs-render-task-definition@v1
|
||||
with:
|
||||
task-definition: task-definition.json
|
||||
container-name: files-worker-prod
|
||||
image: ${{ secrets.AWS_ECR_REGISTRY }}/files:${{ github.sha }}
|
||||
- name: Deploy Amazon ECS task definition
|
||||
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
|
||||
with:
|
||||
task-definition: ${{ steps.task-def-prod.outputs.task-definition }}
|
||||
service: files-worker-prod
|
||||
cluster: prod
|
||||
wait-for-service-stability: true
|
||||
|
||||
newrelic:
|
||||
needs: [ deploy-web, deploy-worker ]
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Create New Relic deployment marker for Web
|
||||
uses: newrelic/deployment-marker-action@v1
|
||||
with:
|
||||
accountId: ${{ secrets.NEW_RELIC_ACCOUNT_ID }}
|
||||
apiKey: ${{ secrets.NEW_RELIC_API_KEY }}
|
||||
applicationId: ${{ secrets.NEW_RELIC_APPLICATION_ID_FILES_WEB_PROD }}
|
||||
revision: "${{ github.sha }}"
|
||||
description: "Automated Deployment via Github Actions"
|
||||
user: "${{ github.actor }}"
|
||||
- name: Create New Relic deployment marker for Worker
|
||||
uses: newrelic/deployment-marker-action@v1
|
||||
with:
|
||||
accountId: ${{ secrets.NEW_RELIC_ACCOUNT_ID }}
|
||||
apiKey: ${{ secrets.NEW_RELIC_API_KEY }}
|
||||
applicationId: ${{ secrets.NEW_RELIC_APPLICATION_ID_FILES_WORKER_PROD }}
|
||||
revision: "${{ github.sha }}"
|
||||
description: "Automated Deployment via Github Actions"
|
||||
user: "${{ github.actor }}"
|
||||
@@ -0,0 +1,46 @@
|
||||
name: Files Server
|
||||
|
||||
concurrency:
|
||||
group: files
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '*standardnotes/files-server*'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
call_server_application_workflow:
|
||||
name: Server Application
|
||||
uses: standardnotes/server/.github/workflows/common-server-application.yml@main
|
||||
with:
|
||||
service_name: files
|
||||
workspace_name: "@standardnotes/files-server"
|
||||
e2e_tag_parameter_name: files_image_tag
|
||||
package_path: packages/files
|
||||
secrets: inherit
|
||||
|
||||
newrelic:
|
||||
needs: call_server_application_workflow
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Create New Relic deployment marker for Web
|
||||
uses: newrelic/deployment-marker-action@v1
|
||||
with:
|
||||
accountId: ${{ secrets.NEW_RELIC_ACCOUNT_ID }}
|
||||
apiKey: ${{ secrets.NEW_RELIC_API_KEY }}
|
||||
applicationId: ${{ secrets.NEW_RELIC_APPLICATION_ID_FILES_WEB_PROD }}
|
||||
revision: "${{ github.sha }}"
|
||||
description: "Automated Deployment via Github Actions"
|
||||
user: "${{ github.actor }}"
|
||||
- name: Create New Relic deployment marker for Worker
|
||||
uses: newrelic/deployment-marker-action@v1
|
||||
with:
|
||||
accountId: ${{ secrets.NEW_RELIC_ACCOUNT_ID }}
|
||||
apiKey: ${{ secrets.NEW_RELIC_API_KEY }}
|
||||
applicationId: ${{ secrets.NEW_RELIC_APPLICATION_ID_FILES_WORKER_PROD }}
|
||||
revision: "${{ github.sha }}"
|
||||
description: "Automated Deployment via Github Actions"
|
||||
user: "${{ github.actor }}"
|
||||
@@ -1,136 +0,0 @@
|
||||
name: Scheduler Server
|
||||
|
||||
concurrency:
|
||||
group: scheduler
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '*standardnotes/scheduler-server*'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
node-version-file: '.nvmrc'
|
||||
- run: yarn build
|
||||
- run: yarn lint:scheduler
|
||||
- run: yarn test:scheduler
|
||||
|
||||
publish-aws-ecr:
|
||||
needs: test
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
node-version-file: '.nvmrc'
|
||||
- name: Build locally
|
||||
run: yarn build
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-east-1
|
||||
- name: Login to Amazon ECR
|
||||
id: login-ecr
|
||||
uses: aws-actions/amazon-ecr-login@v1
|
||||
- name: Build, tag, and push image to Amazon ECR
|
||||
id: build-image
|
||||
env:
|
||||
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
|
||||
ECR_REPOSITORY: scheduler-worker
|
||||
IMAGE_TAG: ${{ github.sha }}
|
||||
run: |
|
||||
yarn docker build @standardnotes/scheduler-server -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
|
||||
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
|
||||
docker tag $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG $ECR_REGISTRY/$ECR_REPOSITORY:latest
|
||||
docker push $ECR_REGISTRY/$ECR_REPOSITORY:latest
|
||||
|
||||
publish-docker-hub:
|
||||
needs: test
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
node-version-file: '.nvmrc'
|
||||
- name: Build locally
|
||||
run: yarn build
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
- name: Build, tag, and push image to Docker Hub
|
||||
run: |
|
||||
yarn docker build @standardnotes/scheduler-server -t standardnotes/scheduler:${{ github.sha }}
|
||||
docker push standardnotes/scheduler:${{ github.sha }}
|
||||
docker tag standardnotes/scheduler:${{ github.sha }} standardnotes/scheduler:latest
|
||||
docker push standardnotes/scheduler:latest
|
||||
|
||||
deploy-worker:
|
||||
needs: publish-aws-ecr
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-east-1
|
||||
- name: Download task definition
|
||||
run: |
|
||||
aws ecs describe-task-definition --task-definition scheduler-worker-prod --query taskDefinition > task-definition.json
|
||||
- name: Fill in the new version in the Amazon ECS task definition
|
||||
run: |
|
||||
jq '(.containerDefinitions[] | select(.name=="scheduler-worker-prod") | .environment[] | select(.name=="VERSION")).value = "${{ github.sha }}"' task-definition.json > tmp.json && mv tmp.json task-definition.json
|
||||
- name: Fill in the new image ID in the Amazon ECS task definition
|
||||
id: task-def-prod
|
||||
uses: aws-actions/amazon-ecs-render-task-definition@v1
|
||||
with:
|
||||
task-definition: task-definition.json
|
||||
container-name: scheduler-worker-prod
|
||||
image: ${{ secrets.AWS_ECR_REGISTRY }}/scheduler-worker:${{ github.sha }}
|
||||
- name: Deploy Amazon ECS task definition
|
||||
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
|
||||
with:
|
||||
task-definition: ${{ steps.task-def-prod.outputs.task-definition }}
|
||||
service: scheduler-worker-prod
|
||||
cluster: prod
|
||||
wait-for-service-stability: true
|
||||
|
||||
newrelic:
|
||||
needs: [ deploy-worker ]
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Create New Relic deployment marker for Worker
|
||||
uses: newrelic/deployment-marker-action@v1
|
||||
with:
|
||||
accountId: ${{ secrets.NEW_RELIC_ACCOUNT_ID }}
|
||||
apiKey: ${{ secrets.NEW_RELIC_API_KEY }}
|
||||
applicationId: ${{ secrets.NEW_RELIC_APPLICATION_ID_SCHEDULER_WORKER_PROD }}
|
||||
revision: "${{ github.sha }}"
|
||||
description: "Automated Deployment via Github Actions"
|
||||
user: "${{ github.actor }}"
|
||||
@@ -0,0 +1,39 @@
|
||||
name: Scheduler Server
|
||||
|
||||
concurrency:
|
||||
group: scheduler
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '*standardnotes/scheduler-server*'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
call_server_application_workflow:
|
||||
name: Server Application
|
||||
uses: standardnotes/server/.github/workflows/common-server-application.yml@main
|
||||
with:
|
||||
service_name: scheduler
|
||||
workspace_name: "@standardnotes/scheduler-server"
|
||||
e2e_tag_parameter_name: scheduler_image_tag
|
||||
deploy_web: false
|
||||
package_path: packages/scheduler
|
||||
secrets: inherit
|
||||
|
||||
newrelic:
|
||||
needs: call_server_application_workflow
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Create New Relic deployment marker for Worker
|
||||
uses: newrelic/deployment-marker-action@v1
|
||||
with:
|
||||
accountId: ${{ secrets.NEW_RELIC_ACCOUNT_ID }}
|
||||
apiKey: ${{ secrets.NEW_RELIC_API_KEY }}
|
||||
applicationId: ${{ secrets.NEW_RELIC_APPLICATION_ID_SCHEDULER_WORKER_PROD }}
|
||||
revision: "${{ github.sha }}"
|
||||
description: "Automated Deployment via Github Actions"
|
||||
user: "${{ github.actor }}"
|
||||
@@ -1,317 +0,0 @@
|
||||
name: Server Application Reusable Workflow
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
service_name:
|
||||
required: true
|
||||
type: string
|
||||
workspace_name:
|
||||
required: true
|
||||
type: string
|
||||
run_e2e_test_suite:
|
||||
required: true
|
||||
type: boolean
|
||||
e2e_tag_parameter_name:
|
||||
required: false
|
||||
type: string
|
||||
package_path:
|
||||
required: true
|
||||
type: string
|
||||
secrets:
|
||||
DOCKER_USERNAME:
|
||||
required: true
|
||||
DOCKER_PASSWORD:
|
||||
required: true
|
||||
CI_PAT_TOKEN:
|
||||
required: true
|
||||
AWS_ACCESS_KEY_ID:
|
||||
required: true
|
||||
AWS_SECRET_ACCESS_KEY:
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Cache build
|
||||
id: cache-build
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: packages/**/dist
|
||||
key: ${{ runner.os }}-${{ inputs.service_name }}-build-${{ github.sha }}
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
node-version-file: '.nvmrc'
|
||||
|
||||
- name: Build
|
||||
run: yarn build ${{ inputs.package_path }}
|
||||
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
needs: build
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Cache build
|
||||
id: cache-build
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: packages/**/dist
|
||||
key: ${{ runner.os }}-${{ inputs.service_name }}-build-${{ github.sha }}
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
node-version-file: '.nvmrc'
|
||||
|
||||
- name: Build
|
||||
if: steps.cache-build.outputs.cache-hit != 'true'
|
||||
run: yarn build ${{ inputs.package_path }}
|
||||
|
||||
- name: Lint
|
||||
run: yarn lint:${{ inputs.service_name }}
|
||||
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
needs: build
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Cache build
|
||||
id: cache-build
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: packages/**/dist
|
||||
key: ${{ runner.os }}-${{ inputs.service_name }}-build-${{ github.sha }}
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
node-version-file: '.nvmrc'
|
||||
|
||||
- name: Build
|
||||
if: steps.cache-build.outputs.cache-hit != 'true'
|
||||
run: yarn build ${{ inputs.package_path }}
|
||||
|
||||
- name: Test
|
||||
run: yarn test ${{ inputs.package_path }}
|
||||
|
||||
e2e:
|
||||
if: ${{ inputs.run_e2e_test_suite }} == true
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
needs: build
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Cache build
|
||||
id: cache-build
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: packages/**/dist
|
||||
key: ${{ runner.os }}-${{ inputs.service_name }}-build-${{ github.sha }}
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
node-version-file: '.nvmrc'
|
||||
|
||||
- name: Build
|
||||
if: steps.cache-build.outputs.cache-hit != 'true'
|
||||
run: yarn build ${{ inputs.package_path }}
|
||||
|
||||
- name: Bundle
|
||||
id: bundle
|
||||
run: |
|
||||
TEMP_DIR=$(mktemp -d -t "${{ inputs.service_name }}-${{ github.sha }}")
|
||||
echo "::set-output name=dir::$TEMP_DIR"
|
||||
yarn workspace ${{ inputs.workspace_name }} bundle --no-compress --output-directory $TEMP_DIR
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@master
|
||||
with:
|
||||
platforms: all
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@master
|
||||
|
||||
- name: Publish Docker image for E2E testing
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
builder: ${{ steps.buildx.outputs.name }}
|
||||
context: ${{ steps.bundle.outputs.dir }}
|
||||
file: ${{ steps.bundle.outputs.dir }}/${{ inputs.package_path }}/Dockerfile
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: standardnotes/${{ inputs.service_name }}:${{ github.sha }}
|
||||
|
||||
- name: Run E2E test suite
|
||||
uses: convictional/trigger-workflow-and-wait@v1.6.3
|
||||
with:
|
||||
owner: standardnotes
|
||||
repo: e2e
|
||||
github_token: ${{ secrets.CI_PAT_TOKEN }}
|
||||
workflow_file_name: testing-with-stable-client.yml
|
||||
wait_interval: 30
|
||||
client_payload: '{"${{ inputs.e2e_tag_parameter_name }}": "${{ github.sha }}"}'
|
||||
propagate_failure: true
|
||||
trigger_workflow: true
|
||||
wait_workflow: true
|
||||
|
||||
publish:
|
||||
needs: [ test, lint, e2e ]
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Cache build
|
||||
id: cache-build
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: packages/**/dist
|
||||
key: ${{ runner.os }}-${{ inputs.service_name }}-build-${{ github.sha }}
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
node-version-file: '.nvmrc'
|
||||
|
||||
- name: Build
|
||||
if: steps.cache-build.outputs.cache-hit != 'true'
|
||||
run: yarn build ${{ inputs.package_path }}
|
||||
|
||||
- name: Bundle
|
||||
id: bundle
|
||||
run: |
|
||||
TEMP_DIR=$(mktemp -d -t "${{ inputs.service_name }}-${{ github.sha }}")
|
||||
echo "::set-output name=dir::$TEMP_DIR"
|
||||
yarn workspace ${{ inputs.workspace_name }} bundle --no-compress --output-directory $TEMP_DIR
|
||||
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-east-1
|
||||
|
||||
- name: Login to Amazon ECR
|
||||
id: login-ecr
|
||||
uses: aws-actions/amazon-ecr-login@v1
|
||||
|
||||
- name: Publish Docker image
|
||||
uses: docker/build-push-action@v3
|
||||
env:
|
||||
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
|
||||
ECR_REPOSITORY: ${{ inputs.service_name }}
|
||||
IMAGE_TAG: ${{ github.sha }}
|
||||
with:
|
||||
builder: ${{ steps.buildx.outputs.name }}
|
||||
context: ${{ steps.bundle.outputs.dir }}
|
||||
file: ${{ steps.bundle.outputs.dir }}/${{ inputs.package_path }}/Dockerfile
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: |
|
||||
standardnotes/${{ inputs.service_name }}:latest
|
||||
$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
|
||||
$ECR_REGISTRY/$ECR_REPOSITORY:latest
|
||||
|
||||
deploy-web:
|
||||
needs: publish
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-east-1
|
||||
|
||||
- name: Download task definition
|
||||
run: |
|
||||
aws ecs describe-task-definition --task-definition ${{ inputs.service_name }}-prod --query taskDefinition > task-definition.json
|
||||
|
||||
- name: Fill in the new version in the Amazon ECS task definition
|
||||
run: |
|
||||
jq '(.containerDefinitions[] | select(.name=="${{ inputs.service_name }}-prod") | .environment[] | select(.name=="VERSION")).value = "${{ github.sha }}"' task-definition.json > tmp.json && mv tmp.json task-definition.json
|
||||
|
||||
- name: Fill in the new image ID in the Amazon ECS task definition
|
||||
id: task-def-prod
|
||||
uses: aws-actions/amazon-ecs-render-task-definition@v1
|
||||
with:
|
||||
task-definition: task-definition.json
|
||||
container-name: ${{ inputs.service_name }}-prod
|
||||
image: ${{ secrets.AWS_ECR_REGISTRY }}/${{ inputs.service_name }}:${{ github.sha }}
|
||||
|
||||
- name: Deploy Amazon ECS task definition
|
||||
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
|
||||
with:
|
||||
task-definition: ${{ steps.task-def-prod.outputs.task-definition }}
|
||||
service: ${{ inputs.service_name }}-prod
|
||||
cluster: prod
|
||||
wait-for-service-stability: true
|
||||
|
||||
deploy-worker:
|
||||
needs: publish
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-east-1
|
||||
|
||||
- name: Download task definition
|
||||
run: |
|
||||
aws ecs describe-task-definition --task-definition ${{ inputs.service_name }}-worker-prod --query taskDefinition > task-definition.json
|
||||
|
||||
- name: Fill in the new version in the Amazon ECS task definition
|
||||
run: |
|
||||
jq '(.containerDefinitions[] | select(.name=="${{ inputs.service_name }}-worker-prod") | .environment[] | select(.name=="VERSION")).value = "${{ github.sha }}"' task-definition.json > tmp.json && mv tmp.json task-definition.json
|
||||
|
||||
- name: Fill in the new image ID in the Amazon ECS task definition
|
||||
id: task-def-prod
|
||||
uses: aws-actions/amazon-ecs-render-task-definition@v1
|
||||
with:
|
||||
task-definition: task-definition.json
|
||||
container-name: ${{ inputs.service_name }}-worker-prod
|
||||
image: ${{ secrets.AWS_ECR_REGISTRY }}/${{ inputs.service_name }}:${{ github.sha }}
|
||||
|
||||
- name: Deploy Amazon ECS task definition
|
||||
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
|
||||
with:
|
||||
task-definition: ${{ steps.task-def-prod.outputs.task-definition }}
|
||||
service: ${{ inputs.service_name }}-worker-prod
|
||||
cluster: prod
|
||||
wait-for-service-stability: true
|
||||
@@ -1,48 +0,0 @@
|
||||
name: Update SNJS Packages
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
repository_dispatch:
|
||||
types: [snjs-updated-event]
|
||||
|
||||
jobs:
|
||||
SNJSUpdateEvent:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
ref: main
|
||||
token: ${{ secrets.CI_PAT_TOKEN }}
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
node-version-file: '.nvmrc'
|
||||
- name: Setup git config
|
||||
run: |
|
||||
git config --global user.name "standardci"
|
||||
git config --global user.email "ci@standardnotes.com"
|
||||
- name: Import GPG key
|
||||
uses: crazy-max/ghaction-import-gpg@v5
|
||||
with:
|
||||
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
|
||||
passphrase: ${{ secrets.PASSPHRASE }}
|
||||
git_user_signingkey: true
|
||||
git_commit_gpgsign: true
|
||||
|
||||
- run: yarn install
|
||||
- run: |
|
||||
yarn upgrade:snjs
|
||||
yarn install --no-immutable
|
||||
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v4
|
||||
with:
|
||||
token: ${{ secrets.CI_PAT_TOKEN }}
|
||||
title: "${{ 'chore(deps): upgrade snjs' }}"
|
||||
body: Updates all packages prefixed with "@standardnotes/"
|
||||
commit-message: "${{ 'chore(deps): upgrade snjs' }}"
|
||||
delete-branch: true
|
||||
committer: standardci <ci@standardnotes.com>
|
||||
author: standardci <ci@standardnotes.com>
|
||||
@@ -1,313 +0,0 @@
|
||||
name: Syncing Server
|
||||
|
||||
concurrency:
|
||||
group: syncing_server
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '*standardnotes/syncing-server*'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Cache build
|
||||
id: cache-build
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: packages/**/dist
|
||||
key: ${{ runner.os }}-syncing-server-build-${{ github.sha }}
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
node-version-file: '.nvmrc'
|
||||
|
||||
- name: Build
|
||||
run: yarn build:syncing-server
|
||||
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
needs: build
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Cache build
|
||||
id: cache-build
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: packages/**/dist
|
||||
key: ${{ runner.os }}-syncing-server-build-${{ github.sha }}
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
node-version-file: '.nvmrc'
|
||||
|
||||
- name: Build
|
||||
if: steps.cache-build.outputs.cache-hit != 'true'
|
||||
run: yarn build:syncing-server
|
||||
|
||||
- name: Lint
|
||||
run: yarn lint:syncing-server
|
||||
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
needs: build
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Cache build
|
||||
id: cache-build
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: packages/**/dist
|
||||
key: ${{ runner.os }}-syncing-server-build-${{ github.sha }}
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
node-version-file: '.nvmrc'
|
||||
|
||||
- name: Build
|
||||
if: steps.cache-build.outputs.cache-hit != 'true'
|
||||
run: yarn build:syncing-server
|
||||
|
||||
- name: Test
|
||||
run: yarn test:syncing-server
|
||||
|
||||
e2e:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
needs: build
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Cache build
|
||||
id: cache-build
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: packages/**/dist
|
||||
key: ${{ runner.os }}-syncing-server-build-${{ github.sha }}
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
node-version-file: '.nvmrc'
|
||||
|
||||
- name: Build
|
||||
if: steps.cache-build.outputs.cache-hit != 'true'
|
||||
run: yarn build:syncing-server
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Publish Docker image for E2E testing
|
||||
run: |
|
||||
yarn docker build @standardnotes/syncing-server -t standardnotes/syncing-server-js:${{ github.sha }}
|
||||
docker push standardnotes/syncing-server-js:${{ github.sha }}
|
||||
|
||||
- name: Run E2E test suite
|
||||
uses: convictional/trigger-workflow-and-wait@v1.6.3
|
||||
with:
|
||||
owner: standardnotes
|
||||
repo: e2e
|
||||
github_token: ${{ secrets.CI_PAT_TOKEN }}
|
||||
workflow_file_name: testing-with-stable-client.yml
|
||||
wait_interval: 30
|
||||
client_payload: '{"syncing_server_js_image_tag": "${{ github.sha }}"}'
|
||||
propagate_failure: true
|
||||
trigger_workflow: true
|
||||
wait_workflow: true
|
||||
|
||||
publish-aws-ecr:
|
||||
needs: [ test, lint, e2e ]
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Cache build
|
||||
id: cache-build
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: packages/**/dist
|
||||
key: ${{ runner.os }}-syncing-server-build-${{ github.sha }}
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
node-version-file: '.nvmrc'
|
||||
|
||||
- name: Build
|
||||
if: steps.cache-build.outputs.cache-hit != 'true'
|
||||
run: yarn build:syncing-server
|
||||
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-east-1
|
||||
|
||||
- name: Login to Amazon ECR
|
||||
id: login-ecr
|
||||
uses: aws-actions/amazon-ecr-login@v1
|
||||
|
||||
- name: Build, tag, and push image to Amazon ECR
|
||||
id: build-image
|
||||
env:
|
||||
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
|
||||
ECR_REPOSITORY: syncing-server-js
|
||||
IMAGE_TAG: ${{ github.sha }}
|
||||
run: |
|
||||
yarn docker build @standardnotes/syncing-server -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
|
||||
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
|
||||
docker tag $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG $ECR_REGISTRY/$ECR_REPOSITORY:latest
|
||||
docker push $ECR_REGISTRY/$ECR_REPOSITORY:latest
|
||||
|
||||
publish-docker-hub:
|
||||
needs: [ test, lint, e2e ]
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Cache build
|
||||
id: cache-build
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: packages/**/dist
|
||||
key: ${{ runner.os }}-syncing-server-build-${{ github.sha }}
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
node-version-file: '.nvmrc'
|
||||
|
||||
- name: Build
|
||||
if: steps.cache-build.outputs.cache-hit != 'true'
|
||||
run: yarn build:syncing-server
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Publish Docker image as stable
|
||||
run: |
|
||||
yarn docker build @standardnotes/syncing-server -t standardnotes/syncing-server-js:latest
|
||||
docker push standardnotes/syncing-server-js:latest
|
||||
|
||||
deploy-web:
|
||||
needs: publish-aws-ecr
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-east-1
|
||||
- name: Download task definition
|
||||
run: |
|
||||
aws ecs describe-task-definition --task-definition syncing-server-js-prod --query taskDefinition > task-definition.json
|
||||
- name: Fill in the new version in the Amazon ECS task definition
|
||||
run: |
|
||||
jq '(.containerDefinitions[] | select(.name=="syncing-server-js-prod") | .environment[] | select(.name=="VERSION")).value = "${{ github.sha }}"' task-definition.json > tmp.json && mv tmp.json task-definition.json
|
||||
- name: Fill in the new image ID in the Amazon ECS task definition
|
||||
id: task-def-prod
|
||||
uses: aws-actions/amazon-ecs-render-task-definition@v1
|
||||
with:
|
||||
task-definition: task-definition.json
|
||||
container-name: syncing-server-js-prod
|
||||
image: ${{ secrets.AWS_ECR_REGISTRY }}/syncing-server-js:${{ github.sha }}
|
||||
- name: Deploy Amazon ECS task definition
|
||||
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
|
||||
with:
|
||||
task-definition: ${{ steps.task-def-prod.outputs.task-definition }}
|
||||
service: syncing-server-js-prod
|
||||
cluster: prod
|
||||
wait-for-service-stability: true
|
||||
|
||||
deploy-worker:
|
||||
needs: publish-aws-ecr
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-east-1
|
||||
- name: Download task definition
|
||||
run: |
|
||||
aws ecs describe-task-definition --task-definition syncing-server-js-worker-prod --query taskDefinition > task-definition.json
|
||||
- name: Fill in the new version in the Amazon ECS task definition
|
||||
run: |
|
||||
jq '(.containerDefinitions[] | select(.name=="syncing-server-js-worker-prod") | .environment[] | select(.name=="VERSION")).value = "${{ github.sha }}"' task-definition.json > tmp.json && mv tmp.json task-definition.json
|
||||
- name: Fill in the new image ID in the Amazon ECS task definition
|
||||
id: task-def-prod
|
||||
uses: aws-actions/amazon-ecs-render-task-definition@v1
|
||||
with:
|
||||
task-definition: task-definition.json
|
||||
container-name: syncing-server-js-worker-prod
|
||||
image: ${{ secrets.AWS_ECR_REGISTRY }}/syncing-server-js:${{ github.sha }}
|
||||
- name: Deploy Amazon ECS task definition
|
||||
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
|
||||
with:
|
||||
task-definition: ${{ steps.task-def-prod.outputs.task-definition }}
|
||||
service: syncing-server-js-worker-prod
|
||||
cluster: prod
|
||||
wait-for-service-stability: true
|
||||
|
||||
newrelic:
|
||||
needs: [ deploy-web, deploy-worker ]
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Create New Relic deployment marker for Web
|
||||
uses: newrelic/deployment-marker-action@v1
|
||||
with:
|
||||
accountId: ${{ secrets.NEW_RELIC_ACCOUNT_ID }}
|
||||
apiKey: ${{ secrets.NEW_RELIC_API_KEY }}
|
||||
applicationId: ${{ secrets.NEW_RELIC_APPLICATION_ID_SYNCING_SERVER_WEB_PROD }}
|
||||
revision: "${{ github.sha }}"
|
||||
description: "Automated Deployment via Github Actions"
|
||||
user: "${{ github.actor }}"
|
||||
- name: Create New Relic deployment marker for Worker
|
||||
uses: newrelic/deployment-marker-action@v1
|
||||
with:
|
||||
accountId: ${{ secrets.NEW_RELIC_ACCOUNT_ID }}
|
||||
apiKey: ${{ secrets.NEW_RELIC_API_KEY }}
|
||||
applicationId: ${{ secrets.NEW_RELIC_APPLICATION_ID_SYNCING_SERVER_WORKER_PROD }}
|
||||
revision: "${{ github.sha }}"
|
||||
description: "Automated Deployment via Github Actions"
|
||||
user: "${{ github.actor }}"
|
||||
@@ -0,0 +1,46 @@
|
||||
name: Syncing Server
|
||||
|
||||
concurrency:
|
||||
group: syncing_server
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '*standardnotes/syncing-server*'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
call_server_application_workflow:
|
||||
name: Server Application
|
||||
uses: standardnotes/server/.github/workflows/common-server-application.yml@main
|
||||
with:
|
||||
service_name: syncing-server-js
|
||||
workspace_name: "@standardnotes/syncing-server"
|
||||
e2e_tag_parameter_name: syncing_server_js_image_tag
|
||||
package_path: packages/syncing-server
|
||||
secrets: inherit
|
||||
|
||||
newrelic:
|
||||
needs: call_server_application_workflow
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Create New Relic deployment marker for Web
|
||||
uses: newrelic/deployment-marker-action@v1
|
||||
with:
|
||||
accountId: ${{ secrets.NEW_RELIC_ACCOUNT_ID }}
|
||||
apiKey: ${{ secrets.NEW_RELIC_API_KEY }}
|
||||
applicationId: ${{ secrets.NEW_RELIC_APPLICATION_ID_SYNCING_SERVER_WEB_PROD }}
|
||||
revision: "${{ github.sha }}"
|
||||
description: "Automated Deployment via Github Actions"
|
||||
user: "${{ github.actor }}"
|
||||
- name: Create New Relic deployment marker for Worker
|
||||
uses: newrelic/deployment-marker-action@v1
|
||||
with:
|
||||
accountId: ${{ secrets.NEW_RELIC_ACCOUNT_ID }}
|
||||
apiKey: ${{ secrets.NEW_RELIC_API_KEY }}
|
||||
applicationId: ${{ secrets.NEW_RELIC_APPLICATION_ID_SYNCING_SERVER_WORKER_PROD }}
|
||||
revision: "${{ github.sha }}"
|
||||
description: "Automated Deployment via Github Actions"
|
||||
user: "${{ github.actor }}"
|
||||
@@ -1,264 +0,0 @@
|
||||
name: Websockets Server
|
||||
|
||||
concurrency:
|
||||
group: websockets
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '*standardnotes/websockets-server*'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Cache build
|
||||
id: cache-build
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: packages/**/dist
|
||||
key: ${{ runner.os }}-websockets-build-${{ github.sha }}
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
node-version-file: '.nvmrc'
|
||||
|
||||
- name: Build
|
||||
run: yarn build:websockets
|
||||
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
needs: build
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Cache build
|
||||
id: cache-build
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: packages/**/dist
|
||||
key: ${{ runner.os }}-websockets-build-${{ github.sha }}
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
node-version-file: '.nvmrc'
|
||||
|
||||
- name: Build
|
||||
if: steps.cache-build.outputs.cache-hit != 'true'
|
||||
run: yarn build:websockets
|
||||
|
||||
- name: Lint
|
||||
run: yarn lint:websockets
|
||||
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
needs: build
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Cache build
|
||||
id: cache-build
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: packages/**/dist
|
||||
key: ${{ runner.os }}-websockets-build-${{ github.sha }}
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
node-version-file: '.nvmrc'
|
||||
|
||||
- name: Build
|
||||
if: steps.cache-build.outputs.cache-hit != 'true'
|
||||
run: yarn build:websockets
|
||||
|
||||
- name: Test
|
||||
run: yarn test:websockets
|
||||
|
||||
publish-aws-ecr:
|
||||
needs: [ test, lint ]
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Cache build
|
||||
id: cache-build
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: packages/**/dist
|
||||
key: ${{ runner.os }}-websockets-build-${{ github.sha }}
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
node-version-file: '.nvmrc'
|
||||
|
||||
- name: Build
|
||||
if: steps.cache-build.outputs.cache-hit != 'true'
|
||||
run: yarn build:websockets
|
||||
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-east-1
|
||||
|
||||
- name: Login to Amazon ECR
|
||||
id: login-ecr
|
||||
uses: aws-actions/amazon-ecr-login@v1
|
||||
|
||||
- name: Build, tag, and push image to Amazon ECR
|
||||
id: build-image
|
||||
env:
|
||||
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
|
||||
ECR_REPOSITORY: websockets
|
||||
IMAGE_TAG: ${{ github.sha }}
|
||||
run: |
|
||||
yarn docker build @standardnotes/websockets-server -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
|
||||
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
|
||||
docker tag $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG $ECR_REGISTRY/$ECR_REPOSITORY:latest
|
||||
docker push $ECR_REGISTRY/$ECR_REPOSITORY:latest
|
||||
|
||||
publish-docker-hub:
|
||||
needs: [ test, lint ]
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Cache build
|
||||
id: cache-build
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: packages/**/dist
|
||||
key: ${{ runner.os }}-websockets-build-${{ github.sha }}
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
node-version-file: '.nvmrc'
|
||||
|
||||
- name: Build
|
||||
if: steps.cache-build.outputs.cache-hit != 'true'
|
||||
run: yarn build:websockets
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Publish Docker image as stable
|
||||
run: |
|
||||
yarn docker build @standardnotes/websockets-server -t standardnotes/websockets:latest
|
||||
docker push standardnotes/websockets:latest
|
||||
|
||||
deploy-web:
|
||||
needs: publish-aws-ecr
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-east-1
|
||||
- name: Download task definition
|
||||
run: |
|
||||
aws ecs describe-task-definition --task-definition websockets-prod --query taskDefinition > task-definition.json
|
||||
- name: Fill in the new version in the Amazon ECS task definition
|
||||
run: |
|
||||
jq '(.containerDefinitions[] | select(.name=="websockets-prod") | .environment[] | select(.name=="VERSION")).value = "${{ github.sha }}"' task-definition.json > tmp.json && mv tmp.json task-definition.json
|
||||
- name: Fill in the new image ID in the Amazon ECS task definition
|
||||
id: task-def-prod
|
||||
uses: aws-actions/amazon-ecs-render-task-definition@v1
|
||||
with:
|
||||
task-definition: task-definition.json
|
||||
container-name: websockets-prod
|
||||
image: ${{ secrets.AWS_ECR_REGISTRY }}/websockets:${{ github.sha }}
|
||||
- name: Deploy Amazon ECS task definition
|
||||
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
|
||||
with:
|
||||
task-definition: ${{ steps.task-def-prod.outputs.task-definition }}
|
||||
service: websockets-prod
|
||||
cluster: prod
|
||||
wait-for-service-stability: true
|
||||
|
||||
deploy-worker:
|
||||
needs: publish-aws-ecr
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-east-1
|
||||
- name: Download task definition
|
||||
run: |
|
||||
aws ecs describe-task-definition --task-definition websockets-worker-prod --query taskDefinition > task-definition.json
|
||||
- name: Fill in the new version in the Amazon ECS task definition
|
||||
run: |
|
||||
jq '(.containerDefinitions[] | select(.name=="websockets-worker-prod") | .environment[] | select(.name=="VERSION")).value = "${{ github.sha }}"' task-definition.json > tmp.json && mv tmp.json task-definition.json
|
||||
- name: Fill in the new image ID in the Amazon ECS task definition
|
||||
id: task-def-prod
|
||||
uses: aws-actions/amazon-ecs-render-task-definition@v1
|
||||
with:
|
||||
task-definition: task-definition.json
|
||||
container-name: websockets-worker-prod
|
||||
image: ${{ secrets.AWS_ECR_REGISTRY }}/websockets:${{ github.sha }}
|
||||
- name: Deploy Amazon ECS task definition
|
||||
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
|
||||
with:
|
||||
task-definition: ${{ steps.task-def-prod.outputs.task-definition }}
|
||||
service: websockets-worker-prod
|
||||
cluster: prod
|
||||
wait-for-service-stability: true
|
||||
|
||||
newrelic:
|
||||
needs: [ deploy-web, deploy-worker ]
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Create New Relic deployment marker for Web
|
||||
uses: newrelic/deployment-marker-action@v1
|
||||
with:
|
||||
accountId: ${{ secrets.NEW_RELIC_ACCOUNT_ID }}
|
||||
apiKey: ${{ secrets.NEW_RELIC_API_KEY }}
|
||||
applicationId: ${{ secrets.NEW_RELIC_APPLICATION_ID_WEBSOCKETS_WEB_PROD }}
|
||||
revision: "${{ github.sha }}"
|
||||
description: "Automated Deployment via Github Actions"
|
||||
user: "${{ github.actor }}"
|
||||
- name: Create New Relic deployment marker for Worker
|
||||
uses: newrelic/deployment-marker-action@v1
|
||||
with:
|
||||
accountId: ${{ secrets.NEW_RELIC_ACCOUNT_ID }}
|
||||
apiKey: ${{ secrets.NEW_RELIC_API_KEY }}
|
||||
applicationId: ${{ secrets.NEW_RELIC_APPLICATION_ID_WEBSOCKETS_WORKER_PROD }}
|
||||
revision: "${{ github.sha }}"
|
||||
description: "Automated Deployment via Github Actions"
|
||||
user: "${{ github.actor }}"
|
||||
@@ -0,0 +1,46 @@
|
||||
name: Websockets Server
|
||||
|
||||
concurrency:
|
||||
group: websockets
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '*standardnotes/websockets-server*'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
call_server_application_workflow:
|
||||
name: Server Application
|
||||
uses: standardnotes/server/.github/workflows/common-server-application.yml@main
|
||||
with:
|
||||
service_name: websockets
|
||||
workspace_name: "@standardnotes/websockets-server"
|
||||
e2e_tag_parameter_name: websockets_image_tag
|
||||
package_path: packages/websockets
|
||||
secrets: inherit
|
||||
|
||||
newrelic:
|
||||
needs: call_server_application_workflow
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Create New Relic deployment marker for Web
|
||||
uses: newrelic/deployment-marker-action@v1
|
||||
with:
|
||||
accountId: ${{ secrets.NEW_RELIC_ACCOUNT_ID }}
|
||||
apiKey: ${{ secrets.NEW_RELIC_API_KEY }}
|
||||
applicationId: ${{ secrets.NEW_RELIC_APPLICATION_ID_WEBSOCKETS_WEB_PROD }}
|
||||
revision: "${{ github.sha }}"
|
||||
description: "Automated Deployment via Github Actions"
|
||||
user: "${{ github.actor }}"
|
||||
- name: Create New Relic deployment marker for Worker
|
||||
uses: newrelic/deployment-marker-action@v1
|
||||
with:
|
||||
accountId: ${{ secrets.NEW_RELIC_ACCOUNT_ID }}
|
||||
apiKey: ${{ secrets.NEW_RELIC_API_KEY }}
|
||||
applicationId: ${{ secrets.NEW_RELIC_APPLICATION_ID_WEBSOCKETS_WORKER_PROD }}
|
||||
revision: "${{ github.sha }}"
|
||||
description: "Automated Deployment via Github Actions"
|
||||
user: "${{ github.actor }}"
|
||||
@@ -12,12 +12,11 @@ on:
|
||||
|
||||
jobs:
|
||||
call_server_application_workflow:
|
||||
name: Build, Test & Deploy Server Application
|
||||
uses: standardnotes/server/.github/workflows/server-application.yml@main
|
||||
name: Server Application
|
||||
uses: standardnotes/server/.github/workflows/common-server-application.yml@main
|
||||
with:
|
||||
service_name: workspace
|
||||
workspace_name: "@standardnotes/workspace-server"
|
||||
run_e2e_test_suite: true
|
||||
e2e_tag_parameter_name: workspace_image_tag
|
||||
package_path: packages/workspace
|
||||
secrets: inherit
|
||||
|
||||
@@ -2555,16 +2555,16 @@ const RAW_RUNTIME_STATE =
|
||||
}]\
|
||||
]],\
|
||||
["@standardnotes/api", [\
|
||||
["npm:1.16.3", {\
|
||||
"packageLocation": "./.yarn/cache/@standardnotes-api-npm-1.16.3-d0cc3c9f0e-512d89961f.zip/node_modules/@standardnotes/api/",\
|
||||
["npm:1.19.0", {\
|
||||
"packageLocation": "./.yarn/cache/@standardnotes-api-npm-1.19.0-ce8296df3c-b28884be40.zip/node_modules/@standardnotes/api/",\
|
||||
"packageDependencies": [\
|
||||
["@standardnotes/api", "npm:1.16.3"],\
|
||||
["@standardnotes/api", "npm:1.19.0"],\
|
||||
["@standardnotes/common", "workspace:packages/common"],\
|
||||
["@standardnotes/encryption", "npm:1.18.2"],\
|
||||
["@standardnotes/models", "npm:1.28.0"],\
|
||||
["@standardnotes/responses", "npm:1.11.1"],\
|
||||
["@standardnotes/encryption", "npm:1.19.0"],\
|
||||
["@standardnotes/models", "npm:1.33.0"],\
|
||||
["@standardnotes/responses", "npm:1.12.0"],\
|
||||
["@standardnotes/security", "workspace:packages/security"],\
|
||||
["@standardnotes/utils", "npm:1.10.0"],\
|
||||
["@standardnotes/utils", "npm:1.11.0"],\
|
||||
["reflect-metadata", "npm:0.1.13"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
@@ -2635,7 +2635,7 @@ const RAW_RUNTIME_STATE =
|
||||
["@newrelic/winston-enricher", "virtual:04783e12400851b8a3d76e71495851cc94959db6e62f04cb0a31190080629440b182d8c8eb4d7f2b04e281912f2783a5fd4d2c3c6ab68d38b7097246c93f4c19#npm:4.0.0"],\
|
||||
["@sentry/node", "npm:7.5.0"],\
|
||||
["@standardnotes/analytics", "workspace:packages/analytics"],\
|
||||
["@standardnotes/api", "npm:1.16.3"],\
|
||||
["@standardnotes/api", "npm:1.19.0"],\
|
||||
["@standardnotes/common", "workspace:packages/common"],\
|
||||
["@standardnotes/domain-events", "workspace:packages/domain-events"],\
|
||||
["@standardnotes/domain-events-infra", "workspace:packages/domain-events-infra"],\
|
||||
@@ -2662,7 +2662,7 @@ const RAW_RUNTIME_STATE =
|
||||
["axios", "npm:0.27.2"],\
|
||||
["bcryptjs", "npm:2.4.3"],\
|
||||
["cors", "npm:2.8.5"],\
|
||||
["dayjs", "npm:1.11.5"],\
|
||||
["dayjs", "npm:1.11.6"],\
|
||||
["dotenv", "npm:16.0.1"],\
|
||||
["eslint", "npm:8.25.0"],\
|
||||
["eslint-plugin-prettier", "virtual:04783e12400851b8a3d76e71495851cc94959db6e62f04cb0a31190080629440b182d8c8eb4d7f2b04e281912f2783a5fd4d2c3c6ab68d38b7097246c93f4c19#npm:4.2.1"],\
|
||||
@@ -2764,15 +2764,15 @@ const RAW_RUNTIME_STATE =
|
||||
}]\
|
||||
]],\
|
||||
["@standardnotes/encryption", [\
|
||||
["npm:1.18.2", {\
|
||||
"packageLocation": "./.yarn/cache/@standardnotes-encryption-npm-1.18.2-546eee8438-255f21734f.zip/node_modules/@standardnotes/encryption/",\
|
||||
["npm:1.19.0", {\
|
||||
"packageLocation": "./.yarn/cache/@standardnotes-encryption-npm-1.19.0-29799e7bcc-af7665e979.zip/node_modules/@standardnotes/encryption/",\
|
||||
"packageDependencies": [\
|
||||
["@standardnotes/encryption", "npm:1.18.2"],\
|
||||
["@standardnotes/encryption", "npm:1.19.0"],\
|
||||
["@standardnotes/common", "workspace:packages/common"],\
|
||||
["@standardnotes/models", "npm:1.28.0"],\
|
||||
["@standardnotes/responses", "npm:1.11.1"],\
|
||||
["@standardnotes/models", "npm:1.33.0"],\
|
||||
["@standardnotes/responses", "npm:1.12.0"],\
|
||||
["@standardnotes/sncrypto-common", "npm:1.13.0"],\
|
||||
["@standardnotes/utils", "npm:1.10.0"],\
|
||||
["@standardnotes/utils", "npm:1.11.0"],\
|
||||
["reflect-metadata", "npm:0.1.13"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
@@ -2820,6 +2820,17 @@ const RAW_RUNTIME_STATE =
|
||||
["reflect-metadata", "npm:0.1.13"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}],\
|
||||
["npm:1.54.0", {\
|
||||
"packageLocation": "./.yarn/cache/@standardnotes-features-npm-1.54.0-15f8cf20f0-7647e7506e.zip/node_modules/@standardnotes/features/",\
|
||||
"packageDependencies": [\
|
||||
["@standardnotes/features", "npm:1.54.0"],\
|
||||
["@standardnotes/auth", "npm:3.19.4"],\
|
||||
["@standardnotes/common", "workspace:packages/common"],\
|
||||
["@standardnotes/security", "workspace:packages/security"],\
|
||||
["reflect-metadata", "npm:0.1.13"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}]\
|
||||
]],\
|
||||
["@standardnotes/files-server", [\
|
||||
@@ -2849,7 +2860,7 @@ const RAW_RUNTIME_STATE =
|
||||
["aws-sdk", "npm:2.1234.0"],\
|
||||
["connect-busboy", "npm:1.0.0"],\
|
||||
["cors", "npm:2.8.5"],\
|
||||
["dayjs", "npm:1.11.5"],\
|
||||
["dayjs", "npm:1.11.6"],\
|
||||
["dotenv", "npm:16.0.1"],\
|
||||
["eslint", "npm:8.25.0"],\
|
||||
["eslint-plugin-prettier", "virtual:04783e12400851b8a3d76e71495851cc94959db6e62f04cb0a31190080629440b182d8c8eb4d7f2b04e281912f2783a5fd4d2c3c6ab68d38b7097246c93f4c19#npm:4.2.1"],\
|
||||
@@ -2888,6 +2899,19 @@ const RAW_RUNTIME_STATE =
|
||||
["reflect-metadata", "npm:0.1.13"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}],\
|
||||
["npm:1.33.0", {\
|
||||
"packageLocation": "./.yarn/cache/@standardnotes-models-npm-1.33.0-df7d20ae6d-7d45409e4a.zip/node_modules/@standardnotes/models/",\
|
||||
"packageDependencies": [\
|
||||
["@standardnotes/models", "npm:1.33.0"],\
|
||||
["@standardnotes/common", "workspace:packages/common"],\
|
||||
["@standardnotes/features", "npm:1.54.0"],\
|
||||
["@standardnotes/responses", "npm:1.12.0"],\
|
||||
["@standardnotes/utils", "npm:1.11.0"],\
|
||||
["lodash", "npm:4.17.21"],\
|
||||
["reflect-metadata", "npm:0.1.13"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}]\
|
||||
]],\
|
||||
["@standardnotes/payloads", [\
|
||||
@@ -2930,6 +2954,17 @@ const RAW_RUNTIME_STATE =
|
||||
["reflect-metadata", "npm:0.1.13"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}],\
|
||||
["npm:1.12.0", {\
|
||||
"packageLocation": "./.yarn/cache/@standardnotes-responses-npm-1.12.0-1de721974f-15b2e92d57.zip/node_modules/@standardnotes/responses/",\
|
||||
"packageDependencies": [\
|
||||
["@standardnotes/responses", "npm:1.12.0"],\
|
||||
["@standardnotes/common", "workspace:packages/common"],\
|
||||
["@standardnotes/features", "npm:1.54.0"],\
|
||||
["@standardnotes/security", "workspace:packages/security"],\
|
||||
["reflect-metadata", "npm:0.1.13"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}]\
|
||||
]],\
|
||||
["@standardnotes/scheduler-server", [\
|
||||
@@ -2950,7 +2985,7 @@ const RAW_RUNTIME_STATE =
|
||||
["@types/node", "npm:18.0.3"],\
|
||||
["@typescript-eslint/eslint-plugin", "virtual:04783e12400851b8a3d76e71495851cc94959db6e62f04cb0a31190080629440b182d8c8eb4d7f2b04e281912f2783a5fd4d2c3c6ab68d38b7097246c93f4c19#npm:5.40.1"],\
|
||||
["aws-sdk", "npm:2.1234.0"],\
|
||||
["dayjs", "npm:1.11.5"],\
|
||||
["dayjs", "npm:1.11.6"],\
|
||||
["dotenv", "npm:16.0.1"],\
|
||||
["eslint", "npm:8.25.0"],\
|
||||
["eslint-plugin-prettier", "virtual:04783e12400851b8a3d76e71495851cc94959db6e62f04cb0a31190080629440b182d8c8eb4d7f2b04e281912f2783a5fd4d2c3c6ab68d38b7097246c93f4c19#npm:4.2.1"],\
|
||||
@@ -3123,7 +3158,7 @@ const RAW_RUNTIME_STATE =
|
||||
["@types/jest", "npm:29.1.1"],\
|
||||
["@types/microtime", "npm:2.1.0"],\
|
||||
["@typescript-eslint/eslint-plugin", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:5.30.5"],\
|
||||
["dayjs", "npm:1.11.5"],\
|
||||
["dayjs", "npm:1.11.6"],\
|
||||
["eslint-plugin-prettier", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:4.2.1"],\
|
||||
["jest", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:29.1.2"],\
|
||||
["microtime", "npm:3.1.1"],\
|
||||
@@ -3145,6 +3180,17 @@ const RAW_RUNTIME_STATE =
|
||||
["reflect-metadata", "npm:0.1.13"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}],\
|
||||
["npm:1.11.0", {\
|
||||
"packageLocation": "./.yarn/cache/@standardnotes-utils-npm-1.11.0-afbc24024c-9e7d9c1257.zip/node_modules/@standardnotes/utils/",\
|
||||
"packageDependencies": [\
|
||||
["@standardnotes/utils", "npm:1.11.0"],\
|
||||
["@standardnotes/common", "workspace:packages/common"],\
|
||||
["dompurify", "npm:2.4.0"],\
|
||||
["lodash", "npm:4.17.21"],\
|
||||
["reflect-metadata", "npm:0.1.13"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}]\
|
||||
]],\
|
||||
["@standardnotes/websockets-server", [\
|
||||
@@ -3154,7 +3200,7 @@ const RAW_RUNTIME_STATE =
|
||||
["@standardnotes/websockets-server", "workspace:packages/websockets"],\
|
||||
["@newrelic/winston-enricher", "virtual:04783e12400851b8a3d76e71495851cc94959db6e62f04cb0a31190080629440b182d8c8eb4d7f2b04e281912f2783a5fd4d2c3c6ab68d38b7097246c93f4c19#npm:4.0.0"],\
|
||||
["@sentry/node", "npm:7.5.0"],\
|
||||
["@standardnotes/api", "npm:1.16.3"],\
|
||||
["@standardnotes/api", "npm:1.19.0"],\
|
||||
["@standardnotes/common", "workspace:packages/common"],\
|
||||
["@standardnotes/domain-events", "workspace:packages/domain-events"],\
|
||||
["@standardnotes/domain-events-infra", "workspace:packages/domain-events-infra"],\
|
||||
@@ -3194,7 +3240,7 @@ const RAW_RUNTIME_STATE =
|
||||
["@standardnotes/workspace-server", "workspace:packages/workspace"],\
|
||||
["@newrelic/winston-enricher", "virtual:04783e12400851b8a3d76e71495851cc94959db6e62f04cb0a31190080629440b182d8c8eb4d7f2b04e281912f2783a5fd4d2c3c6ab68d38b7097246c93f4c19#npm:4.0.0"],\
|
||||
["@sentry/node", "npm:7.5.0"],\
|
||||
["@standardnotes/api", "npm:1.16.3"],\
|
||||
["@standardnotes/api", "npm:1.19.0"],\
|
||||
["@standardnotes/common", "workspace:packages/common"],\
|
||||
["@standardnotes/domain-events", "workspace:packages/domain-events"],\
|
||||
["@standardnotes/domain-events-infra", "workspace:packages/domain-events-infra"],\
|
||||
@@ -5856,10 +5902,10 @@ const RAW_RUNTIME_STATE =
|
||||
}]\
|
||||
]],\
|
||||
["dayjs", [\
|
||||
["npm:1.11.5", {\
|
||||
"packageLocation": "./.yarn/cache/dayjs-npm-1.11.5-a825142dc5-ea78d43de0.zip/node_modules/dayjs/",\
|
||||
["npm:1.11.6", {\
|
||||
"packageLocation": "./.yarn/cache/dayjs-npm-1.11.6-44daf311a9-f59ea45f24.zip/node_modules/dayjs/",\
|
||||
"packageDependencies": [\
|
||||
["dayjs", "npm:1.11.5"]\
|
||||
["dayjs", "npm:1.11.6"]\
|
||||
],\
|
||||
"linkType": "HARD"\
|
||||
}]\
|
||||
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
+1
-1
@@ -14,7 +14,7 @@
|
||||
"lint": "yarn workspaces foreach -p -j 10 --verbose run lint",
|
||||
"lint:auth": "yarn workspace @standardnotes/auth-server lint",
|
||||
"lint:scheduler": "yarn workspace @standardnotes/scheduler-server lint",
|
||||
"lint:syncing-server": "yarn workspace @standardnotes/syncing-server lint",
|
||||
"lint:syncing-server-js": "yarn workspace @standardnotes/syncing-server lint",
|
||||
"lint:files": "yarn workspace @standardnotes/files-server lint",
|
||||
"lint:api-gateway": "yarn workspace @standardnotes/api-gateway lint",
|
||||
"lint:event-store": "yarn workspace @standardnotes/event-store lint",
|
||||
|
||||
@@ -3,6 +3,48 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.34.1](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.34.0...@standardnotes/api-gateway@1.34.1) (2022-11-03)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||
|
||||
# [1.34.0](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.33.6...@standardnotes/api-gateway@1.34.0) (2022-11-02)
|
||||
|
||||
### Features
|
||||
|
||||
* **auth:** add processing user requests ([2255f85](https://github.com/standardnotes/api-gateway/commit/2255f856f928e855ac94f8aca4e1fb81047f58f7))
|
||||
|
||||
## [1.33.6](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.33.5...@standardnotes/api-gateway@1.33.6) (2022-11-02)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||
|
||||
## [1.33.5](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.33.4...@standardnotes/api-gateway@1.33.5) (2022-11-01)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||
|
||||
## [1.33.4](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.33.3...@standardnotes/api-gateway@1.33.4) (2022-10-31)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||
|
||||
## [1.33.3](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.33.2...@standardnotes/api-gateway@1.33.3) (2022-10-31)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||
|
||||
## [1.33.2](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.33.1...@standardnotes/api-gateway@1.33.2) (2022-10-26)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||
|
||||
## [1.33.1](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.33.0...@standardnotes/api-gateway@1.33.1) (2022-10-24)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **api-gateway:** remove invite declining endpoint ([23b05ca](https://github.com/standardnotes/api-gateway/commit/23b05caea2197e36fa446ffb3c9a5e7598224f3e))
|
||||
|
||||
# [1.33.0](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.32.0...@standardnotes/api-gateway@1.33.0) (2022-10-24)
|
||||
|
||||
### Features
|
||||
|
||||
* **auth:** change accepting invitations to be an authorized endpoint ([771a555](https://github.com/standardnotes/api-gateway/commit/771a555b4f33452311cd5bf0b8cfcbc4f2f1c4dd))
|
||||
|
||||
# [1.32.0](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.31.2...@standardnotes/api-gateway@1.32.0) (2022-10-19)
|
||||
|
||||
### Features
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/api-gateway",
|
||||
"version": "1.32.0",
|
||||
"version": "1.34.1",
|
||||
"engines": {
|
||||
"node": ">=16.0.0 <17.0.0"
|
||||
},
|
||||
|
||||
@@ -26,17 +26,8 @@ export class SubscriptionInvitesController extends BaseHttpController {
|
||||
await this.httpService.callAuthServer(request, response, `subscription-invites/${request.params.inviteUuid}`)
|
||||
}
|
||||
|
||||
@httpGet('/:inviteUuid/accept')
|
||||
@httpPost('/:inviteUuid/accept', TYPES.AuthMiddleware)
|
||||
async acceptInvite(request: Request, response: Response): Promise<void> {
|
||||
await this.httpService.callAuthServer(request, response, `subscription-invites/${request.params.inviteUuid}/accept`)
|
||||
}
|
||||
|
||||
@httpGet('/:inviteUuid/decline')
|
||||
async declineInvite(request: Request, response: Response): Promise<void> {
|
||||
await this.httpService.callAuthServer(
|
||||
request,
|
||||
response,
|
||||
`subscription-invites/${request.params.inviteUuid}/decline`,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,4 +147,9 @@ export class UsersController extends BaseHttpController {
|
||||
async deleteUser(request: Request, response: Response): Promise<void> {
|
||||
await this.httpService.callPaymentsServer(request, response, 'api/account', request.body)
|
||||
}
|
||||
|
||||
@httpPost('/:userUuid/requests', TYPES.AuthMiddleware)
|
||||
async submitRequest(request: Request, response: Response): Promise<void> {
|
||||
await this.httpService.callAuthServer(request, response, `users/${request.params.userUuid}/requests`, request.body)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,66 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.48.2](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.48.1...@standardnotes/auth-server@1.48.2) (2022-11-03)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/auth-server
|
||||
|
||||
## [1.48.1](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.48.0...@standardnotes/auth-server@1.48.1) (2022-11-02)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **auth:** controller name ([5b0d9dd](https://github.com/standardnotes/server/commit/5b0d9dd3949d4da9d5ac3ca86a0e54ead2ce730d))
|
||||
|
||||
# [1.48.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.47.7...@standardnotes/auth-server@1.48.0) (2022-11-02)
|
||||
|
||||
### Features
|
||||
|
||||
* **auth:** add processing user requests ([2255f85](https://github.com/standardnotes/server/commit/2255f856f928e855ac94f8aca4e1fb81047f58f7))
|
||||
|
||||
## [1.47.7](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.47.6...@standardnotes/auth-server@1.47.7) (2022-11-02)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/auth-server
|
||||
|
||||
## [1.47.6](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.47.5...@standardnotes/auth-server@1.47.6) (2022-11-01)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/auth-server
|
||||
|
||||
## [1.47.5](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.47.4...@standardnotes/auth-server@1.47.5) (2022-11-01)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* force utf8mb4 charset on typeorm ([5160cc3](https://github.com/standardnotes/server/commit/5160cc36ddc9e30551d5ad40a9e210d87091eec3))
|
||||
|
||||
## [1.47.4](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.47.3...@standardnotes/auth-server@1.47.4) (2022-10-31)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/auth-server
|
||||
|
||||
## [1.47.3](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.47.2...@standardnotes/auth-server@1.47.3) (2022-10-31)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/auth-server
|
||||
|
||||
## [1.47.2](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.47.1...@standardnotes/auth-server@1.47.2) (2022-10-26)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/auth-server
|
||||
|
||||
## [1.47.1](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.47.0...@standardnotes/auth-server@1.47.1) (2022-10-24)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **auth:** accepting shared subscription for inviters with multiple subscriptions ([f8433c1](https://github.com/standardnotes/server/commit/f8433c106fe593f9132558d080b88d08cf9cfe86))
|
||||
|
||||
# [1.47.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.46.1...@standardnotes/auth-server@1.47.0) (2022-10-24)
|
||||
|
||||
### Features
|
||||
|
||||
* **auth:** change accepting invitations to be an authorized endpoint ([771a555](https://github.com/standardnotes/server/commit/771a555b4f33452311cd5bf0b8cfcbc4f2f1c4dd))
|
||||
|
||||
## [1.46.1](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.46.0...@standardnotes/auth-server@1.46.1) (2022-10-20)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **auth:** additional response message to accepting invitation ([126e6a3](https://github.com/standardnotes/server/commit/126e6a3c2f99c8e3ec994d8ce50d008b0f0ec43f))
|
||||
|
||||
# [1.46.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.45.0...@standardnotes/auth-server@1.46.0) (2022-10-19)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -20,6 +20,7 @@ import '../src/Controller/SubscriptionSettingsController'
|
||||
|
||||
import '../src/Infra/InversifyExpressUtils/InversifyExpressAuthController'
|
||||
import '../src/Infra/InversifyExpressUtils/InversifyExpressSubscriptionInvitesController'
|
||||
import '../src/Infra/InversifyExpressUtils/InversifyExpressUserRequestsController'
|
||||
import '../src/Infra/InversifyExpressUtils/InversifyExpressWebSocketsController'
|
||||
|
||||
import * as cors from 'cors'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/auth-server",
|
||||
"version": "1.46.0",
|
||||
"version": "1.48.2",
|
||||
"engines": {
|
||||
"node": ">=16.0.0 <17.0.0"
|
||||
},
|
||||
@@ -33,7 +33,7 @@
|
||||
"@newrelic/winston-enricher": "^4.0.0",
|
||||
"@sentry/node": "^7.3.0",
|
||||
"@standardnotes/analytics": "workspace:*",
|
||||
"@standardnotes/api": "^1.16.0",
|
||||
"@standardnotes/api": "^1.19.0",
|
||||
"@standardnotes/common": "workspace:*",
|
||||
"@standardnotes/domain-events": "workspace:*",
|
||||
"@standardnotes/domain-events-infra": "workspace:*",
|
||||
@@ -49,7 +49,7 @@
|
||||
"axios": "^0.27.2",
|
||||
"bcryptjs": "2.4.3",
|
||||
"cors": "2.8.5",
|
||||
"dayjs": "^1.11.3",
|
||||
"dayjs": "^1.11.6",
|
||||
"dotenv": "^16.0.1",
|
||||
"express": "^4.18.1",
|
||||
"inversify": "^6.0.1",
|
||||
|
||||
@@ -203,6 +203,8 @@ import { PaymentSuccessEventHandler } from '../Domain/Handler/PaymentSuccessEven
|
||||
import { RefundProcessedEventHandler } from '../Domain/Handler/RefundProcessedEventHandler'
|
||||
import { SubscriptionInvitesController } from '../Controller/SubscriptionInvitesController'
|
||||
import { CreateCrossServiceToken } from '../Domain/UseCase/CreateCrossServiceToken/CreateCrossServiceToken'
|
||||
import { ProcessUserRequest } from '../Domain/UseCase/ProcessUserRequest/ProcessUserRequest'
|
||||
import { UserRequestsController } from '../Controller/UserRequestsController'
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const newrelicFormatter = require('@newrelic/winston-enricher')
|
||||
@@ -266,6 +268,7 @@ export class ContainerConfigLoader {
|
||||
// Controller
|
||||
container.bind<AuthController>(TYPES.AuthController).to(AuthController)
|
||||
container.bind<SubscriptionInvitesController>(TYPES.SubscriptionInvitesController).to(SubscriptionInvitesController)
|
||||
container.bind<UserRequestsController>(TYPES.UserRequestsController).to(UserRequestsController)
|
||||
|
||||
// Repositories
|
||||
container.bind<SessionRepositoryInterface>(TYPES.SessionRepository).to(MySQLSessionRepository)
|
||||
@@ -438,6 +441,7 @@ export class ContainerConfigLoader {
|
||||
container.bind<GetUserAnalyticsId>(TYPES.GetUserAnalyticsId).to(GetUserAnalyticsId)
|
||||
container.bind<VerifyPredicate>(TYPES.VerifyPredicate).to(VerifyPredicate)
|
||||
container.bind<CreateCrossServiceToken>(TYPES.CreateCrossServiceToken).to(CreateCrossServiceToken)
|
||||
container.bind<ProcessUserRequest>(TYPES.ProcessUserRequest).to(ProcessUserRequest)
|
||||
|
||||
// Handlers
|
||||
container.bind<UserRegisteredEventHandler>(TYPES.UserRegisteredEventHandler).to(UserRegisteredEventHandler)
|
||||
|
||||
@@ -22,6 +22,7 @@ const maxQueryExecutionTime = env.get('DB_MAX_QUERY_EXECUTION_TIME', true)
|
||||
|
||||
export const AppDataSource = new DataSource({
|
||||
type: 'mysql',
|
||||
charset: 'utf8mb4',
|
||||
supportBigNumbers: true,
|
||||
bigNumberStrings: false,
|
||||
maxQueryExecutionTime,
|
||||
|
||||
@@ -6,6 +6,7 @@ const TYPES = {
|
||||
// Controller
|
||||
AuthController: Symbol.for('AuthController'),
|
||||
SubscriptionInvitesController: Symbol.for('SubscriptionInvitesController'),
|
||||
UserRequestsController: Symbol.for('UserRequestsController'),
|
||||
// Repositories
|
||||
UserRepository: Symbol.for('UserRepository'),
|
||||
SessionRepository: Symbol.for('SessionRepository'),
|
||||
@@ -121,6 +122,7 @@ const TYPES = {
|
||||
GetUserAnalyticsId: Symbol.for('GetUserAnalyticsId'),
|
||||
VerifyPredicate: Symbol.for('VerifyPredicate'),
|
||||
CreateCrossServiceToken: Symbol.for('CreateCrossServiceToken'),
|
||||
ProcessUserRequest: Symbol.for('ProcessUserRequest'),
|
||||
// Handlers
|
||||
UserRegisteredEventHandler: Symbol.for('UserRegisteredEventHandler'),
|
||||
AccountDeletionRequestedEventHandler: Symbol.for('AccountDeletionRequestedEventHandler'),
|
||||
|
||||
@@ -109,4 +109,15 @@ describe('AuthController', () => {
|
||||
|
||||
expect(response.status).toEqual(400)
|
||||
})
|
||||
|
||||
it('should throw error on the delete user method as it is still a part of the payments server', async () => {
|
||||
let caughtError = null
|
||||
try {
|
||||
await createController().deleteAccount({ userUuid: '1-2-3' })
|
||||
} catch (error) {
|
||||
caughtError = error
|
||||
}
|
||||
|
||||
expect(caughtError).not.toBeNull()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -2,6 +2,7 @@ import { inject, injectable } from 'inversify'
|
||||
import { DomainEventPublisherInterface } from '@standardnotes/domain-events'
|
||||
import {
|
||||
HttpStatusCode,
|
||||
UserDeletionResponse,
|
||||
UserRegistrationRequestParams,
|
||||
UserRegistrationResponse,
|
||||
UserServerInterface,
|
||||
@@ -12,6 +13,7 @@ import { ClearLoginAttempts } from '../Domain/UseCase/ClearLoginAttempts'
|
||||
import { Register } from '../Domain/UseCase/Register'
|
||||
import { DomainEventFactoryInterface } from '../Domain/Event/DomainEventFactoryInterface'
|
||||
import { ProtocolVersion } from '@standardnotes/common'
|
||||
import { UserDeletionRequestParams } from '@standardnotes/api/dist/Domain/Request/User/UserDeletionRequestParams'
|
||||
|
||||
@injectable()
|
||||
export class AuthController implements UserServerInterface {
|
||||
@@ -22,6 +24,10 @@ export class AuthController implements UserServerInterface {
|
||||
@inject(TYPES.DomainEventFactory) private domainEventFactory: DomainEventFactoryInterface,
|
||||
) {}
|
||||
|
||||
async deleteAccount(_params: UserDeletionRequestParams): Promise<UserDeletionResponse> {
|
||||
throw new Error('This method is implemented on the payments server.')
|
||||
}
|
||||
|
||||
async register(params: UserRegistrationRequestParams): Promise<UserRegistrationResponse> {
|
||||
if (!params.email || !params.password) {
|
||||
return {
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
import 'reflect-metadata'
|
||||
|
||||
import { UserRequestType } from '@standardnotes/common'
|
||||
|
||||
import { ProcessUserRequest } from '../Domain/UseCase/ProcessUserRequest/ProcessUserRequest'
|
||||
|
||||
import { UserRequestsController } from './UserRequestsController'
|
||||
|
||||
describe('UserRequestsController', () => {
|
||||
let processUserRequest: ProcessUserRequest
|
||||
|
||||
const createController = () => new UserRequestsController(processUserRequest)
|
||||
|
||||
beforeEach(() => {
|
||||
processUserRequest = {} as jest.Mocked<ProcessUserRequest>
|
||||
processUserRequest.execute = jest.fn().mockReturnValue({ success: true })
|
||||
})
|
||||
|
||||
it('should process user request', async () => {
|
||||
expect(
|
||||
await createController().submitUserRequest({
|
||||
userUuid: '1-2-3',
|
||||
requestType: UserRequestType.ExitDiscount,
|
||||
}),
|
||||
).toEqual({
|
||||
status: 200,
|
||||
data: { success: true },
|
||||
})
|
||||
})
|
||||
|
||||
it('should not process user request', async () => {
|
||||
processUserRequest.execute = jest.fn().mockReturnValue({ success: false })
|
||||
expect(
|
||||
await createController().submitUserRequest({
|
||||
userUuid: '1-2-3',
|
||||
requestType: UserRequestType.ExitDiscount,
|
||||
}),
|
||||
).toEqual({
|
||||
status: 400,
|
||||
data: { success: false },
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,34 @@
|
||||
import {
|
||||
HttpStatusCode,
|
||||
UserRequestRequestParams,
|
||||
UserRequestResponse,
|
||||
UserRequestServerInterface,
|
||||
} from '@standardnotes/api'
|
||||
import { inject, injectable } from 'inversify'
|
||||
import TYPES from '../Bootstrap/Types'
|
||||
import { ProcessUserRequest } from '../Domain/UseCase/ProcessUserRequest/ProcessUserRequest'
|
||||
|
||||
@injectable()
|
||||
export class UserRequestsController implements UserRequestServerInterface {
|
||||
constructor(@inject(TYPES.ProcessUserRequest) private processUserRequest: ProcessUserRequest) {}
|
||||
|
||||
async submitUserRequest(params: UserRequestRequestParams): Promise<UserRequestResponse> {
|
||||
const result = await this.processUserRequest.execute({
|
||||
requestType: params.requestType,
|
||||
userEmail: params.userEmail as string,
|
||||
userUuid: params.userUuid,
|
||||
})
|
||||
|
||||
if (!result.success) {
|
||||
return {
|
||||
status: HttpStatusCode.BadRequest,
|
||||
data: result,
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
status: HttpStatusCode.Success,
|
||||
data: result,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,29 @@ describe('DomainEventFactory', () => {
|
||||
timer.getUTCDate = jest.fn().mockReturnValue(new Date(1))
|
||||
})
|
||||
|
||||
it('should create a EXIT_DISCOUNT_APPLY_REQUESTED event', () => {
|
||||
expect(
|
||||
createFactory().createExitDiscountApplyRequestedEvent({
|
||||
userEmail: 'test@test.te',
|
||||
discountCode: 'exit-20',
|
||||
}),
|
||||
).toEqual({
|
||||
createdAt: expect.any(Date),
|
||||
meta: {
|
||||
correlation: {
|
||||
userIdentifier: 'test@test.te',
|
||||
userIdentifierType: 'email',
|
||||
},
|
||||
origin: 'auth',
|
||||
},
|
||||
payload: {
|
||||
userEmail: 'test@test.te',
|
||||
discountCode: 'exit-20',
|
||||
},
|
||||
type: 'EXIT_DISCOUNT_APPLY_REQUESTED',
|
||||
})
|
||||
})
|
||||
|
||||
it('should create a WEB_SOCKET_MESSAGE_REQUESTED event', () => {
|
||||
expect(
|
||||
createFactory().createWebSocketMessageRequestedEvent({
|
||||
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
DomainEventService,
|
||||
EmailMessageRequestedEvent,
|
||||
WebSocketMessageRequestedEvent,
|
||||
ExitDiscountApplyRequestedEvent,
|
||||
} from '@standardnotes/domain-events'
|
||||
import { Predicate, PredicateVerificationResult } from '@standardnotes/predicates'
|
||||
import { TimerInterface } from '@standardnotes/time'
|
||||
@@ -28,6 +29,24 @@ import { DomainEventFactoryInterface } from './DomainEventFactoryInterface'
|
||||
export class DomainEventFactory implements DomainEventFactoryInterface {
|
||||
constructor(@inject(TYPES.Timer) private timer: TimerInterface) {}
|
||||
|
||||
createExitDiscountApplyRequestedEvent(dto: {
|
||||
userEmail: string
|
||||
discountCode: string
|
||||
}): ExitDiscountApplyRequestedEvent {
|
||||
return {
|
||||
type: 'EXIT_DISCOUNT_APPLY_REQUESTED',
|
||||
createdAt: this.timer.getUTCDate(),
|
||||
meta: {
|
||||
correlation: {
|
||||
userIdentifier: dto.userEmail,
|
||||
userIdentifierType: 'email',
|
||||
},
|
||||
origin: DomainEventService.Auth,
|
||||
},
|
||||
payload: dto,
|
||||
}
|
||||
}
|
||||
|
||||
createWebSocketMessageRequestedEvent(dto: { userUuid: Uuid; message: JSONString }): WebSocketMessageRequestedEvent {
|
||||
return {
|
||||
type: 'WEB_SOCKET_MESSAGE_REQUESTED',
|
||||
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
PredicateVerifiedEvent,
|
||||
EmailMessageRequestedEvent,
|
||||
WebSocketMessageRequestedEvent,
|
||||
ExitDiscountApplyRequestedEvent,
|
||||
} from '@standardnotes/domain-events'
|
||||
import { InviteeIdentifierType } from '../SharedSubscription/InviteeIdentifierType'
|
||||
|
||||
@@ -83,4 +84,8 @@ export interface DomainEventFactoryInterface {
|
||||
predicate: Predicate
|
||||
predicateVerificationResult: PredicateVerificationResult
|
||||
}): PredicateVerifiedEvent
|
||||
createExitDiscountApplyRequestedEvent(dto: {
|
||||
userEmail: string
|
||||
discountCode: string
|
||||
}): ExitDiscountApplyRequestedEvent
|
||||
}
|
||||
|
||||
+70
@@ -108,6 +108,47 @@ describe('AcceptSharedSubscriptionInvitation', () => {
|
||||
)
|
||||
})
|
||||
|
||||
it('should create a shared subscription upon accepting the invitation if inviter has a second subscription', async () => {
|
||||
const inviterSubscription1 = { endsAt: 1, planName: SubscriptionName.PlusPlan } as jest.Mocked<UserSubscription>
|
||||
const inviterSubscription2 = { endsAt: 5, planName: SubscriptionName.PlusPlan } as jest.Mocked<UserSubscription>
|
||||
|
||||
timer.getTimestampInMicroseconds = jest.fn().mockReturnValue(3)
|
||||
|
||||
userSubscriptionRepository.findBySubscriptionIdAndType = jest
|
||||
.fn()
|
||||
.mockReturnValue([inviterSubscription1, inviterSubscription2])
|
||||
|
||||
expect(
|
||||
await createUseCase().execute({
|
||||
sharedSubscriptionInvitationUuid: '1-2-3',
|
||||
}),
|
||||
).toEqual({
|
||||
success: true,
|
||||
})
|
||||
|
||||
expect(sharedSubscriptionInvitationRepository.save).toHaveBeenCalledWith({
|
||||
status: 'accepted',
|
||||
subscriptionId: 3,
|
||||
updatedAt: 3,
|
||||
})
|
||||
expect(userSubscriptionRepository.save).toHaveBeenCalledWith({
|
||||
cancelled: false,
|
||||
createdAt: 3,
|
||||
endsAt: 5,
|
||||
planName: 'PLUS_PLAN',
|
||||
subscriptionId: 3,
|
||||
subscriptionType: 'shared',
|
||||
updatedAt: 3,
|
||||
user: Promise.resolve(invitee),
|
||||
})
|
||||
expect(roleService.addUserRole).toHaveBeenCalledWith(invitee, 'PLUS_PLAN')
|
||||
expect(subscriptionSettingService.applyDefaultSubscriptionSettingsForSubscription).toHaveBeenCalledWith(
|
||||
inviteeSubscription,
|
||||
'PLUS_PLAN',
|
||||
'123',
|
||||
)
|
||||
})
|
||||
|
||||
it('should not create a shared subscription if invitiation is not found', async () => {
|
||||
sharedSubscriptionInvitationRepository.findOneByUuidAndStatus = jest.fn().mockReturnValue(null)
|
||||
expect(
|
||||
@@ -116,6 +157,7 @@ describe('AcceptSharedSubscriptionInvitation', () => {
|
||||
}),
|
||||
).toEqual({
|
||||
success: false,
|
||||
message: 'Could not find the subscription invitation. It may have been already accepted or declined.',
|
||||
})
|
||||
|
||||
expect(sharedSubscriptionInvitationRepository.save).not.toHaveBeenCalled()
|
||||
@@ -132,6 +174,8 @@ describe('AcceptSharedSubscriptionInvitation', () => {
|
||||
}),
|
||||
).toEqual({
|
||||
success: false,
|
||||
message:
|
||||
'Could not find the invitee in our user database. Please first register an account before accepting the invitation.',
|
||||
})
|
||||
|
||||
expect(sharedSubscriptionInvitationRepository.save).not.toHaveBeenCalled()
|
||||
@@ -148,6 +192,32 @@ describe('AcceptSharedSubscriptionInvitation', () => {
|
||||
}),
|
||||
).toEqual({
|
||||
success: false,
|
||||
message: 'The person that invited you does not have a running subscription with Standard Notes anymore.',
|
||||
})
|
||||
|
||||
expect(sharedSubscriptionInvitationRepository.save).not.toHaveBeenCalled()
|
||||
expect(userSubscriptionRepository.save).not.toHaveBeenCalled()
|
||||
expect(roleService.addUserRole).not.toHaveBeenCalled()
|
||||
expect(subscriptionSettingService.applyDefaultSubscriptionSettingsForSubscription).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should not create a shared subscription if inviter subscriptions are not active', async () => {
|
||||
const inviterSubscription1 = { endsAt: 1, planName: SubscriptionName.PlusPlan } as jest.Mocked<UserSubscription>
|
||||
const inviterSubscription2 = { endsAt: 2, planName: SubscriptionName.PlusPlan } as jest.Mocked<UserSubscription>
|
||||
|
||||
timer.getTimestampInMicroseconds = jest.fn().mockReturnValue(3)
|
||||
|
||||
userSubscriptionRepository.findBySubscriptionIdAndType = jest
|
||||
.fn()
|
||||
.mockReturnValue([inviterSubscription1, inviterSubscription2])
|
||||
|
||||
expect(
|
||||
await createUseCase().execute({
|
||||
sharedSubscriptionInvitationUuid: '1-2-3',
|
||||
}),
|
||||
).toEqual({
|
||||
success: false,
|
||||
message: 'The person that invited you does not have a running subscription with Standard Notes anymore.',
|
||||
})
|
||||
|
||||
expect(sharedSubscriptionInvitationRepository.save).not.toHaveBeenCalled()
|
||||
|
||||
+10
-2
@@ -37,6 +37,7 @@ export class AcceptSharedSubscriptionInvitation implements UseCaseInterface {
|
||||
if (sharedSubscriptionInvitation === null) {
|
||||
return {
|
||||
success: false,
|
||||
message: 'Could not find the subscription invitation. It may have been already accepted or declined.',
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,6 +45,8 @@ export class AcceptSharedSubscriptionInvitation implements UseCaseInterface {
|
||||
if (invitee === null) {
|
||||
return {
|
||||
success: false,
|
||||
message:
|
||||
'Could not find the invitee in our user database. Please first register an account before accepting the invitation.',
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,12 +54,17 @@ export class AcceptSharedSubscriptionInvitation implements UseCaseInterface {
|
||||
sharedSubscriptionInvitation.subscriptionId,
|
||||
UserSubscriptionType.Regular,
|
||||
)
|
||||
if (inviterUserSubscriptions.length !== 1) {
|
||||
const timestamp = this.timer.getTimestampInMicroseconds()
|
||||
const activeUserSubscriptions = inviterUserSubscriptions.filter((userSubscription: UserSubscription) => {
|
||||
return userSubscription.endsAt >= timestamp
|
||||
})
|
||||
if (activeUserSubscriptions.length === 0) {
|
||||
return {
|
||||
success: false,
|
||||
message: 'The person that invited you does not have a running subscription with Standard Notes anymore.',
|
||||
}
|
||||
}
|
||||
const inviterUserSubscription = inviterUserSubscriptions[0]
|
||||
const inviterUserSubscription = activeUserSubscriptions[0]
|
||||
|
||||
sharedSubscriptionInvitation.status = InvitationStatus.Accepted
|
||||
sharedSubscriptionInvitation.updatedAt = this.timer.getTimestampInMicroseconds()
|
||||
|
||||
+1
-3
@@ -1,3 +1 @@
|
||||
export type AcceptSharedSubscriptionInvitationResponse = {
|
||||
success: boolean
|
||||
}
|
||||
export type AcceptSharedSubscriptionInvitationResponse = { success: true } | { success: false; message: string }
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
import 'reflect-metadata'
|
||||
|
||||
import { DomainEventPublisherInterface, ExitDiscountApplyRequestedEvent } from '@standardnotes/domain-events'
|
||||
import { UserRequestType } from '@standardnotes/common'
|
||||
|
||||
import { DomainEventFactoryInterface } from '../../Event/DomainEventFactoryInterface'
|
||||
import { UserSubscription } from '../../Subscription/UserSubscription'
|
||||
import { UserSubscriptionRepositoryInterface } from '../../Subscription/UserSubscriptionRepositoryInterface'
|
||||
|
||||
import { ProcessUserRequest } from './ProcessUserRequest'
|
||||
|
||||
describe('ProcessUserRequest', () => {
|
||||
let userSubscriptionRepository: UserSubscriptionRepositoryInterface
|
||||
let domainEventFactory: DomainEventFactoryInterface
|
||||
let domainEventPublisher: DomainEventPublisherInterface
|
||||
|
||||
const createUseCase = () =>
|
||||
new ProcessUserRequest(userSubscriptionRepository, domainEventFactory, domainEventPublisher)
|
||||
|
||||
beforeEach(() => {
|
||||
userSubscriptionRepository = {} as jest.Mocked<UserSubscriptionRepositoryInterface>
|
||||
userSubscriptionRepository.findOneByUserUuid = jest.fn().mockReturnValue({
|
||||
cancelled: true,
|
||||
} as jest.Mocked<UserSubscription>)
|
||||
|
||||
domainEventFactory = {} as jest.Mocked<DomainEventFactoryInterface>
|
||||
domainEventFactory.createExitDiscountApplyRequestedEvent = jest
|
||||
.fn()
|
||||
.mockReturnValue({} as jest.Mocked<ExitDiscountApplyRequestedEvent>)
|
||||
|
||||
domainEventPublisher = {} as jest.Mocked<DomainEventPublisherInterface>
|
||||
domainEventPublisher.publish = jest.fn()
|
||||
})
|
||||
|
||||
it('should not process unsupported requests', async () => {
|
||||
expect(
|
||||
await createUseCase().execute({
|
||||
userEmail: 'test@test.te',
|
||||
userUuid: '1-2-3',
|
||||
requestType: 'foobar' as UserRequestType,
|
||||
}),
|
||||
).toEqual({
|
||||
success: false,
|
||||
})
|
||||
|
||||
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should not process uncancelled subscriptions', async () => {
|
||||
userSubscriptionRepository.findOneByUserUuid = jest.fn().mockReturnValue({} as jest.Mocked<UserSubscription>)
|
||||
|
||||
expect(
|
||||
await createUseCase().execute({
|
||||
userEmail: 'test@test.te',
|
||||
userUuid: '1-2-3',
|
||||
requestType: UserRequestType.ExitDiscount,
|
||||
}),
|
||||
).toEqual({
|
||||
success: false,
|
||||
})
|
||||
|
||||
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should not process non existing subscriptions', async () => {
|
||||
userSubscriptionRepository.findOneByUserUuid = jest.fn().mockReturnValue(null)
|
||||
|
||||
expect(
|
||||
await createUseCase().execute({
|
||||
userEmail: 'test@test.te',
|
||||
userUuid: '1-2-3',
|
||||
requestType: UserRequestType.ExitDiscount,
|
||||
}),
|
||||
).toEqual({
|
||||
success: false,
|
||||
})
|
||||
|
||||
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should publish an exit discount apply requested event', async () => {
|
||||
expect(
|
||||
await createUseCase().execute({
|
||||
userEmail: 'test@test.te',
|
||||
userUuid: '1-2-3',
|
||||
requestType: UserRequestType.ExitDiscount,
|
||||
}),
|
||||
).toEqual({
|
||||
success: true,
|
||||
})
|
||||
|
||||
expect(domainEventPublisher.publish).toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,46 @@
|
||||
import { DomainEventPublisherInterface } from '@standardnotes/domain-events'
|
||||
import { inject, injectable } from 'inversify'
|
||||
import { UserRequestType } from '@standardnotes/common'
|
||||
|
||||
import TYPES from '../../../Bootstrap/Types'
|
||||
import { DomainEventFactoryInterface } from '../../Event/DomainEventFactoryInterface'
|
||||
import { UserSubscriptionRepositoryInterface } from '../../Subscription/UserSubscriptionRepositoryInterface'
|
||||
|
||||
import { UseCaseInterface } from '../UseCaseInterface'
|
||||
import { ProcessUserRequestDTO } from './ProcessUserRequestDTO'
|
||||
import { ProcessUserRequestResponse } from './ProcessUserRequestResponse'
|
||||
|
||||
@injectable()
|
||||
export class ProcessUserRequest implements UseCaseInterface {
|
||||
constructor(
|
||||
@inject(TYPES.UserSubscriptionRepository) private userSubscriptionRepository: UserSubscriptionRepositoryInterface,
|
||||
@inject(TYPES.DomainEventFactory) private domainEventFactory: DomainEventFactoryInterface,
|
||||
@inject(TYPES.DomainEventPublisher) private domainEventPublisher: DomainEventPublisherInterface,
|
||||
) {}
|
||||
|
||||
async execute(dto: ProcessUserRequestDTO): Promise<ProcessUserRequestResponse> {
|
||||
if (dto.requestType !== UserRequestType.ExitDiscount) {
|
||||
return {
|
||||
success: false,
|
||||
}
|
||||
}
|
||||
|
||||
const subscription = await this.userSubscriptionRepository.findOneByUserUuid(dto.userUuid)
|
||||
if (subscription === null || !subscription.cancelled) {
|
||||
return {
|
||||
success: false,
|
||||
}
|
||||
}
|
||||
|
||||
await this.domainEventPublisher.publish(
|
||||
this.domainEventFactory.createExitDiscountApplyRequestedEvent({
|
||||
userEmail: dto.userEmail,
|
||||
discountCode: 'exit-20',
|
||||
}),
|
||||
)
|
||||
|
||||
return {
|
||||
success: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
import { UserRequestType, Uuid } from '@standardnotes/common'
|
||||
|
||||
export type ProcessUserRequestDTO = {
|
||||
userUuid: Uuid
|
||||
userEmail: string
|
||||
requestType: UserRequestType
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
export type ProcessUserRequestResponse = {
|
||||
success: boolean
|
||||
}
|
||||
+1
-1
@@ -22,7 +22,7 @@ export class InversifyExpressSubscriptionInvitesController extends BaseHttpContr
|
||||
super()
|
||||
}
|
||||
|
||||
@httpGet('/:inviteUuid/accept')
|
||||
@httpPost('/:inviteUuid/accept', TYPES.ApiGatewayAuthMiddleware)
|
||||
async acceptInvite(request: Request): Promise<results.JsonResult> {
|
||||
const response = await this.subscriptionInvitesController.acceptInvite({
|
||||
api: request.query.api as ApiVersion,
|
||||
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
import { Request, Response } from 'express'
|
||||
import { inject } from 'inversify'
|
||||
import { controller, BaseHttpController, results, httpPost } from 'inversify-express-utils'
|
||||
|
||||
import TYPES from '../../Bootstrap/Types'
|
||||
import { UserRequestsController } from '../../Controller/UserRequestsController'
|
||||
|
||||
@controller('/users/:userUuid/requests')
|
||||
export class InversifyExpressUserRequestsController extends BaseHttpController {
|
||||
constructor(@inject(TYPES.UserRequestsController) private userRequestsController: UserRequestsController) {
|
||||
super()
|
||||
}
|
||||
|
||||
@httpPost('/', TYPES.ApiGatewayAuthMiddleware)
|
||||
async submitRequest(request: Request, response: Response): Promise<results.JsonResult> {
|
||||
const result = await this.userRequestsController.submitUserRequest({
|
||||
requestType: request.body.requestType,
|
||||
userUuid: response.locals.user.uuid,
|
||||
userEmail: response.locals.user.email,
|
||||
})
|
||||
|
||||
return this.json(result.data, result.status)
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,24 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [1.44.0](https://github.com/standardnotes/server/compare/@standardnotes/common@1.43.0...@standardnotes/common@1.44.0) (2022-11-03)
|
||||
|
||||
### Features
|
||||
|
||||
* **common:** add subscription cancelled email message identifier ([0c5305a](https://github.com/standardnotes/server/commit/0c5305acf62aae047caedca25de25049c37f7653))
|
||||
|
||||
# [1.43.0](https://github.com/standardnotes/server/compare/@standardnotes/common@1.42.0...@standardnotes/common@1.43.0) (2022-11-01)
|
||||
|
||||
### Features
|
||||
|
||||
* **common:** add user request type ([d4af1d7](https://github.com/standardnotes/server/commit/d4af1d743ef914228a15f15b36a15dc9b612c704))
|
||||
|
||||
# [1.42.0](https://github.com/standardnotes/server/compare/@standardnotes/common@1.41.0...@standardnotes/common@1.42.0) (2022-10-31)
|
||||
|
||||
### Features
|
||||
|
||||
* **domain-events:** add exit discount applied event ([7b797f0](https://github.com/standardnotes/server/commit/7b797f0cbabfbca4f8bf8859c613dcff38d91df3))
|
||||
|
||||
# [1.41.0](https://github.com/standardnotes/server/compare/@standardnotes/common@1.40.0...@standardnotes/common@1.41.0) (2022-10-19)
|
||||
|
||||
### Features
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/common",
|
||||
"version": "1.41.0",
|
||||
"version": "1.44.0",
|
||||
"engines": {
|
||||
"node": ">=16.0.0 <17.0.0"
|
||||
},
|
||||
|
||||
@@ -25,4 +25,6 @@ export enum EmailMessageIdentifier {
|
||||
REFUND_REQUESTED = 'REFUND_REQUESTED',
|
||||
RATE_ADJUSTMENT_NOTICE = 'RATE_ADJUSTMENT_NOTICE',
|
||||
WORKSPACE_INVITE_CREATED = 'WORKSPACE_INVITE_CREATED',
|
||||
EXIT_DISCOUNT = 'EXIT_DISCOUNT',
|
||||
SUBSCRIPTION_CANCELLED = 'SUBSCRIPTION_CANCELLED',
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
export enum UserRequestType {
|
||||
ExitDiscount = 'exit-discount',
|
||||
}
|
||||
@@ -23,6 +23,7 @@ export * from './Subscription/SubscriptionBillingFrequency'
|
||||
export * from './Subscription/SubscriptionName'
|
||||
export * from './Type/Either'
|
||||
export * from './Type/Only'
|
||||
export * from './User/UserRequestType'
|
||||
export * from './Validator/UuidValidator'
|
||||
export * from './Validator/ValidatorInterface'
|
||||
export * from './Workspace/WorkspaceAccessLevel'
|
||||
|
||||
@@ -3,6 +3,30 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.9.6](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.9.5...@standardnotes/domain-events-infra@1.9.6) (2022-11-03)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/domain-events-infra
|
||||
|
||||
## [1.9.5](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.9.4...@standardnotes/domain-events-infra@1.9.5) (2022-11-02)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/domain-events-infra
|
||||
|
||||
## [1.9.4](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.9.3...@standardnotes/domain-events-infra@1.9.4) (2022-11-01)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/domain-events-infra
|
||||
|
||||
## [1.9.3](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.9.2...@standardnotes/domain-events-infra@1.9.3) (2022-10-31)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/domain-events-infra
|
||||
|
||||
## [1.9.2](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.9.1...@standardnotes/domain-events-infra@1.9.2) (2022-10-31)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/domain-events-infra
|
||||
|
||||
## [1.9.1](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.9.0...@standardnotes/domain-events-infra@1.9.1) (2022-10-26)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/domain-events-infra
|
||||
|
||||
# [1.9.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.8.27...@standardnotes/domain-events-infra@1.9.0) (2022-10-19)
|
||||
|
||||
### Features
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/domain-events-infra",
|
||||
"version": "1.9.0",
|
||||
"version": "1.9.6",
|
||||
"engines": {
|
||||
"node": ">=16.0.0 <17.0.0"
|
||||
},
|
||||
|
||||
@@ -3,6 +3,38 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [2.73.1](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.73.0...@standardnotes/domain-events@2.73.1) (2022-11-03)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/domain-events
|
||||
|
||||
# [2.73.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.72.1...@standardnotes/domain-events@2.73.0) (2022-11-02)
|
||||
|
||||
### Features
|
||||
|
||||
* **domain-events:** add exit discount events ([59eb70c](https://github.com/standardnotes/server/commit/59eb70ce62eddd1ac8031667bc38e495e9c17bba))
|
||||
|
||||
## [2.72.1](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.72.0...@standardnotes/domain-events@2.72.1) (2022-11-01)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/domain-events
|
||||
|
||||
# [2.72.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.71.0...@standardnotes/domain-events@2.72.0) (2022-10-31)
|
||||
|
||||
### Features
|
||||
|
||||
* **domain-events:** add exit discount applied event ([7b797f0](https://github.com/standardnotes/server/commit/7b797f0cbabfbca4f8bf8859c613dcff38d91df3))
|
||||
|
||||
# [2.71.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.70.0...@standardnotes/domain-events@2.71.0) (2022-10-31)
|
||||
|
||||
### Features
|
||||
|
||||
* **domain-events:** add subscription reactivated event ([6e8481b](https://github.com/standardnotes/server/commit/6e8481bb2f271f3b9e86ca7d2ac683f1fd6f6516))
|
||||
|
||||
# [2.70.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.69.0...@standardnotes/domain-events@2.70.0) (2022-10-26)
|
||||
|
||||
### Features
|
||||
|
||||
* **domain-events:** add subscription reactivation discount requested event ([88d4d21](https://github.com/standardnotes/server/commit/88d4d211b885d63b6063b4d673280e3f4fe1cc30))
|
||||
|
||||
# [2.69.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.68.0...@standardnotes/domain-events@2.69.0) (2022-10-19)
|
||||
|
||||
### Features
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/domain-events",
|
||||
"version": "2.69.0",
|
||||
"version": "2.73.1",
|
||||
"engines": {
|
||||
"node": ">=16.0.0 <17.0.0"
|
||||
},
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
import { DomainEventInterface } from './DomainEventInterface'
|
||||
|
||||
import { ExitDiscountAppliedEventPayload } from './ExitDiscountAppliedEventPayload'
|
||||
|
||||
export interface ExitDiscountAppliedEvent extends DomainEventInterface {
|
||||
type: 'EXIT_DISCOUNT_APPLIED'
|
||||
payload: ExitDiscountAppliedEventPayload
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
export interface ExitDiscountAppliedEventPayload {
|
||||
userEmail: string
|
||||
discountRate: number
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
import { DomainEventInterface } from './DomainEventInterface'
|
||||
import { ExitDiscountApplyRequestedEventPayload } from './ExitDiscountApplyRequestedEventPayload'
|
||||
|
||||
export interface ExitDiscountApplyRequestedEvent extends DomainEventInterface {
|
||||
type: 'EXIT_DISCOUNT_APPLY_REQUESTED'
|
||||
payload: ExitDiscountApplyRequestedEventPayload
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
export interface ExitDiscountApplyRequestedEventPayload {
|
||||
userEmail: string
|
||||
discountCode: string
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
import { DomainEventInterface } from './DomainEventInterface'
|
||||
import { ExitDiscountWithdrawRequestedEventPayload } from './ExitDiscountWithdrawRequestedEventPayload'
|
||||
|
||||
export interface ExitDiscountWithdrawRequestedEvent extends DomainEventInterface {
|
||||
type: 'EXIT_DISCOUNT_WITHDRAW_REQUESTED'
|
||||
payload: ExitDiscountWithdrawRequestedEventPayload
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
export interface ExitDiscountWithdrawRequestedEventPayload {
|
||||
userEmail: string
|
||||
discountCode: string
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import { DomainEventInterface } from './DomainEventInterface'
|
||||
|
||||
import { SubscriptionReactivatedEventPayload } from './SubscriptionReactivatedEventPayload'
|
||||
|
||||
export interface SubscriptionReactivatedEvent extends DomainEventInterface {
|
||||
type: 'SUBSCRIPTION_REACTIVATED'
|
||||
payload: SubscriptionReactivatedEventPayload
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import { SubscriptionName } from '@standardnotes/common'
|
||||
|
||||
export interface SubscriptionReactivatedEventPayload {
|
||||
userEmail: string
|
||||
previousSubscriptionId: number
|
||||
currentSubscriptionId: number
|
||||
subscriptionName: SubscriptionName
|
||||
subscriptionExpiresAt: number
|
||||
discountCode: string | null
|
||||
}
|
||||
@@ -30,6 +30,12 @@ export * from './Event/EmailBackupRequestedEvent'
|
||||
export * from './Event/EmailBackupRequestedEventPayload'
|
||||
export * from './Event/EmailMessageRequestedEvent'
|
||||
export * from './Event/EmailMessageRequestedEventPayload'
|
||||
export * from './Event/ExitDiscountAppliedEvent'
|
||||
export * from './Event/ExitDiscountAppliedEventPayload'
|
||||
export * from './Event/ExitDiscountApplyRequestedEvent'
|
||||
export * from './Event/ExitDiscountApplyRequestedEventPayload'
|
||||
export * from './Event/ExitDiscountWithdrawRequestedEvent'
|
||||
export * from './Event/ExitDiscountWithdrawRequestedEventPayload'
|
||||
export * from './Event/ExtensionKeyGrantedEvent'
|
||||
export * from './Event/ExtensionKeyGrantedEventPayload'
|
||||
export * from './Event/FileRemovedEvent'
|
||||
@@ -78,6 +84,8 @@ export * from './Event/SubscriptionPurchasedEvent'
|
||||
export * from './Event/SubscriptionPurchasedEventPayload'
|
||||
export * from './Event/SubscriptionRateAdjustedEvent'
|
||||
export * from './Event/SubscriptionRateAdjustedEventPayload'
|
||||
export * from './Event/SubscriptionReactivatedEvent'
|
||||
export * from './Event/SubscriptionReactivatedEventPayload'
|
||||
export * from './Event/SubscriptionReassignedEvent'
|
||||
export * from './Event/SubscriptionReassignedEventPayload'
|
||||
export * from './Event/SubscriptionRefundedEvent'
|
||||
|
||||
@@ -3,6 +3,52 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.6.1](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.6.0...@standardnotes/event-store@1.6.1) (2022-11-03)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/event-store
|
||||
|
||||
# [1.6.0](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.5.8...@standardnotes/event-store@1.6.0) (2022-11-03)
|
||||
|
||||
### Features
|
||||
|
||||
* **event-store:** add discount events to event store ([eb53c38](https://github.com/standardnotes/server/commit/eb53c3896f8c64747e30901722c0bdc63125128f))
|
||||
|
||||
## [1.5.8](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.5.7...@standardnotes/event-store@1.5.8) (2022-11-02)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/event-store
|
||||
|
||||
## [1.5.7](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.5.6...@standardnotes/event-store@1.5.7) (2022-11-02)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/event-store
|
||||
|
||||
## [1.5.6](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.5.5...@standardnotes/event-store@1.5.6) (2022-11-01)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/event-store
|
||||
|
||||
## [1.5.5](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.5.4...@standardnotes/event-store@1.5.5) (2022-11-01)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* force utf8mb4 charset on typeorm ([5160cc3](https://github.com/standardnotes/server/commit/5160cc36ddc9e30551d5ad40a9e210d87091eec3))
|
||||
|
||||
## [1.5.4](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.5.3...@standardnotes/event-store@1.5.4) (2022-10-31)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/event-store
|
||||
|
||||
## [1.5.3](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.5.2...@standardnotes/event-store@1.5.3) (2022-10-31)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **event-store:** add subscription reactivate handler ([9589403](https://github.com/standardnotes/server/commit/9589403c9de9304f1183789e111f6e4cf58cb7ff))
|
||||
|
||||
## [1.5.2](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.5.1...@standardnotes/event-store@1.5.2) (2022-10-31)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/event-store
|
||||
|
||||
## [1.5.1](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.5.0...@standardnotes/event-store@1.5.1) (2022-10-26)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/event-store
|
||||
|
||||
# [1.5.0](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.4.6...@standardnotes/event-store@1.5.0) (2022-10-19)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/event-store",
|
||||
"version": "1.5.0",
|
||||
"version": "1.6.1",
|
||||
"description": "Event Store Service",
|
||||
"private": true,
|
||||
"main": "dist/src/index.js",
|
||||
|
||||
@@ -82,11 +82,17 @@ export class ContainerConfigLoader {
|
||||
['SUBSCRIPTION_REVERT_REQUESTED', container.get(TYPES.EventHandler)],
|
||||
['REFUND_PROCESSED', container.get(TYPES.EventHandler)],
|
||||
['ACCOUNT_RESET_REQUESTED', container.get(TYPES.EventHandler)],
|
||||
['DISCOUNT_APPLY_REQUESTED', container.get(TYPES.EventHandler)],
|
||||
['DISCOUNT_APPLIED', container.get(TYPES.EventHandler)],
|
||||
['DISCOUNT_WITHDRAW_REQUESTED', container.get(TYPES.EventHandler)],
|
||||
['SUBSCRIPTION_RATE_ADJUSTED', container.get(TYPES.EventHandler)],
|
||||
['REFUND_REQUESTED', container.get(TYPES.EventHandler)],
|
||||
['INVOICE_GENERATED', container.get(TYPES.EventHandler)],
|
||||
['WORKSPACE_INVITE_CREATED', container.get(TYPES.EventHandler)],
|
||||
['SUBSCRIPTION_REACTIVATED', container.get(TYPES.EventHandler)],
|
||||
['EXIT_DISCOUNT_APPLY_REQUESTED', container.get(TYPES.EventHandler)],
|
||||
['EXIT_DISCOUNT_APPLIED', container.get(TYPES.EventHandler)],
|
||||
['EXIT_DISCOUNT_WITHDRAW_REQUESTED', container.get(TYPES.EventHandler)],
|
||||
])
|
||||
|
||||
container
|
||||
|
||||
@@ -11,6 +11,7 @@ const maxQueryExecutionTime = env.get('DB_MAX_QUERY_EXECUTION_TIME', true)
|
||||
|
||||
export const AppDataSource = new DataSource({
|
||||
type: 'mysql',
|
||||
charset: 'utf8mb4',
|
||||
supportBigNumbers: true,
|
||||
bigNumberStrings: false,
|
||||
maxQueryExecutionTime,
|
||||
|
||||
@@ -3,6 +3,36 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.8.1](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.8.0...@standardnotes/files-server@1.8.1) (2022-11-03)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/files-server
|
||||
|
||||
# [1.8.0](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.7.5...@standardnotes/files-server@1.8.0) (2022-11-02)
|
||||
|
||||
### Features
|
||||
|
||||
* **auth:** add processing user requests ([2255f85](https://github.com/standardnotes/files/commit/2255f856f928e855ac94f8aca4e1fb81047f58f7))
|
||||
|
||||
## [1.7.5](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.7.4...@standardnotes/files-server@1.7.5) (2022-11-02)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/files-server
|
||||
|
||||
## [1.7.4](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.7.3...@standardnotes/files-server@1.7.4) (2022-11-01)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/files-server
|
||||
|
||||
## [1.7.3](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.7.2...@standardnotes/files-server@1.7.3) (2022-10-31)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/files-server
|
||||
|
||||
## [1.7.2](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.7.1...@standardnotes/files-server@1.7.2) (2022-10-31)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/files-server
|
||||
|
||||
## [1.7.1](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.7.0...@standardnotes/files-server@1.7.1) (2022-10-26)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/files-server
|
||||
|
||||
# [1.7.0](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.6.18...@standardnotes/files-server@1.7.0) (2022-10-19)
|
||||
|
||||
### Features
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/files-server",
|
||||
"version": "1.7.0",
|
||||
"version": "1.8.1",
|
||||
"engines": {
|
||||
"node": ">=16.0.0 <17.0.0"
|
||||
},
|
||||
@@ -36,7 +36,7 @@
|
||||
"aws-sdk": "^2.1158.0",
|
||||
"connect-busboy": "^1.0.0",
|
||||
"cors": "^2.8.5",
|
||||
"dayjs": "^1.11.3",
|
||||
"dayjs": "^1.11.6",
|
||||
"dotenv": "^16.0.1",
|
||||
"express": "^4.18.1",
|
||||
"express-winston": "^4.0.5",
|
||||
|
||||
@@ -3,6 +3,18 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.5.3](https://github.com/standardnotes/server/compare/@standardnotes/predicates@1.5.2...@standardnotes/predicates@1.5.3) (2022-11-03)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/predicates
|
||||
|
||||
## [1.5.2](https://github.com/standardnotes/server/compare/@standardnotes/predicates@1.5.1...@standardnotes/predicates@1.5.2) (2022-11-01)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/predicates
|
||||
|
||||
## [1.5.1](https://github.com/standardnotes/server/compare/@standardnotes/predicates@1.5.0...@standardnotes/predicates@1.5.1) (2022-10-31)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/predicates
|
||||
|
||||
# [1.5.0](https://github.com/standardnotes/server/compare/@standardnotes/predicates@1.4.11...@standardnotes/predicates@1.5.0) (2022-10-19)
|
||||
|
||||
### Features
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/predicates",
|
||||
"version": "1.5.0",
|
||||
"version": "1.5.3",
|
||||
"engines": {
|
||||
"node": ">=16.0.0 <17.0.0"
|
||||
},
|
||||
|
||||
@@ -3,6 +3,54 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.13.1](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.13.0...@standardnotes/scheduler-server@1.13.1) (2022-11-03)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/scheduler-server
|
||||
|
||||
# [1.13.0](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.12.0...@standardnotes/scheduler-server@1.13.0) (2022-11-03)
|
||||
|
||||
### Features
|
||||
|
||||
* **scheduler:** add publishing exit discount withdraw requested event ([d66f784](https://github.com/standardnotes/server/commit/d66f78453820c8a97d090f858d9a4fc2557773fa))
|
||||
|
||||
# [1.12.0](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.11.7...@standardnotes/scheduler-server@1.12.0) (2022-11-02)
|
||||
|
||||
### Features
|
||||
|
||||
* **auth:** add processing user requests ([2255f85](https://github.com/standardnotes/server/commit/2255f856f928e855ac94f8aca4e1fb81047f58f7))
|
||||
|
||||
## [1.11.7](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.11.6...@standardnotes/scheduler-server@1.11.7) (2022-11-02)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/scheduler-server
|
||||
|
||||
## [1.11.6](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.11.5...@standardnotes/scheduler-server@1.11.6) (2022-11-01)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/scheduler-server
|
||||
|
||||
## [1.11.5](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.11.4...@standardnotes/scheduler-server@1.11.5) (2022-11-01)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* force utf8mb4 charset on typeorm ([5160cc3](https://github.com/standardnotes/server/commit/5160cc36ddc9e30551d5ad40a9e210d87091eec3))
|
||||
|
||||
## [1.11.4](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.11.3...@standardnotes/scheduler-server@1.11.4) (2022-10-31)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/scheduler-server
|
||||
|
||||
## [1.11.3](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.11.2...@standardnotes/scheduler-server@1.11.3) (2022-10-31)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/scheduler-server
|
||||
|
||||
## [1.11.2](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.11.1...@standardnotes/scheduler-server@1.11.2) (2022-10-26)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/scheduler-server
|
||||
|
||||
## [1.11.1](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.11.0...@standardnotes/scheduler-server@1.11.1) (2022-10-20)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **scheduler:** add wait-for script for docker purposes ([23ced94](https://github.com/standardnotes/server/commit/23ced9427f63f96b5c470dccbc5aa07bd77e4d81))
|
||||
|
||||
# [1.11.0](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.10.46...@standardnotes/scheduler-server@1.11.0) (2022-10-19)
|
||||
|
||||
### Features
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/scheduler-server",
|
||||
"version": "1.11.0",
|
||||
"version": "1.13.1",
|
||||
"engines": {
|
||||
"node": ">=16.0.0 <17.0.0"
|
||||
},
|
||||
@@ -32,7 +32,7 @@
|
||||
"@standardnotes/predicates": "workspace:*",
|
||||
"@standardnotes/time": "workspace:*",
|
||||
"aws-sdk": "^2.1158.0",
|
||||
"dayjs": "^1.11.3",
|
||||
"dayjs": "^1.11.6",
|
||||
"dotenv": "^16.0.1",
|
||||
"inversify": "^6.0.1",
|
||||
"ioredis": "^5.2.0",
|
||||
|
||||
@@ -36,6 +36,7 @@ import { PredicateVerifiedEventHandler } from '../Domain/Handler/PredicateVerifi
|
||||
import { VerifyPredicates } from '../Domain/UseCase/VerifyPredicates/VerifyPredicates'
|
||||
import { UserRegisteredEventHandler } from '../Domain/Handler/UserRegisteredEventHandler'
|
||||
import { SubscriptionCancelledEventHandler } from '../Domain/Handler/SubscriptionCancelledEventHandler'
|
||||
import { ExitDiscountAppliedEventHandler } from '../Domain/Handler/ExitDiscountAppliedEventHandler'
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const newrelicFormatter = require('@newrelic/winston-enricher')
|
||||
@@ -124,6 +125,9 @@ export class ContainerConfigLoader {
|
||||
container
|
||||
.bind<SubscriptionCancelledEventHandler>(TYPES.SubscriptionCancelledEventHandler)
|
||||
.to(SubscriptionCancelledEventHandler)
|
||||
container
|
||||
.bind<ExitDiscountAppliedEventHandler>(TYPES.ExitDiscountAppliedEventHandler)
|
||||
.to(ExitDiscountAppliedEventHandler)
|
||||
|
||||
// Services
|
||||
container.bind<DomainEventFactory>(TYPES.DomainEventFactory).to(DomainEventFactory)
|
||||
@@ -146,6 +150,7 @@ export class ContainerConfigLoader {
|
||||
['PREDICATE_VERIFIED', container.get(TYPES.PredicateVerifiedEventHandler)],
|
||||
['USER_REGISTERED', container.get(TYPES.UserRegisteredEventHandler)],
|
||||
['SUBSCRIPTION_CANCELLED', container.get(TYPES.SubscriptionCancelledEventHandler)],
|
||||
['EXIT_DISCOUNT_APPLIED', container.get(TYPES.ExitDiscountAppliedEventHandler)],
|
||||
])
|
||||
|
||||
if (env.get('SQS_QUEUE_URL', true)) {
|
||||
|
||||
@@ -12,6 +12,7 @@ const maxQueryExecutionTime = env.get('DB_MAX_QUERY_EXECUTION_TIME', true)
|
||||
|
||||
export const AppDataSource = new DataSource({
|
||||
type: 'mysql',
|
||||
charset: 'utf8mb4',
|
||||
supportBigNumbers: true,
|
||||
bigNumberStrings: false,
|
||||
maxQueryExecutionTime,
|
||||
|
||||
@@ -24,6 +24,7 @@ const TYPES = {
|
||||
PredicateVerifiedEventHandler: Symbol.for('PredicateVerifiedEventHandler'),
|
||||
UserRegisteredEventHandler: Symbol.for('UserRegisteredEventHandler'),
|
||||
SubscriptionCancelledEventHandler: Symbol.for('SubscriptionCancelledEventHandler'),
|
||||
ExitDiscountAppliedEventHandler: Symbol.for('ExitDiscountAppliedEventHandler'),
|
||||
// Services
|
||||
DomainEventPublisher: Symbol.for('DomainEventPublisher'),
|
||||
DomainEventSubscriberFactory: Symbol.for('DomainEventSubscriberFactory'),
|
||||
|
||||
@@ -65,6 +65,29 @@ describe('DomainEventFactory', () => {
|
||||
})
|
||||
})
|
||||
|
||||
it('should create a EXIT_DISCOUNT_WITHDRAW_REQUESTED event', () => {
|
||||
expect(
|
||||
createFactory().createExitDiscountWithdrawRequestedEvent({
|
||||
userEmail: 'test@test.te',
|
||||
discountCode: 'exit-20',
|
||||
}),
|
||||
).toEqual({
|
||||
createdAt: expect.any(Date),
|
||||
meta: {
|
||||
correlation: {
|
||||
userIdentifier: 'test@test.te',
|
||||
userIdentifierType: 'email',
|
||||
},
|
||||
origin: 'scheduler',
|
||||
},
|
||||
payload: {
|
||||
userEmail: 'test@test.te',
|
||||
discountCode: 'exit-20',
|
||||
},
|
||||
type: 'EXIT_DISCOUNT_WITHDRAW_REQUESTED',
|
||||
})
|
||||
})
|
||||
|
||||
it('should create a EMAIL_MESSAGE_REQUESTED event', () => {
|
||||
expect(
|
||||
createFactory().createEmailMessageRequestedEvent({
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
DiscountWithdrawRequestedEvent,
|
||||
DomainEventService,
|
||||
EmailMessageRequestedEvent,
|
||||
ExitDiscountWithdrawRequestedEvent,
|
||||
PredicateVerificationRequestedEvent,
|
||||
} from '@standardnotes/domain-events'
|
||||
import { PredicateAuthority } from '@standardnotes/predicates'
|
||||
@@ -51,6 +52,24 @@ export class DomainEventFactory implements DomainEventFactoryInterface {
|
||||
}
|
||||
}
|
||||
|
||||
createExitDiscountWithdrawRequestedEvent(dto: {
|
||||
userEmail: string
|
||||
discountCode: string
|
||||
}): ExitDiscountWithdrawRequestedEvent {
|
||||
return {
|
||||
type: 'EXIT_DISCOUNT_WITHDRAW_REQUESTED',
|
||||
createdAt: this.timer.getUTCDate(),
|
||||
meta: {
|
||||
correlation: {
|
||||
userIdentifier: dto.userEmail,
|
||||
userIdentifierType: 'email',
|
||||
},
|
||||
origin: DomainEventService.Scheduler,
|
||||
},
|
||||
payload: dto,
|
||||
}
|
||||
}
|
||||
|
||||
createEmailMessageRequestedEvent(dto: {
|
||||
userEmail: string
|
||||
messageIdentifier: EmailMessageIdentifier
|
||||
|
||||
@@ -3,6 +3,7 @@ import {
|
||||
DiscountApplyRequestedEvent,
|
||||
DiscountWithdrawRequestedEvent,
|
||||
EmailMessageRequestedEvent,
|
||||
ExitDiscountWithdrawRequestedEvent,
|
||||
PredicateVerificationRequestedEvent,
|
||||
} from '@standardnotes/domain-events'
|
||||
|
||||
@@ -18,4 +19,8 @@ export interface DomainEventFactoryInterface {
|
||||
}): EmailMessageRequestedEvent
|
||||
createDiscountApplyRequestedEvent(dto: { userEmail: string; discountCode: string }): DiscountApplyRequestedEvent
|
||||
createDiscountWithdrawRequestedEvent(dto: { userEmail: string; discountCode: string }): DiscountWithdrawRequestedEvent
|
||||
createExitDiscountWithdrawRequestedEvent(dto: {
|
||||
userEmail: string
|
||||
discountCode: string
|
||||
}): ExitDiscountWithdrawRequestedEvent
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
import 'reflect-metadata'
|
||||
|
||||
import { ExitDiscountAppliedEvent } from '@standardnotes/domain-events'
|
||||
import { TimerInterface } from '@standardnotes/time'
|
||||
|
||||
import { JobRepositoryInterface } from '../Job/JobRepositoryInterface'
|
||||
|
||||
import { ExitDiscountAppliedEventHandler } from './ExitDiscountAppliedEventHandler'
|
||||
|
||||
describe('ExitDiscountAppliedEventHandler', () => {
|
||||
let timer: TimerInterface
|
||||
let jobRepository: JobRepositoryInterface
|
||||
|
||||
const createHandler = () => new ExitDiscountAppliedEventHandler(timer, jobRepository)
|
||||
|
||||
beforeEach(() => {
|
||||
timer = {} as jest.Mocked<TimerInterface>
|
||||
timer.getUTCDateNHoursAhead = jest.fn().mockReturnValue(new Date(2))
|
||||
timer.convertDateToMicroseconds = jest.fn().mockReturnValue(123)
|
||||
timer.getTimestampInMicroseconds = jest.fn().mockReturnValue(1)
|
||||
|
||||
jobRepository = {} as jest.Mocked<JobRepositoryInterface>
|
||||
jobRepository.save = jest.fn()
|
||||
})
|
||||
|
||||
it('should schedule a job to do an exit discount withdrawal', async () => {
|
||||
await createHandler().handle({
|
||||
payload: { userEmail: 'test@test.te', discountRate: 20 },
|
||||
} as jest.Mocked<ExitDiscountAppliedEvent>)
|
||||
|
||||
expect(jobRepository.save).toHaveBeenNthCalledWith(1, {
|
||||
createdAt: 1,
|
||||
name: 'withdraw-subscription-exit-discount',
|
||||
scheduledAt: 123,
|
||||
status: 'pending',
|
||||
userIdentifier: 'test@test.te',
|
||||
userIdentifierType: 'email',
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,33 @@
|
||||
import { DomainEventHandlerInterface, ExitDiscountAppliedEvent } from '@standardnotes/domain-events'
|
||||
import { inject, injectable } from 'inversify'
|
||||
import { TimerInterface } from '@standardnotes/time'
|
||||
|
||||
import TYPES from '../../Bootstrap/Types'
|
||||
import { Job } from '../Job/Job'
|
||||
import { JobName } from '../Job/JobName'
|
||||
import { JobRepositoryInterface } from '../Job/JobRepositoryInterface'
|
||||
import { JobStatus } from '../Job/JobStatus'
|
||||
|
||||
@injectable()
|
||||
export class ExitDiscountAppliedEventHandler implements DomainEventHandlerInterface {
|
||||
constructor(
|
||||
@inject(TYPES.Timer) private timer: TimerInterface,
|
||||
@inject(TYPES.JobRepository) private jobRepository: JobRepositoryInterface,
|
||||
) {}
|
||||
|
||||
async handle(event: ExitDiscountAppliedEvent): Promise<void> {
|
||||
await this.scheduleExitDiscountWithdraw(event)
|
||||
}
|
||||
|
||||
private async scheduleExitDiscountWithdraw(event: ExitDiscountAppliedEvent): Promise<void> {
|
||||
const job = new Job()
|
||||
job.name = JobName.WITHDRAW_SUBSCRIPTION_EXIT_DISCOUNT
|
||||
job.scheduledAt = this.timer.convertDateToMicroseconds(this.timer.getUTCDateNHoursAhead(24))
|
||||
job.createdAt = this.timer.getTimestampInMicroseconds()
|
||||
job.status = JobStatus.Pending
|
||||
job.userIdentifier = event.payload.userEmail
|
||||
job.userIdentifierType = 'email'
|
||||
|
||||
await this.jobRepository.save(job)
|
||||
}
|
||||
}
|
||||
@@ -253,6 +253,35 @@ describe('JobDoneInterpreter', () => {
|
||||
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should request exit discount withdraw', async () => {
|
||||
jobRepository.findOneByUuid = jest.fn().mockReturnValue({
|
||||
name: JobName.WITHDRAW_SUBSCRIPTION_EXIT_DISCOUNT,
|
||||
userIdentifier: 'test@standardnotes.com',
|
||||
userIdentifierType: 'email',
|
||||
} as jest.Mocked<Job>)
|
||||
|
||||
await createInterpreter().interpret('1-2-3')
|
||||
|
||||
expect(domainEventFactory.createExitDiscountWithdrawRequestedEvent).toHaveBeenCalledWith({
|
||||
userEmail: 'test@standardnotes.com',
|
||||
discountCode: 'exit-20',
|
||||
})
|
||||
expect(domainEventPublisher.publish).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should not request exit discount withdraw if email is missing', async () => {
|
||||
jobRepository.findOneByUuid = jest.fn().mockReturnValue({
|
||||
name: JobName.WITHDRAW_SUBSCRIPTION_EXIT_DISCOUNT,
|
||||
userIdentifier: '2-3-4',
|
||||
userIdentifierType: 'uuid',
|
||||
} as jest.Mocked<Job>)
|
||||
|
||||
await createInterpreter().interpret('1-2-3')
|
||||
|
||||
expect(domainEventFactory.createExitDiscountWithdrawRequestedEvent).not.toHaveBeenCalled()
|
||||
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should do nothing if there is no interpretation for a given job', async () => {
|
||||
jobRepository.findOneByUuid = jest.fn().mockReturnValue({
|
||||
name: 'foobar' as JobName,
|
||||
|
||||
@@ -65,6 +65,11 @@ export class JobDoneInterpreter implements JobDoneInterpreterInterface {
|
||||
await this.requestDiscountWithdraw(job)
|
||||
}
|
||||
return
|
||||
case JobName.WITHDRAW_SUBSCRIPTION_EXIT_DISCOUNT:
|
||||
if (job.userIdentifierType === 'email') {
|
||||
await this.requestExitDiscountWithdraw(job)
|
||||
}
|
||||
return
|
||||
default:
|
||||
this.logger.warn(`[${jobUuid}]${job.name}: job is not interpretable.`)
|
||||
|
||||
@@ -132,6 +137,17 @@ export class JobDoneInterpreter implements JobDoneInterpreterInterface {
|
||||
)
|
||||
}
|
||||
|
||||
private async requestExitDiscountWithdraw(job: Job): Promise<void> {
|
||||
this.logger.debug(`[${job.uuid}]${job.name}: requesting exit discount withdraw.`)
|
||||
|
||||
await this.domainEventPublisher.publish(
|
||||
this.domainEventFactory.createExitDiscountWithdrawRequestedEvent({
|
||||
userEmail: job.userIdentifier,
|
||||
discountCode: 'exit-20',
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
private async predicatesAreFulfilled(job: Job): Promise<boolean> {
|
||||
const predicates = await this.predicateRepository.findByJobUuid(job.uuid)
|
||||
|
||||
|
||||
@@ -5,4 +5,5 @@ export enum JobName {
|
||||
EXIT_INTERVIEW = 'exit-interview',
|
||||
APPLY_SUBSCRIPTION_DISCOUNT = 'apply-subscription-discount',
|
||||
WITHDRAW_SUBSCRIPTION_DISCOUNT = 'withdraw-subscription-discount',
|
||||
WITHDRAW_SUBSCRIPTION_EXIT_DISCOUNT = 'withdraw-subscription-exit-discount',
|
||||
}
|
||||
|
||||
Executable
+17
@@ -0,0 +1,17 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
host="$1"
|
||||
shift
|
||||
port="$1"
|
||||
shift
|
||||
cmd="$@"
|
||||
|
||||
while ! nc -vz $host $port; do
|
||||
>&2 echo "$host:$port is unavailable yet - waiting for it to start"
|
||||
sleep 10
|
||||
done
|
||||
|
||||
>&2 echo "$host:$port is up - executing command"
|
||||
exec $cmd
|
||||
@@ -3,6 +3,18 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.5.3](https://github.com/standardnotes/server/compare/@standardnotes/security@1.5.2...@standardnotes/security@1.5.3) (2022-11-03)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/security
|
||||
|
||||
## [1.5.2](https://github.com/standardnotes/server/compare/@standardnotes/security@1.5.1...@standardnotes/security@1.5.2) (2022-11-01)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/security
|
||||
|
||||
## [1.5.1](https://github.com/standardnotes/server/compare/@standardnotes/security@1.5.0...@standardnotes/security@1.5.1) (2022-10-31)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/security
|
||||
|
||||
# [1.5.0](https://github.com/standardnotes/server/compare/@standardnotes/security@1.4.9...@standardnotes/security@1.5.0) (2022-10-19)
|
||||
|
||||
### Features
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/security",
|
||||
"version": "1.5.0",
|
||||
"version": "1.5.3",
|
||||
"engines": {
|
||||
"node": ">=16.0.0 <17.0.0"
|
||||
},
|
||||
|
||||
@@ -3,6 +3,40 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.10.8](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.10.7...@standardnotes/syncing-server@1.10.8) (2022-11-03)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/syncing-server
|
||||
|
||||
## [1.10.7](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.10.6...@standardnotes/syncing-server@1.10.7) (2022-11-02)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/syncing-server
|
||||
|
||||
## [1.10.6](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.10.5...@standardnotes/syncing-server@1.10.6) (2022-11-02)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/syncing-server
|
||||
|
||||
## [1.10.5](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.10.4...@standardnotes/syncing-server@1.10.5) (2022-11-01)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/syncing-server
|
||||
|
||||
## [1.10.4](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.10.3...@standardnotes/syncing-server@1.10.4) (2022-11-01)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* force utf8mb4 charset on typeorm ([5160cc3](https://github.com/standardnotes/syncing-server-js/commit/5160cc36ddc9e30551d5ad40a9e210d87091eec3))
|
||||
|
||||
## [1.10.3](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.10.2...@standardnotes/syncing-server@1.10.3) (2022-10-31)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/syncing-server
|
||||
|
||||
## [1.10.2](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.10.1...@standardnotes/syncing-server@1.10.2) (2022-10-31)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/syncing-server
|
||||
|
||||
## [1.10.1](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.10.0...@standardnotes/syncing-server@1.10.1) (2022-10-26)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/syncing-server
|
||||
|
||||
# [1.10.0](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.9.8...@standardnotes/syncing-server@1.10.0) (2022-10-19)
|
||||
|
||||
### Features
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/syncing-server",
|
||||
"version": "1.10.0",
|
||||
"version": "1.10.8",
|
||||
"engines": {
|
||||
"node": ">=16.0.0 <17.0.0"
|
||||
},
|
||||
|
||||
@@ -12,6 +12,7 @@ const maxQueryExecutionTime = env.get('DB_MAX_QUERY_EXECUTION_TIME', true)
|
||||
|
||||
export const AppDataSource = new DataSource({
|
||||
type: 'mysql',
|
||||
charset: 'utf8mb4',
|
||||
supportBigNumbers: true,
|
||||
bigNumberStrings: false,
|
||||
maxQueryExecutionTime,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user