Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .cursor/mcp.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"mcpServers": {
"nx-mcp": {
"url": "http://localhost:9549/sse"
}
}
}
1 change: 1 addition & 0 deletions .github/scripts/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ function generatePrStateComment(state, commitSha, prNumber) {
| **Status** | ${getStatusEmoji(state.deploy)} ${state.deploy || 'No state'} |
| **Commit** | \`${commitSha.substring(0, 7)}\` |
| **Updated** | ${new Date().toLocaleString()} |
| **API Endpoint** | [${state.api_container_endpoint}](${state.api_container_endpoint}) |
`
}

Expand Down
11 changes: 7 additions & 4 deletions .github/workflows/iac-apply.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ on:
branches:
- main
paths:
- "infrastructure/**"
- 'infrastructure/**'

jobs:
core:
Expand Down Expand Up @@ -40,6 +40,9 @@ jobs:
bucket=${{ github.event.repository.name }}-tofu-state
variables: |
gh_repo_name = "${{ github.event.repository.name }}"
scw_access_key = "${{ secrets.SCW_ACCESS_KEY }}"
scw_secret_key = "${{ secrets.SCW_SECRET_KEY }}"
scw_organization_id = "${{ secrets.SCW_ORGANIZATION_ID }}"

environments:
needs: core
Expand Down Expand Up @@ -68,9 +71,6 @@ jobs:
env:
GITHUB_TOKEN: ${{ steps.app-token.outputs.token }}
GITHUB_OWNER: ${{ github.repository_owner }}
SCW_ACCESS_KEY: ${{ secrets.SCW_ACCESS_KEY }}
SCW_SECRET_KEY: ${{ secrets.SCW_SECRET_KEY }}
SCW_ORGANIZATION_ID: ${{ secrets.SCW_ORGANIZATION_ID }}
with:
path: ./infrastructure/envs/${{ matrix.environment }}
label: ${{ matrix.environment }}
Expand All @@ -80,3 +80,6 @@ jobs:
bucket=${{ github.event.repository.name }}-tofu-state
variables: |
gh_repo_name = "${{ github.event.repository.name }}"
scw_access_key = "${{ secrets.SCW_ACCESS_KEY }}"
scw_secret_key = "${{ secrets.SCW_SECRET_KEY }}"
scw_organization_id = "${{ secrets.SCW_ORGANIZATION_ID }}"
11 changes: 7 additions & 4 deletions .github/workflows/iac-plan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ on:
branches:
- main
paths:
- "infrastructure/**"
- 'infrastructure/**'

jobs:
fmt-check:
Expand Down Expand Up @@ -53,6 +53,9 @@ jobs:
bucket=${{ github.event.repository.name }}-tofu-state
variables: |
gh_repo_name = "${{ github.event.repository.name }}"
scw_access_key = "${{ secrets.SCW_ACCESS_KEY }}"
scw_secret_key = "${{ secrets.SCW_SECRET_KEY }}"
scw_organization_id = "${{ secrets.SCW_ORGANIZATION_ID }}"

environments:
needs: core
Expand Down Expand Up @@ -81,9 +84,6 @@ jobs:
env:
GITHUB_TOKEN: ${{ steps.app-token.outputs.token }}
GITHUB_OWNER: ${{ github.repository_owner }}
SCW_ACCESS_KEY: ${{ secrets.SCW_ACCESS_KEY }}
SCW_SECRET_KEY: ${{ secrets.SCW_SECRET_KEY }}
SCW_ORGANIZATION_ID: ${{ secrets.SCW_ORGANIZATION_ID }}
with:
path: ./infrastructure/envs/${{ matrix.environment }}
label: ${{ matrix.environment }}
Expand All @@ -93,3 +93,6 @@ jobs:
bucket=${{ github.event.repository.name }}-tofu-state
variables: |
gh_repo_name = "${{ github.event.repository.name }}"
scw_access_key = "${{ secrets.SCW_ACCESS_KEY }}"
scw_secret_key = "${{ secrets.SCW_SECRET_KEY }}"
scw_organization_id = "${{ secrets.SCW_ORGANIZATION_ID }}"
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Preview - Deploy
name: Pull Request

on:
pull_request:
Expand All @@ -10,7 +10,44 @@ concurrency:
cancel-in-progress: false

jobs:
lint-test-build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
filter: tree:0
fetch-depth: 0

- uses: pnpm/action-setup@v4
name: Install pnpm
with:
version: 10.12.2
run_install: false

# This enables task distribution via Nx Cloud
# Run this command as early as possible, before dependencies are installed
# Learn more at https://nx.dev/ci/reference/nx-cloud-cli#npx-nxcloud-startcirun
# Uncomment this line to enable task distribution
# - run: pnpm dlx nx-cloud start-ci-run --distribute-on="3 linux-medium-js" --stop-agents-after="build"

# Cache node_modules
- uses: actions/setup-node@v4
with:
node-version: 22
cache: 'pnpm'

- run: pnpm install --frozen-lockfile
- uses: nrwl/nx-set-shas@v4

- run: pnpm sherif

# Prepend any command with "nx-cloud record --" to record its logs to Nx Cloud
# - run: pnpm exec nx-cloud record -- echo Hello World
# Nx Affected runs only tasks affected by the changes in this PR/commit. Learn more: https://nx.dev/ci/features/affected
- run: pnpm exec nx affected -t lint test build

determine-actions:
needs: lint-test-build
name: Determine actions
runs-on: ubuntu-latest
outputs:
Expand Down Expand Up @@ -67,12 +104,10 @@ jobs:

- name: Apply Tofu plan
uses: dflook/tofu-apply@v2.1.0
id: apply
env:
GITHUB_TOKEN: ${{ steps.app-token.outputs.token }}
GITHUB_OWNER: ${{ github.repository_owner }}
SCW_ACCESS_KEY: ${{ secrets.SCW_ACCESS_KEY }}
SCW_SECRET_KEY: ${{ secrets.SCW_SECRET_KEY }}
SCW_ORGANIZATION_ID: ${{ secrets.SCW_ORGANIZATION_ID }}
with:
path: ./infrastructure/envs/preview
label: preview
Expand All @@ -85,6 +120,9 @@ jobs:
variables: |
gh_repo_name = "${{ github.event.repository.name }}"
pr_number = "${{ github.event.pull_request.number }}"
scw_access_key = "${{ secrets.SCW_ACCESS_KEY }}"
scw_secret_key = "${{ secrets.SCW_SECRET_KEY }}"
scw_organization_id = "${{ secrets.SCW_ORGANIZATION_ID }}"

- name: Deploy application
run: |
Expand All @@ -96,7 +134,8 @@ jobs:
script: |
const scripts = require('./.github/scripts/report-state.js');
await scripts({ github, context, core }, {
deploy: 'deployed'
deploy: 'deployed',
api_container_endpoint: ${{ steps.apply.outputs.api_container_endpoint }}
});

- name: Report state (failure)
Expand Down Expand Up @@ -140,9 +179,6 @@ jobs:
env:
GITHUB_TOKEN: ${{ steps.app-token.outputs.token }}
GITHUB_OWNER: ${{ github.repository_owner }}
SCW_ACCESS_KEY: ${{ secrets.SCW_ACCESS_KEY }}
SCW_SECRET_KEY: ${{ secrets.SCW_SECRET_KEY }}
SCW_ORGANIZATION_ID: ${{ secrets.SCW_ORGANIZATION_ID }}
with:
path: ./infrastructure/envs/preview
workspace: pr-${{ github.event.pull_request.number }}
Expand All @@ -153,6 +189,9 @@ jobs:
variables: |
gh_repo_name = "${{ github.event.repository.name }}"
pr_number = "${{ github.event.pull_request.number }}"
scw_access_key = "${{ secrets.SCW_ACCESS_KEY }}"
scw_secret_key = "${{ secrets.SCW_SECRET_KEY }}"
scw_organization_id = "${{ secrets.SCW_ORGANIZATION_ID }}"

- name: Report state (destroyed)
uses: actions/github-script@v7
Expand Down
66 changes: 64 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,65 @@
.terraform
# See https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files for more about ignoring files.

# compiled output
dist
tmp
out-tsc

# dependencies
node_modules

# IDEs and editors
/.idea
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace

# IDE - VSCode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json

# misc
/.sass-cache
/connect.lock
/coverage
/libpeerconnection.log
npm-debug.log
yarn-error.log
testem.log
/typings

# System Files
.DS_Store
Thumbs.db

.nx/cache
.nx/workspace-data
.cursor/rules/nx-rules.mdc
.github/instructions/nx.instructions.md

test-output

vite.config.*.timestamp*
vitest.config.*.timestamp*

# Local .terraform directories
**/.terraform/*

# Ignore variables files
*.auto.tfvars
node_modules

# Ignore override files
*.tfoverride

# Ignore environment-specific files
.envrc

# Ignore CLI configuration files
.terraformrc
terraform.rc
2 changes: 2 additions & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
strict-peer-dependencies=false
auto-install-peers=true
5 changes: 5 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Add files here to ignore them from prettier formatting
/dist
/coverage
/.nx/cache
/.nx/workspace-data
3 changes: 3 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"singleQuote": true
}
9 changes: 9 additions & 0 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"recommendations": [
"nrwl.angular-console",
"esbenp.prettier-vscode",
"dbaeumer.vscode-eslint",
"Orta.vscode-jest",
"ms-playwright.playwright"
]
}
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{
"nxConsole.generateAiAgentRules": true,
"editor.formatOnSave": true
}
}
22 changes: 22 additions & 0 deletions apps/api-e2e/.spec.swcrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"jsc": {
"target": "es2017",
"parser": {
"syntax": "typescript",
"decorators": true,
"dynamicImport": true
},
"transform": {
"decoratorMetadata": true,
"legacyDecorator": true
},
"keepClassNames": true,
"externalHelpers": true,
"loose": true
},
"module": {
"type": "es6"
},
"sourceMaps": true,
"exclude": []
}
3 changes: 3 additions & 0 deletions apps/api-e2e/eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import baseConfig from '../../eslint.config.mjs';

export default [...baseConfig];
24 changes: 24 additions & 0 deletions apps/api-e2e/jest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/* eslint-disable */
import { readFileSync } from 'fs';

// Reading the SWC compilation config for the spec files
const swcJestConfig = JSON.parse(
readFileSync(`${__dirname}/.spec.swcrc`, 'utf-8')
);

// Disable .swcrc look-up by SWC core because we're passing in swcJestConfig ourselves
swcJestConfig.swcrc = false;

export default {
displayName: '@nxstack/api-e2e',
preset: '../../jest.preset.js',
globalSetup: '<rootDir>/src/support/global-setup.ts',
globalTeardown: '<rootDir>/src/support/global-teardown.ts',
setupFiles: ['<rootDir>/src/support/test-setup.ts'],
testEnvironment: 'node',
transform: {
'^.+\\.[tj]s$': ['@swc/jest', swcJestConfig],
},
moduleFileExtensions: ['ts', 'js', 'html'],
coverageDirectory: 'test-output/jest/coverage',
};
26 changes: 26 additions & 0 deletions apps/api-e2e/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"name": "@nxstack/api-e2e",
"version": "0.0.1",
"private": true,
"nx": {
"implicitDependencies": [
"@nxstack/api"
],
"targets": {
"e2e": {
"executor": "@nx/jest:jest",
"outputs": [
"{projectRoot}/test-output/jest/coverage"
],
"options": {
"jestConfig": "apps/api-e2e/jest.config.ts",
"passWithNoTests": true
},
"dependsOn": [
"@nxstack/api:build",
"@nxstack/api:serve"
]
}
}
}
}
10 changes: 10 additions & 0 deletions apps/api-e2e/src/api/api.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import axios from 'axios';

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

expect(res.status).toBe(200);
expect(res.data).toEqual({ message: 'Hello API' });
});
});
Loading