Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into production
Browse files Browse the repository at this point in the history
  • Loading branch information
pylipp committed Feb 6, 2024
2 parents 44b95a1 + 4642c1c commit 68ca62a
Show file tree
Hide file tree
Showing 234 changed files with 8,777 additions and 10,124 deletions.
52 changes: 28 additions & 24 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -100,23 +100,23 @@ jobs:
name: Generate .env File
command: |
echo "
REACT_APP_AUTH0_DOMAIN=${AUTH0_DOMAIN}
REACT_APP_AUTH0_CLIENT_ID=${AUTH0_CLIENT_ID}
REACT_APP_AUTH0_AUDIENCE=${AUTH0_AUDIENCE}
REACT_APP_REDIRECT=${REACT_APP_REDIRECT}
REACT_APP_LOGOUT_URL=${REACT_APP_LOGOUT_URL}
REACT_APP_GRAPHQL_SERVER=${REACT_APP_GRAPHQL_SERVER}
REACT_APP_OLD_APP_BASE_URL=${OLD_APP_BASE_URL}
REACT_APP_SENTRY_FE_DSN=${SENTRY_FE_DSN}
REACT_APP_SENTRY_ENVIRONMENT=${ENVIRONMENT}
REACT_APP_SENTRY_TRACES_SAMPLE_RATE=${SENTRY_TRACES_SAMPLE_RATE}
REACT_APP_ENVIRONMENT=${ENVIRONMENT}
FRONT_AUTH0_DOMAIN=${AUTH0_DOMAIN}
FRONT_AUTH0_CLIENT_ID=${AUTH0_CLIENT_ID}
FRONT_AUTH0_AUDIENCE=${AUTH0_AUDIENCE}
FRONT_REDIRECT=${FRONT_REDIRECT}
FRONT_LOGOUT_URL=${FRONT_LOGOUT_URL}
FRONT_GRAPHQL_SERVER=${FRONT_GRAPHQL_SERVER}
FRONT_OLD_APP_BASE_URL=${OLD_APP_BASE_URL}
FRONT_SENTRY_FE_DSN=${SENTRY_FE_DSN}
FRONT_SENTRY_ENVIRONMENT=${ENVIRONMENT}
FRONT_SENTRY_TRACES_SAMPLE_RATE=${SENTRY_TRACES_SAMPLE_RATE}
FRONT_ENVIRONMENT=${ENVIRONMENT}
" > .env
- run:
name: Run style checks
command: |
yarn lint
yarn format:write
yarn lint:fix:all
yarn format:write:all
- run:
name: Build front
command: |
Expand All @@ -127,29 +127,33 @@ jobs:
- persist_to_workspace:
root: ~/
paths:
- front/build
- front/dist

test-front:
executor: node-executor
working_directory: ~/front
resource_class: medium+
steps:
- attach_workspace:
at: ~/
- run:
name: Test front app and create reports
command: |
DEBUG_PRINT_LIMIT=10000 yarn test:coverage --ci --runInBand --reporters=default --reporters=jest-junit
environment:
JEST_JUNIT_OUTPUT_DIR: reports
DEBUG_PRINT_LIMIT=10000 yarn test:coverage --test-timeout=40000
- store_test_results:
path: reports
path: coverage/junit.xml
- store_artifacts:
path: coverage
destination: coverage
- codecov/upload:
flags: frontend
file: coverage/coverage-final.json
- slack/notify-on-failure:
only_for_branches: master,production
- run:
name: Show memory usage of FE tests in Bytes
command: cat /sys/fs/cgroup/memory/memory.max_usage_in_bytes
when: always

# following https://circleci.com/docs/2.0/project-walkthrough/
test-back:
Expand All @@ -170,7 +174,7 @@ jobs:
name: run style checks on Python files
command: |
source $(pyenv root)/versions/3.10.4/envs/env/bin/activate
pre-commit run --files **/*.py
pre-commit run --files ./**/*.py
- save_cache:
key: webapp-deps-{{ checksum "requirements.txt" }}-{{ checksum "requirements-deploy.txt" }}-{{ checksum "requirements-dev.txt" }}-{{ checksum "../.pre-commit-config.yaml" }}
paths:
Expand Down Expand Up @@ -199,9 +203,9 @@ jobs:
command: |
source $(pyenv root)/versions/3.10.4/envs/env/bin/activate
# overwrite environment variable because it must not depend on the CircleCI context
ENVIRONMENT=development MYSQL_PORT=3306 pytest --cov-report xml:test-results/coverage.xml --cov=boxtribute_server
ENVIRONMENT=development MYSQL_PORT=3306 pytest --cov-report xml:test-results/coverage.xml --cov=boxtribute_server --junit-xml=test-results/junit.xml
- store_test_results:
path: test-results
path: test-results/junit.xml
- store_artifacts:
path: test-results
- slack/notify-on-failure:
Expand All @@ -225,11 +229,11 @@ jobs:
- run:
name: Inject Heap Analytics Script to index.html
command: |
sed -i "s/HEAPIO_APP_ID/${HEAPIO_APP_ID}/" ../front/build/heapanalytics.js
sed -i 's|</head>|<script src="/heapanalytics.js"></script></head>|' ../front/build/index.html
sed -i "s/HEAPIO_APP_ID/${HEAPIO_APP_ID}/" ../front/dist/heapanalytics.js
sed -i 's|</head>|<script src="/heapanalytics.js"></script></head>|' ../front/dist/index.html
- run:
name: Copy react build into flask app for deployment
command: mv ../front/build front-build
command: mv ../front/dist front-build
- run:
name: Create version.txt
command: |
Expand Down
17 changes: 17 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
build
dist
coverage
node_modules
public
*.js
*.old.*
*.stories.*
# Disable linting for Distributions feature
Distributions
# Disabled until we move to tanStack table v8
react-table-config.d.ts
# Disable linting for generated files from the GraphQL codegen
generated
graphql.ts
codegen.ts
vite.config.ts
112 changes: 112 additions & 0 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
module.exports = {
// It does not look for a configuration file upwards from the root directory.
root: true,
// This defines env variables
env: { browser: true, es2020: true },
// ignore linting for these files
ignorePatterns: ["dist", ".eslintrc.cjs", ".eslintrc"],
// loads settings and rules from other eslint configs
extends: [
"eslint:recommended",
// TODO: try out plugin:@typescript-eslint/recommended-type-checked
"plugin:@typescript-eslint/eslint-recommended",
// we generally want to follow the rules from airbnb as a base
// --> the extension of airbnb should be last so that it cannot be overriden by other configs
// airbnb uses the plugins eslint-plugin-import, eslint-plugin-react, eslint-plugin-react-hooks, eslint-plugin-jsx-a11y
// --> we need to install these plugins as devDependencies and load their recommended settings first
"plugin:react/recommended",
"plugin:react-hooks/recommended",
"plugin:jsx-a11y/recommended",
"plugin:import/recommended",
"plugin:import/typescript",
"airbnb",
// put prettier config last so that it can override all formatting rules
"prettier",
],
// regarding @typescript-eslint: https://typescript-eslint.io/linting/typed-linting/monorepos
parser: "@typescript-eslint/parser",
parserOptions: {
tsconfigRootDir: __dirname,
project: ["./*/tsconfig.json"],
},
plugins: ["@typescript-eslint"],
settings: {
// --------- Import Plugin Settings ---------
// This defines the parser to use for .ts and .tsx files
"import/parsers": {
"@typescript-eslint/parser": [".ts", ".tsx"],
},
// this defines how eslint resolves import statements
"import/resolver": {
node: {
// resolve imports with these extensions
extensions: [".ts", ".tsx"],
// look here for modules of import statements
moduleDirectory: ["node_modules", "src"],
},
typescript: {
// always try to resolve types
alwaysTryTypes: true,
// look here for tsconfig files
project: ["./*/tsconfig.json"],
},
},
},
rules: {
// --------- typescipt-eslint Plugin Rules ---------
// enforce to have interfaces/type should start with "I".
"@typescript-eslint/naming-convention": [
"error",
{
selector: "interface",
format: ["PascalCase"],
custom: {
regex: "^I[A-Z]",
match: true,
},
},
],
// --------- React Plugin Rules ---------
// we do not need to import React in every file
"react/react-in-jsx-scope": "off",
"react/jsx-props-no-spreading": "off",
// TODO: turn this on
"react/prop-types": "off",
// matter of preference (allows to use props.propName instead of deconstructing props first)
"react/destructuring-assignment": "off",
// allow other than jsx extensions
"react/jsx-filename-extension": [1, { extensions: [".js", ".jsx", ".ts", ".tsx"] }],
// --------- Import Plugin Rules ---------
// ensure that all modules that are imported are actually declared in a package.json file
"import/no-extraneous-dependencies": ["error"],
// ensure that all modules that are imported can be resolved to a module on the local filesystem
"import/no-unresolved": [2, { caseSensitive: true }],
// if there is only a single export on a file, it does not have to be a default export
"import/prefer-default-export": "off",
// TODO: enable this rule at some point, we have quite a few circular imports due to type definitions being all over the place.
"import/no-cycle": ["off"],
// ensure consistent use of file extension within the import statements
"import/extensions": [
"error",
// ignore rule when importing from packages
"ignorePackages",
// ignore rule when importing from .js, .jsx, .ts, .tsx files
{
js: "never",
jsx: "never",
ts: "never",
tsx: "never",
},
],
},
overrides: [
{
files: [
"**/?(__)tests?(__)/**/*.[jt]s?(x)",
"**/?(*.)+(spec|test).[jt]s?(x)",
"**/mocks/**/*.[jt]s?(x)",
],
extends: ["plugin:testing-library/react"],
},
],
};
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ node_modules
.env
.envrc

# test results
coverage

# OS files
**/.DS_Store
**/Thumbs.db
Expand Down
8 changes: 6 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,21 @@ repos:
- id: eslint
name: Lint Typescript files
entry: ./invoke_yarn lint
files: ^front/.*
types_or: [javascript, jsx, ts, tsx]
language: script
require_serial: true
- id: prettier
name: Format Typescript files
entry: ./invoke_yarn format
files: ^front/.*
types_or: [javascript, jsx, ts, tsx]
language: script
require_serial: true
- id: tsc
name: Typecheck Typescript files
entry: ./invoke_yarn tsc
types_or: [ts, tsx]
language: script
require_serial: true
- id: generate-graphql-ts-types
name: Generate GraphQL Typescript definitions
entry: ./invoke_yarn graphql-types
Expand Down
File renamed without changes.
38 changes: 3 additions & 35 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,47 +8,15 @@

// prettier
"editor.defaultFormatter": "esbenp.prettier-vscode",
"prettier.stylelintIntegration": true,
"prettier.eslintIntegration": true,

"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
}
},
"[javascriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
}
},
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.codeActionsOnSave": {
"source.fixAll": true
}
},
"[typescriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.codeActionsOnSave": {
"source.fixAll": true
}
},
// eslint
"eslint.workingDirectories": ["./react"],
"editor.formatOnPaste": false, // required
"editor.formatOnType": false, // required
"editor.formatOnSave": true,
"eslint.alwaysShowStatus": true,
"files.autoSave": "onFocusChange",
"eslint.packageManager": "yarn", // optional but recommended

// eslint
"eslint.workingDirectories": ["./", "./front", "./shared-components", "./statviz"],
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
},
"[python]": {
"editor.defaultFormatter": "ms-python.python"
},
"[javascript][javascriptreact]": {
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
Expand Down
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ RUN yarn policies set-version $YARN_VERSION
# Copy the root package.json and yarn.lock.
COPY package.json .
COPY yarn.lock .
COPY shared-components shared-components

# Copy the service package.json and yarn.lock.
COPY ./${SERVICE_DIR}/package.json ${SERVICE_DIR}/
Expand Down
24 changes: 19 additions & 5 deletions back/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -335,16 +335,16 @@ For building a static web documentation of the schema, see [this directory](../d

For the production schema, documentation can be found online at `api.boxtribute.org/docs`.

### Playground
### GraphQL API explorer

You can experiment with the API in the GraphQL playground.
You can experiment with the API in the `GraphiQL` GraphQL explorer.

1. Activate the virtual environment
1. Start the required services by `docker-compose up webapp`
1. Open `localhost:5005/graphql` (or `/` for the query-only API; or `/public` for the statistics API, then the next steps can be skipped)
1. Open `localhost:5005/graphql` (or `/` for the query-only API; or `/public` for the statviz API, then the next steps can be skipped)
1. Simulate being a valid, logged-in user by fetching an authorization token: `./fetch_token --test`
1. Copy the displayed token
1. Insert the access token in the following format on the playground in the section on the bottom left of the playground called HTTP Headers.
1. Insert the access token in the following format in the section called 'Headers' on the bottom left of the explorer.

{ "authorization": "Bearer <the token you retrieved from Auth0>"}

Expand Down Expand Up @@ -400,7 +400,7 @@ Launch the production server by

ENVIRONMENT=production docker-compose up --build webapp

In production mode, inspection of the GraphQL server is disabled, i.e. it's not possible to run the GraphQL playground.
In production mode, inspection of the GraphQL server is disabled, i.e. it's not possible to use auto-completion the GraphQL explorer.

## Performance evaluation

Expand All @@ -410,6 +410,8 @@ Used in combination with [k6](https://k6.io/docs/). See the example [script](./s

### Profiling

#### Execution time

1. Add profiling middleware by extending `main.py`

import pathlib
Expand All @@ -433,6 +435,18 @@ Used in combination with [k6](https://k6.io/docs/). See the example [script](./s

1. Inspect the stack visualization in your web browser.

#### Memory

Several tools exist, e.g. [memray](https://github.com/bloomberg/memray) or [scalene](https://github.com/plasma-umass/scalene). Setting them up for analysing a complex application is not straightforward, and has only worked when running the Flask app outside of Docker, directly on the host machine.

For using memray,

1. the Flask app has to be registered in `setup.py` to be invoked from the CLI. Add the following to the `console_scripts` list: `"bserve = boxtribute_server.dev_main:run"`
1. Install the new CLI command: `pip install -U -e back/`
1. Start the server while recording profiling data: `memray run $(which bserve)`
1. Make requests to the server. Eventually stop the server.
1. Generate graphs with `memray flamegraph` or `memray table` and inspect them in your web browser.

## Authentication and Authorization

We use the [Auth0](https://auth0.com) web service to provide the app client with user authentication and authorization data (for short, auth and authz, resp.).
Expand Down
Loading

0 comments on commit 68ca62a

Please sign in to comment.