Skip to content

Commit

Permalink
Merge branch 'main' into renovate/actions-checkout-4.x
Browse files Browse the repository at this point in the history
  • Loading branch information
tdonaworth authored Sep 29, 2023
2 parents 52c3aaa + 3fc76aa commit daa4472
Show file tree
Hide file tree
Showing 103 changed files with 3,296 additions and 1,925 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/build_data_tools.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:

# https://github.com/docker/login-action
- name: Log in to the Container registry
uses: docker/login-action@465a07811f14bebb1938fbed4728c6a1ff8901fc # v2.2.0
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
Expand All @@ -49,7 +49,7 @@ jobs:

# https://github.com/docker/build-push-action/
- name: Build and push Docker image
uses: docker/build-push-action@0a97817b6ade9f46837855d676c4cca3a2471fc9 # v4.2.1
uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # v5.0.0
with:
context: "{{defaultContext}}:backend" # https://github.com/docker/build-push-action#git-context
push: true
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/unit_test_reusable.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ jobs:
- name: Upload logs as artifact
if: always() # Ensure this runs, even if E2E fails
uses: actions/upload-artifact@82c141cc518b40d92cc801eee768e7aafc9c2fa2 # v2
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3
with:
# Set the path to the log file
path: full-stack-logs.log
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ cd ./backend/ops_api
pytest
```

Note: All backend API endpoints have the abililty to simulate an error response, for testing purposes for the frontend. This is accomplished
through passing the `simulatedError=true` query parameter. It will automatically return a status code of 500 whenever this is done. It can
be customized further by choosing the status code and passing that, so `simulatedError=400` sends back a 400 code rather than a 500 code. This will override any other processing the endpoint would normally do and just return the response, giving a simple mechanism for frontend development and/or testing to validate it works with error conditions from the backend.

#### Frontend

The frontend tests are implemented through [Jest](https://jestjs.io).
Expand Down
4 changes: 3 additions & 1 deletion backend/data_tools/environment/dev.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
class DevConfig(DataToolsConfig):
@property
def db_connection_string(self) -> str:
return "postgresql://postgres:local_password@localhost:5432/postgres" # pragma: allowlist secret
return (
"postgresql://ops:ops@localhost:5432/postgres" # pragma: allowlist secret
)

@property
def opre_excel_connection_string(self) -> str:
Expand Down
4 changes: 2 additions & 2 deletions backend/data_tools/environment/local.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
class LocalConfig(DataToolsConfig):
@property
def db_connection_string(self) -> str:
return "postgresql://postgres:local_password@db:5432/postgres" # pragma: allowlist secret
return "postgresql://ops:ops@db:5432/postgres" # pragma: allowlist secret

@property
def opre_excel_connection_string(self) -> str:
return "excel:///?Excel File='/Users/jdeangelis/PycharmProjects/OPRE-OPS-2/data-tools/data/REDACTED - FY22 Budget Summary -10-12-22.xlsm'" # noqa: B950
return ""

@property
def verbosity(self) -> bool:
Expand Down
6 changes: 4 additions & 2 deletions backend/data_tools/environment/pytest.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@
class PytestConfig(DataToolsConfig):
@property
def db_connection_string(self) -> str:
return "postgresql://postgres:local_password@unittest_db:5432/postgres" # pragma: allowlist secret
return (
"postgresql://ops:ops@unittest_db:5432/postgres" # pragma: allowlist secret
)

@property
def opre_excel_connection_string(self) -> str:
return "excel:///?Excel File='/Users/jdeangelis/PycharmProjects/OPRE-OPS-2/data-tools/data/REDACTED - FY22 Budget Summary -10-12-22.xlsm'" # noqa: B950
return ""

@property
def verbosity(self) -> bool:
Expand Down
2 changes: 1 addition & 1 deletion backend/data_tools/environment/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ def db_connection_string(self) -> str:

@property
def opre_excel_connection_string(self) -> str:
return "excel:///?Excel File='/Users/jdeangelis/PycharmProjects/OPRE-OPS-2/data-tools/data/REDACTED - FY22 Budget Summary -10-12-22.xlsm'" # noqa: B950
return ""

@property
def verbosity(self) -> bool:
Expand Down
3 changes: 3 additions & 0 deletions backend/data_tools/ops_db_sql_init/1_init.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
CREATE SCHEMA ops;
CREATE USER ops WITH PASSWORD 'ops';
GRANT ALL ON SCHEMA ops TO ops;
4 changes: 3 additions & 1 deletion backend/data_tools/tests/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ version: "3.8"
services:

db:
image: "postgres:12"
image: "postgres:16"
platform: linux/amd64
container_name: unit-test-db
security_opt:
Expand All @@ -12,5 +12,7 @@ services:
- POSTGRES_PASSWORD=local_password # pragma: allowlist secret
read_only: true # Resolve semgrep https://sg.run/e4JE
tmpfs: /var/run/postgresql/
volumes:
- ../ops_db_sql_init:/docker-entrypoint-initdb.d
ports:
- "54321:5432"
8 changes: 1 addition & 7 deletions backend/models/cans.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,7 @@
case,
select,
)
from sqlalchemy.orm import (
InstrumentedAttribute,
column_property,
object_session,
relationship,
with_polymorphic,
)
from sqlalchemy.orm import InstrumentedAttribute, column_property, object_session, relationship, with_polymorphic
from typing_extensions import override


Expand Down
1 change: 0 additions & 1 deletion backend/models/users.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,4 +124,3 @@ class Group(BaseModel):
@BaseModel.display_name.getter
def display_name(self):
return self.name

2 changes: 1 addition & 1 deletion backend/ops_api/Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ name = "pypi"
[packages]
sqlalchemy = "==2.0.21"
flask = "==2.3.3"
mypy = "==0.991"
mypy = "==1.4.0"
flask-jwt-extended = {extras = ["asymmetric_crypto"], version = "==4.5.2"}
authlib = "==1.2.1"
requests = "==2.31.0"
Expand Down
85 changes: 41 additions & 44 deletions backend/ops_api/Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions backend/ops_api/ops/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def configure_logging(log_level: str = "INFO") -> None:
)


def create_app(config_overrides: Optional[dict[str, Any]] = {}) -> Flask:
def create_app(config_overrides: Optional[dict[str, Any]] = None) -> Flask:
is_unit_test = False if config_overrides is None else config_overrides.get("TESTING") is True
log_level = "INFO" if not is_unit_test else "DEBUG"
configure_logging(log_level) # should be configured before any access to app.logger
Expand All @@ -53,7 +53,7 @@ def create_app(config_overrides: Optional[dict[str, Any]] = {}) -> Flask:
# fall back for pytest to use
app.config.setdefault(
"SQLALCHEMY_DATABASE_URI",
"postgresql+psycopg2://postgres:local_password@localhost:5432/postgres",
"postgresql+psycopg2://ops:ops@localhost:5432/postgres",
)

if config_overrides is not None:
Expand Down
5 changes: 5 additions & 0 deletions backend/ops_api/ops/base_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from marshmallow import Schema, ValidationError
from models.base import BaseModel
from ops_api.ops.utils.auth import auth_gateway
from ops_api.ops.utils.errors import error_simulator
from ops_api.ops.utils.response import make_response_with_headers
from sqlalchemy import select
from sqlalchemy.exc import SQLAlchemyError
Expand Down Expand Up @@ -99,6 +100,7 @@ def __init__(self, model: BaseModel):

@override
@jwt_required()
@error_simulator
def get(self, id: int) -> Response:
return self._get_item_with_try(id)

Expand All @@ -109,11 +111,13 @@ def __init__(self, model: BaseModel):

@override
@jwt_required()
@error_simulator
def get(self) -> Response:
return self._get_all_items_with_try()

@override
@jwt_required()
@error_simulator
def post(self) -> Response:
raise NotImplementedError

Expand All @@ -130,6 +134,7 @@ def __init__(self, enum: Enum, **kwargs):

@override
@jwt_required()
@error_simulator
def get(self) -> Response:
enum_items = {e.name: e.value for e in self.enum} # type: ignore [attr-defined]
return jsonify(enum_items)
1 change: 0 additions & 1 deletion backend/ops_api/ops/environment/default_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

DEBUG = False # make sure DEBUG is off unless enabled explicitly otherwise

# SQLALCHEMY_DATABASE_URI = "postgresql+psycopg2://postgres:local_password@localhost:5432/postgres"
SQLALCHEMY_TRACK_MODIFICATIONS = False
SQLALCHEMY_ECHO = False

Expand Down
4 changes: 1 addition & 3 deletions backend/ops_api/ops/environment/dev.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
DEBUG = True # make sure DEBUG is off unless enabled explicitly otherwise

# pragma: allowlist secret
SQLALCHEMY_DATABASE_URI = (
"postgresql+psycopg2://postgres:local_password@localhost:5432/postgres" # pragma: allowlist secret
)
SQLALCHEMY_DATABASE_URI = "postgresql+psycopg2://ops:ops@localhost:5432/postgres" # pragma: allowlist secret
SQLALCHEMY_ECHO = False
3 changes: 1 addition & 2 deletions backend/ops_api/ops/environment/local/container.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
DEBUG = True # make sure DEBUG is off unless enabled explicitly otherwise

# pragma: allowlist secret
SQLALCHEMY_DATABASE_URI = "postgresql+psycopg2://postgres:local_password@db:5432/postgres" # pragma: allowlist secret
# SQLALCHEMY_DATABASE_URI = "postgresql+psycopg2://postgres:local_password@localhost:5432/postgres" # pragma: allowlist secret
SQLALCHEMY_DATABASE_URI = "postgresql+psycopg2://ops:ops@db:5432/postgres" # pragma: allowlist secret
SQLALCHEMY_ECHO = False

AUTHLIB_OAUTH_CLIENTS = {
Expand Down
3 changes: 1 addition & 2 deletions backend/ops_api/ops/environment/local/e2e.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
DEBUG = True # make sure DEBUG is off unless enabled explicitly otherwise

# pragma: allowlist secret
SQLALCHEMY_DATABASE_URI = "postgresql+psycopg2://postgres:local_password@db:5432/postgres" # pragma: allowlist secret
# SQLALCHEMY_DATABASE_URI = "postgresql+psycopg2://postgres:local_password@localhost:5432/postgres" # pragma: allowlist secret
SQLALCHEMY_DATABASE_URI = "postgresql+psycopg2://ops:ops@db:5432/postgres" # pragma: allowlist secret
SQLALCHEMY_ECHO = False

AUTHLIB_OAUTH_CLIENTS = {
Expand Down
4 changes: 1 addition & 3 deletions backend/ops_api/ops/environment/local/localhost.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@
DEBUG = True # make sure DEBUG is off unless enabled explicitly otherwise

# pragma: allowlist secret
SQLALCHEMY_DATABASE_URI = (
"postgresql+psycopg2://postgres:local_password@localhost:5432/postgres" # pragma: allowlist secret
)
SQLALCHEMY_DATABASE_URI = "postgresql+psycopg2://ops:ops@localhost:5432/postgres" # pragma: allowlist secret
SQLALCHEMY_ECHO = False

AUTHLIB_OAUTH_CLIENTS = {
Expand Down
3 changes: 2 additions & 1 deletion backend/ops_api/ops/resources/agreements.py
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,8 @@ def _get_query(args):
pass # Do nothing if only filters are provided

for key, value in filter_args.items():
query_helper.add_column_equals(Agreement.get_class_field(key), value)
with suppress(ValueError):
query_helper.add_column_equals(Agreement.get_class_field(key), value)

stmt = query_helper.get_stmt()
current_app.logger.debug(f"SQL: {stmt}")
Expand Down
2 changes: 2 additions & 0 deletions backend/ops_api/ops/resources/cans.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from models.base import BaseModel
from models.cans import CAN
from ops_api.ops.base_views import BaseItemAPI, BaseListAPI
from ops_api.ops.utils.errors import error_simulator
from ops_api.ops.utils.query_helpers import QueryHelper
from ops_api.ops.utils.response import make_response_with_headers
from sqlalchemy import select
Expand Down Expand Up @@ -46,6 +47,7 @@ def _get_query(search=None):
return stmt

@jwt_required(True) # For an example case, we're allowing CANs to be queried unauthed
@error_simulator
def get(self) -> Response:
errors = self._get_input_schema.validate(request.args)

Expand Down
Loading

0 comments on commit daa4472

Please sign in to comment.