diff --git a/.github/actions/setup-python/action.yml b/.github/actions/setup-python/action.yml index 462856f1c3..f8ac0e123d 100644 --- a/.github/actions/setup-python/action.yml +++ b/.github/actions/setup-python/action.yml @@ -4,7 +4,7 @@ runs: using: composite steps: - name: Set up Python - uses: actions/setup-python@1928ae624dc06094d8c65f021a4700ea8fa56b9d # tag: v4.3.0 + uses: actions/setup-python@b8cf3eb1ebc9c7f906e4ca96fcdf2e289e25d230 # tag: v4.3.0 with: python-version: '3.12' cache: pipenv diff --git a/.github/actions/tf-apply/action.yaml b/.github/actions/tf-apply/action.yaml index 097a433373..a32d6bbb92 100644 --- a/.github/actions/tf-apply/action.yaml +++ b/.github/actions/tf-apply/action.yaml @@ -71,7 +71,7 @@ runs: - name: Twingate Connect if: ${{ inputs.twingate_service_key != '' }} # Corrected syntax with a colon after the condition - uses: twingate/github-action@cbdfc51acb6e7f9ea5a09553b6bf4a1d1ed94ea5 + uses: twingate/github-action@5b0cf3702f5da691303c8e31626b0ef48b880278 with: service-key: ${{ inputs.twingate_service_key }} diff --git a/.github/workflows/nightly_scans.yml b/.github/workflows/nightly_scans.yml index 43b3523b26..69cca9c96a 100644 --- a/.github/workflows/nightly_scans.yml +++ b/.github/workflows/nightly_scans.yml @@ -34,6 +34,6 @@ jobs: uses: SvanBoxel/zaproxy-to-ghas@cfc77481d74a17a4c3d6b753aa9d7abef453d501 # v1.0.2 - name: Upload SARIF file - uses: github/codeql-action/upload-sarif@b6a472f63d85b9c78a3ac5e89422239fc15e9b3c # v3 + uses: github/codeql-action/upload-sarif@d68b2d4edb4189fd2a5366ac14e72027bd4b37dd # v3 with: sarif_file: results.sarif diff --git a/.github/workflows/security_codeql.yml b/.github/workflows/security_codeql.yml index b136a488c6..c530377ea4 100644 --- a/.github/workflows/security_codeql.yml +++ b/.github/workflows/security_codeql.yml @@ -22,7 +22,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@b6a472f63d85b9c78a3ac5e89422239fc15e9b3c # v3 + uses: github/codeql-action/init@d68b2d4edb4189fd2a5366ac14e72027bd4b37dd # v3 with: languages: javascript, python # If you wish to specify custom queries, you can do so here or in a config file. @@ -33,4 +33,4 @@ jobs: queries: +security-extended - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@b6a472f63d85b9c78a3ac5e89422239fc15e9b3c # v3 + uses: github/codeql-action/analyze@d68b2d4edb4189fd2a5366ac14e72027bd4b37dd # v3 diff --git a/.github/workflows/security_semgrep.yml b/.github/workflows/security_semgrep.yml index 42911202f4..cd230b901d 100644 --- a/.github/workflows/security_semgrep.yml +++ b/.github/workflows/security_semgrep.yml @@ -25,7 +25,7 @@ jobs: SEMGREP_RULES: "p/default" - name: Upload SARIF file for GitHub Advanced Security Dashboard - uses: github/codeql-action/upload-sarif@b6a472f63d85b9c78a3ac5e89422239fc15e9b3c # v3 + uses: github/codeql-action/upload-sarif@d68b2d4edb4189fd2a5366ac14e72027bd4b37dd # v3 with: sarif_file: ${{ env.SEMGREP_TO_UPLOAD }} if: always() diff --git a/backend/alembic/versions/2025_01_21_0619-6e35b193a666_updating_can_funding_source_enum.py b/backend/alembic/versions/2025_01_21_0619-6e35b193a666_updating_can_funding_source_enum.py new file mode 100644 index 0000000000..08068cc921 --- /dev/null +++ b/backend/alembic/versions/2025_01_21_0619-6e35b193a666_updating_can_funding_source_enum.py @@ -0,0 +1,42 @@ +"""updating CAN Funding Source enum + +Revision ID: 6e35b193a666 +Revises: 0536c9a5d32e +Create Date: 2025-01-21 06:19:03.550866+00:00 + +""" +from typing import Sequence, Union + +import sqlalchemy as sa +from alembic import op +from alembic_postgresql_enum import TableReference + +# revision identifiers, used by Alembic. +revision: str = '6e35b193a666' +down_revision: Union[str, None] = '0536c9a5d32e' +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.sync_enum_values( + enum_schema='ops', + enum_name='canfundingsource', + new_values=['OPRE', 'ACF', 'ACF_MOU', 'HHS', 'OTHER'], + affected_columns=[TableReference(table_schema='ops', table_name='can_funding_details', column_name='funding_source'), TableReference(table_schema='ops', table_name='can_funding_details_version', column_name='funding_source')], + enum_values_to_rename=[], + ) + # ### end Alembic commands ### + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.sync_enum_values( + enum_schema='ops', + enum_name='canfundingsource', + new_values=['OPRE', 'ACF', 'HHS'], + affected_columns=[TableReference(table_schema='ops', table_name='can_funding_details', column_name='funding_source'), TableReference(table_schema='ops', table_name='can_funding_details_version', column_name='funding_source')], + enum_values_to_rename=[], + ) + # ### end Alembic commands ### diff --git a/backend/models/cans.py b/backend/models/cans.py index 031e23c8d8..b9ddd33774 100644 --- a/backend/models/cans.py +++ b/backend/models/cans.py @@ -34,7 +34,9 @@ class CANFundingSource(Enum): OPRE = auto() ACF = auto() + ACF_MOU = auto() HHS = auto() + OTHER = auto() class CAN(BaseModel): diff --git a/backend/openapi.yml b/backend/openapi.yml index 7d576e8736..873ee86693 100644 --- a/backend/openapi.yml +++ b/backend/openapi.yml @@ -2964,7 +2964,9 @@ components: enum: - OPRE - ACF + - ACF_MOU - HHS + - OTHER method_of_transfer: type: string enum: @@ -2998,7 +3000,9 @@ components: enum: - OPRE - ACF + - ACF_MOU - HHS + - OTHER id: type: integer method_of_transfer: diff --git a/backend/ops_api/ops/services/can_funding_summary.py b/backend/ops_api/ops/services/can_funding_summary.py index ed1ee8dda2..c753fe8c80 100644 --- a/backend/ops_api/ops/services/can_funding_summary.py +++ b/backend/ops_api/ops/services/can_funding_summary.py @@ -83,8 +83,6 @@ def get_can_funding_summary_request_data(request): @staticmethod def get_mapped_transfer_value(transfer: list[str]) -> tuple[bool, Optional[List[CANMethodOfTransfer]]]: - if "MOU" in transfer: - transfer[transfer.index("MOU")] = "COST_SHARE" try: transfer = [CANMethodOfTransfer[t] for t in transfer] except KeyError: diff --git a/backend/ops_api/tests/ops/funding_summary/test_can_funding_summary.py b/backend/ops_api/tests/ops/funding_summary/test_can_funding_summary.py index ded5d1e02b..7690d2d412 100644 --- a/backend/ops_api/tests/ops/funding_summary/test_can_funding_summary.py +++ b/backend/ops_api/tests/ops/funding_summary/test_can_funding_summary.py @@ -42,22 +42,22 @@ def test_can_get_can_funding_summary_fy_budget(auth_client: FlaskClient): def test_can_get_can_funding_summary_duplicate_transfer(auth_client: FlaskClient): - query_params = f"can_ids={0}&fiscal_year=2023&transfer=MOU&transfer=MOU" + query_params = f"can_ids={0}&fiscal_year=2023&transfer=COST_SHARE&transfer=COST_SHARE" response = auth_client.get(f"/api/v1/can-funding-summary?{query_params}") assert response.status_code == 200 assert len(response.json["cans"]) == 0 def test_can_get_can_funding_summary_cost_share_transfer(auth_client: FlaskClient): - query_params = f"can_ids={0}&fiscal_year=2023&transfer=COST_SHARE" + query_params = f"can_ids={0}&fiscal_year=2021&transfer=COST_SHARE" response = auth_client.get(f"/api/v1/can-funding-summary?{query_params}") assert response.status_code == 200 - assert len(response.json["cans"]) == 0 + assert len(response.json["cans"]) == 1 assert response.json["expected_funding"] == "0.0" - assert response.json["received_funding"] == "0.0" - assert response.json["total_funding"] == "0.0" + assert response.json["received_funding"] == "200000.0" + assert response.json["total_funding"] == "200000.0" def test_can_get_can_funding_summary_invalid_transfer(auth_client: FlaskClient): @@ -67,13 +67,6 @@ def test_can_get_can_funding_summary_invalid_transfer(auth_client: FlaskClient): assert response.json["Error"] == "Invalid 'transfer' value. Must be one of: DIRECT, COST_SHARE, IAA, IDDA, OTHER." -def test_can_get_can_funding_summary_mou_transfer(auth_client: FlaskClient): - query_params = f"can_ids={0}&fiscal_year=2023&transfer=MOU" - response = auth_client.get(f"/api/v1/can-funding-summary?{query_params}") - assert response.status_code == 200 - assert len(response.json["cans"]) == 0 - - def test_can_get_can_funding_summary_all_cans_fiscal_year_match(auth_client: FlaskClient) -> None: query_params = f"can_ids={0}&fiscal_year=2023" diff --git a/frontend/Dockerfile b/frontend/Dockerfile index d1f293ef5a..4c28b0f02f 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -1,4 +1,4 @@ -FROM oven/bun@sha256:c644717831b531f8fba049ddde9bb34f452bd75c4184f1e9a643ec4537be16de +FROM oven/bun@sha256:eeb5977d3987150b32d45b493c2fa0d8449065a9feb579cc8d7fcdeeabe6e862 # hadolint ignore=DL3008 RUN apt-get update && apt-get -y --no-install-recommends install unzip && apt-get clean && rm -rf /var/lib/apt/lists/* RUN useradd -ms /bin/bash app diff --git a/frontend/Dockerfile.azure b/frontend/Dockerfile.azure index 33e9b86d89..a8ecd98580 100644 --- a/frontend/Dockerfile.azure +++ b/frontend/Dockerfile.azure @@ -1,6 +1,6 @@ # ---- Build Stage ---- # alpine -FROM oven/bun@sha256:c644717831b531f8fba049ddde9bb34f452bd75c4184f1e9a643ec4537be16de as build +FROM oven/bun@sha256:eeb5977d3987150b32d45b493c2fa0d8449065a9feb579cc8d7fcdeeabe6e862 as build RUN apt-get update && apt-get -y install unzip=6.0-26+deb11u1 --no-install-recommends && apt-get clean && rm -rf /var/lib/apt/lists/* WORKDIR /home/bun/app diff --git a/frontend/bun.lockb b/frontend/bun.lockb index e7be6c7122..03d2d45a43 100755 Binary files a/frontend/bun.lockb and b/frontend/bun.lockb differ diff --git a/frontend/package.json b/frontend/package.json index 7dc2b12b3a..ae36eebd91 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -50,7 +50,7 @@ "sass-loader": "16.0.4", "styled-components": "6.1.13", "vest": "5.4.6", - "vite": "5.4.11", + "vite": "5.4.12", "vite-jsconfig-paths": "2.0.1", "vite-plugin-babel-macros": "1.0.6", "vite-plugin-eslint": "1.8.1", diff --git a/frontend/src/components/CANs/CAN.constants.js b/frontend/src/components/CANs/CAN.constants.js index fb1b9835ff..c51e44e62f 100644 --- a/frontend/src/components/CANs/CAN.constants.js +++ b/frontend/src/components/CANs/CAN.constants.js @@ -5,3 +5,11 @@ export const CAN_TRANSFER = { IAA: "IAA", OTHER: "OTHER" }; + +export const CAN_FUNDING_SOURCE = { + OPRE: "OPRE", + ACF: "ACF", + ACF_MOU: "ACF MOU", + HHS: "HHS", + OTHER: "Other" +}; diff --git a/frontend/src/components/CANs/CANTypes.d.ts b/frontend/src/components/CANs/CANTypes.d.ts index 9b0ebb9430..d1ab9d2f6a 100644 --- a/frontend/src/components/CANs/CANTypes.d.ts +++ b/frontend/src/components/CANs/CANTypes.d.ts @@ -75,7 +75,7 @@ export type FundingDetails = { fiscal_year: number; fund_code: string; funding_partner?: string; - funding_source?: "OPRE" | "ACF" | "HHS"; + funding_source?: keyof typeof CAN_FUNDING_SOURCE; funding_method?: "Direct" | "Reimbursable"; funding_received?: "Quarterly" | "FY Start"; funding_type?: "Discretionary" | "Mandatory";