Skip to content

Commit

Permalink
Val -> Prod (#743)
Browse files Browse the repository at this point in the history
  • Loading branch information
jessabean authored Aug 27, 2024
2 parents 87d6c5c + 0448195 commit 5a44b68
Show file tree
Hide file tree
Showing 40 changed files with 947 additions and 540 deletions.
57 changes: 47 additions & 10 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -108,18 +108,38 @@ jobs:
echo "application_endpoint=$APPLICATION_ENDPOINT" >> $GITHUB_OUTPUT
echo "## Application Endpoint" >> $GITHUB_STEP_SUMMARY
echo "<$APPLICATION_ENDPOINT>" >> $GITHUB_STEP_SUMMARY
- id: api_endpoint
- id: api_name
run: |
API_ENDPOINT=$(./scripts/output.sh app-api ApiGatewayRestApiUrl $STAGE_PREFIX$branch_name)
echo "API_ENDPOINT=$API_ENDPOINT" >> $GITHUB_ENV
- id: cognito_user_pool_id
API_NAME=$(./scripts/output.sh app-api ApiGatewayRestApiName $STAGE_PREFIX$branch_name)
echo "api_name=$API_NAME" >> $GITHUB_OUTPUT
- id: branch_name
run: |
echo "branch_name=$branch_name" >> $GITHUB_OUTPUT
- id: cognito_user_pool_client_id
run: |
COGNITO_USER_POOL_CLIENT_ID=$(./scripts/output.sh ui-auth UserPoolClientId $STAGE_PREFIX$branch_name)
echo "cognito_user_pool_client_id=$COGNITO_USER_POOL_CLIENT_ID" >> $GITHUB_OUTPUT
- id: cognito_user_pool_id_encrypted
run: |
COGNITO_USER_POOL_ID=$(./scripts/output.sh ui-auth UserPoolId $STAGE_PREFIX$branch_name)
echo "COGNITO_USER_POOL_ID=$COGNITO_USER_POOL_ID" >> $GITHUB_ENV
COGNITO_USER_POOL_ID_ENCRYPTED=$(echo -n "$COGNITO_USER_POOL_ID" | openssl enc -e -aes-256-cbc -a -pbkdf2 -iter 10000 -k "${{ secrets.CODE_CLIMATE_ID }}")
echo "cognito_user_pool_id_encrypted<<EOF" >> $GITHUB_OUTPUT
echo $COGNITO_USER_POOL_ID_ENCRYPTED >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- id: region_encrypted
run: |
REGION=$(./scripts/output.sh app-api Region $STAGE_PREFIX$branch_name)
REGION_ENCRYPTED=$(echo -n "$REGION" | openssl enc -e -aes-256-cbc -a -pbkdf2 -iter 10000 -k "${{ secrets.CODE_CLIMATE_ID }}")
echo "region_encrypted<<EOF" >> $GITHUB_OUTPUT
echo $REGION_ENCRYPTED >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
outputs:
application_endpoint: ${{ steps.endpoint.outputs.application_endpoint}}
api_endpoint: ${{ steps.api_endpoint.outputs.api_endpoint}}
cognito_user_pool_id: ${{ steps.cognito_user_pool_id.outputs.cognito_user_pool_id}}
api_name: ${{ steps.api_name.outputs.api_name }}
application_endpoint: ${{ steps.endpoint.outputs.application_endpoint }}
branch_name: ${{ steps.branch_name.outputs.branch_name }}
cognito_user_pool_client_id: ${{ steps.cognito_user_pool_client_id.outputs.cognito_user_pool_client_id }}
cognito_user_pool_id_encrypted: ${{ steps.cognito_user_pool_id_encrypted.outputs.cognito_user_pool_id_encrypted }}
region_encrypted: ${{ steps.region_encrypted.outputs.region_encrypted }}
BRANCH_SPECIFIC_VARNAME_AWS_DEFAULT_REGION: ${{ steps.set_names.outputs.BRANCH_SPECIFIC_VARNAME_AWS_DEFAULT_REGION }}
BRANCH_SPECIFIC_VARNAME_AWS_OIDC_ROLE_TO_ASSUME: ${{ steps.set_names.outputs.BRANCH_SPECIFIC_VARNAME_AWS_OIDC_ROLE_TO_ASSUME }}

Expand Down Expand Up @@ -300,6 +320,22 @@ jobs:
- uses: actions/setup-node@v4
with:
node-version-file: ".nvmrc"
- name: Decrypt cognito_user_pool_id
run: |
COGNITO_USER_POOL_ID_ENCRYPTED=${{ needs.deploy.outputs.cognito_user_pool_id_encrypted }}
COGNITO_USER_POOL_ID_DECRYPTED=$(echo "$COGNITO_USER_POOL_ID_ENCRYPTED" | openssl base64 -d)
COGNITO_USER_POOL_ID=$(echo -n "$COGNITO_USER_POOL_ID_DECRYPTED" | openssl enc -d -aes-256-cbc -pbkdf2 -iter 10000 -k "${{ secrets.CODE_CLIMATE_ID }}")
echo "cognito_user_pool_id<<EOF" >> $GITHUB_ENV
echo $COGNITO_USER_POOL_ID >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
- name: Decrypt region
run: |
REGION_ENCRYPTED=${{ needs.deploy.outputs.region_encrypted }}
REGION_DECRYPTED=$(echo "$REGION_ENCRYPTED" | openssl base64 -d)
REGION=$(echo -n "$REGION_DECRYPTED" | openssl enc -d -aes-256-cbc -pbkdf2 -iter 10000 -k "${{ secrets.CODE_CLIMATE_ID }}")
echo "region<<EOF" >> $GITHUB_ENV
echo $REGION >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
- name: yarn install
run: yarn install
- name: Install Playwright Browsers
Expand All @@ -308,9 +344,10 @@ jobs:
run: yarn playwright test
continue-on-error: true
env:
API_URL: ${{ needs.deploy.outputs.api_endpoint }}
API_URL: https://${{ needs.deploy.outputs.api_name }}.execute-api.${{ env.region }}.amazonaws.com/${{ needs.deploy.outputs.branch_name }}
BASE_URL: ${{ needs.deploy.outputs.application_endpoint }}
COGNITO_USER_POOL_ID: ${{ needs.deploy.outputs.cognito_user_pool_id }}
COGNITO_USER_POOL_CLIENT_ID: ${{ needs.deploy.outputs.cognito_user_pool_client_id }}
COGNITO_USER_POOL_ID: ${{ env.cognito_user_pool_id }}
CYPRESS_STATE_USER_EMAIL: ${{ secrets.CYPRESS_STATE_USER_EMAIL }}
CYPRESS_STATE_USER_PASSWORD: ${{ secrets.CYPRESS_STATE_USER_PASSWORD }}
CYPRESS_ADMIN_USER_EMAIL: ${{ secrets.CYPRESS_ADMIN_USER_EMAIL }}
Expand Down
15 changes: 0 additions & 15 deletions .github/workflows/post-deploy-slack-notification.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ on:
- 'main'
- 'val'
- 'production'
- 'snyk-**'

jobs:
notify_on_failure:
Expand All @@ -24,20 +23,6 @@ jobs:
MSG_MINIMAL: true
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}

# Notify the integrations channel only when a Snyk auto merge fails
notify_failed_snyk_auto_merge:
runs-on: ubuntu-latest
#only check branch names that begin with snyk-
if: ${{ github.event.workflow_run.conclusion == 'failure' && startsWith(github.event.workflow_run.head_branch, 'snyk-') }}
steps:
- name: Slack Notification
uses: rtCamp/action-slack-notify@v2
env:
SLACK_TITLE: ":boom: A Synk auto merge has failed in ${{ github.repository }}"
SLACK_MESSAGE: "${{ github.event.workflow_run.html_url }}"
MSG_MINIMAL: true
SLACK_WEBHOOK: ${{ secrets.INTEGRATIONS_SLACK_WEBHOOK }}

# Sends a slack message to the mdct-prod-releases channel in CMS slack
notify_on_prod_release:
runs-on: ubuntu-latest
Expand Down
15 changes: 0 additions & 15 deletions .github/workflows/pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,3 @@ jobs:
PRNUM: ${{ github.event.pull_request.number }}
PR_AUTHOR: ${{ github.event.pull_request.user.login }}
PR_AUTHOR_TYPE: ${{ github.event.pull_request.user.type }}

#Notify the integrations channel only when a Snyk auto merge fails pr checks
notify_on_pr_failure:
runs-on: ubuntu-latest
needs:
- prchecks
#only check branch names that begin with snyk-
if: ${{ failure() && startsWith(github.head_ref, 'snyk-') }}
steps:
- name: Slack Notification
uses: rtCamp/action-slack-notify@v2
env:
SLACK_TITLE: ":boom: A Synk auto merge has failed pull request checks in ${{ github.repository }}."
MSG_MINIMAL: true
SLACK_WEBHOOK: ${{ secrets.INTEGRATIONS_SLACK_WEBHOOK }}
24 changes: 0 additions & 24 deletions .github/workflows/snyk-auto-merge.yml

This file was deleted.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"@enterprise-cmcs/serverless-waf-plugin": "^1.4.0"
},
"devDependencies": {
"@axe-core/playwright": "^4.10.0",
"@faker-js/faker": "^8.4.1",
"@playwright/test": "^1.44.0",
"@serverless/compose": "^1.3.0",
Expand Down
8 changes: 0 additions & 8 deletions services/app-api/db/seed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { currentYear } from "../../../tests/seeds/helpers";
import {
bannerKey,
createApprovedWorkPlan,
createArchivedSemiAnnualReport,
createArchivedWorkPlan,
createBanner,
createFilledSemiAnnualReport,
Expand Down Expand Up @@ -303,13 +302,6 @@ const seed = async (): Promise<void> => {
);
break;
}
case "createArchivedSAR": {
createdLog(
await createArchivedSemiAnnualReport(reportYear, reportPeriod),
"Archived SAR"
);
break;
}
case "getSARsByState":
expandedLog(await getSemiAnnualReportsByState());
break;
Expand Down
16 changes: 15 additions & 1 deletion services/app-api/handlers/reports/archive.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { archiveReport } from "./archive";
// utils
import { proxyEvent } from "../../utils/testing/proxyEvent";
import { mockWPReport } from "../../utils/testing/setupJest";
import {
mockWPReport,
mockWPReportWithAssociatedSar,
} from "../../utils/testing/setupJest";
import { error } from "../../utils/constants/constants";
import { getReportMetadata, putReportMetadata } from "../../storage/reports";
// types
Expand Down Expand Up @@ -73,4 +76,15 @@ describe("Test archiveReport method", () => {
expect(res.statusCode).toBe(StatusCodes.UNAUTHORIZED);
expect(res.body).toContain(error.UNAUTHORIZED);
});

test("Test archive report with associatedSar throws 400", async () => {
mockAuthUtil.hasPermissions.mockReturnValueOnce(true);
(getReportMetadata as jest.Mock).mockResolvedValue(
mockWPReportWithAssociatedSar
);
const res = await archiveReport(archiveEvent, null);
expect(consoleSpy.debug).toHaveBeenCalled();
expect(res.statusCode).toBe(StatusCodes.BAD_REQUEST);
expect(res.body).toContain(error.INVALID_DATA);
});
});
15 changes: 11 additions & 4 deletions services/app-api/handlers/reports/archive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { hasPermissions } from "../../utils/auth/authorization";
import { parseSpecificReportParameters } from "../../utils/auth/parameters";
import { getReportMetadata, putReportMetadata } from "../../storage/reports";
// types
import { StatusCodes, UserRoles } from "../../utils/types";
import { ReportType, StatusCodes, UserRoles } from "../../utils/types";

export const archiveReport = handler(async (event) => {
const { allParamsValid, reportType, state, id } =
Expand All @@ -26,6 +26,15 @@ export const archiveReport = handler(async (event) => {
}

const currentReport = await getReportMetadata(reportType, state, id);
const hasAssociatedSar = currentReport?.associatedSar;

// WP with associated SAR cannot be archived
if (reportType !== ReportType.WP || hasAssociatedSar) {
return {
status: StatusCodes.BAD_REQUEST,
body: error.INVALID_DATA,
};
}

if (!currentReport) {
return {
Expand All @@ -34,11 +43,9 @@ export const archiveReport = handler(async (event) => {
};
}

const currentArchivedStatus = currentReport?.archived;

const updatedReport = {
...currentReport,
archived: !currentArchivedStatus,
archived: true,
};

try {
Expand Down
16 changes: 16 additions & 0 deletions services/app-api/utils/testing/mocks/mockReport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,22 @@ export const mockWPReport = {
lastAltered: 162515200000,
};

export const mockWPReportWithAssociatedSar = {
...mockReportKeys,
metadata: {
reportType: "WP",
submissionName: "testProgram",
status: "Submitted",
lastAlteredBy: "Thelonious States",
fieldDataId: "mockReportFieldData",
formTemplateId: "mockReportJson",
},
formTemplate: { ...mockReportJson },
fieldData: { ...mockReportFieldData },
createdAt: 162515200000,
lastAltered: 162515200000,
associatedSar: "mock-sar-id",
};
export const mockWPDynamoData = {
...mockReportKeys,
reportType: "WP",
Expand Down
4 changes: 2 additions & 2 deletions services/ui-src/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@
"react-error-boundary": "^3.1.4",
"react-hook-form": "^7.52.1",
"react-icons": "^4.12.0",
"react-router-dom": "6.24.1",
"react-router-dom": "6.25.1",
"react-uuid": "^1.0.3",
"sass": "^1.77.8",
"vite": "^5.2.12",
"vite": "^5.3.4",
"vite-tsconfig-paths": "^4.3.2",
"yup": "^0.32.11",
"zustand": "^4.5.2"
Expand Down
4 changes: 2 additions & 2 deletions services/ui-src/src/components/layout/Timeout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
UserContext,
} from "utils";
import { PROMPT_AT, IDLE_WINDOW } from "../../constants";
import moment from "moment";
import { add } from "date-fns";

export const Timeout = () => {
const context = useContext(UserContext);
Expand All @@ -43,7 +43,7 @@ export const Timeout = () => {
}, [location]);

const setTimer = () => {
const expiration = moment().add(IDLE_WINDOW, "milliseconds");
const expiration = add(Date.now(), { seconds: IDLE_WINDOW / 1000 });
if (timeoutPromptId) {
clearTimers();
}
Expand Down
79 changes: 79 additions & 0 deletions services/ui-src/src/components/modals/ArchiveReportModal.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { render, screen } from "@testing-library/react";
import { useStore } from "utils";
import {
mockReportMethods,
mockUseStore,
mockWPFullReport,
RouterWrappedComponent,
} from "utils/testing/setupJest";
import { ReportContext } from "components/reports/ReportProvider";
import { testA11yAct } from "utils/testing/commonTests";
import userEvent from "@testing-library/user-event";
import { ArchiveReportModal } from "./ArchiveReportModal";
import wpVerbiage from "verbiage/pages/wp/wp-dashboard";

jest.mock("utils/state/useStore");

const mockFetchReportsByState = jest.fn();
const mockCloseHandler = jest.fn();

const mockedUseStore = useStore as jest.MockedFunction<typeof useStore>;

const report = {
...mockWPFullReport,
};

const modalComponent = (
<RouterWrappedComponent>
<ReportContext.Provider value={mockReportMethods}>
<ArchiveReportModal
adminState={report.state}
archiveReport={mockReportMethods.archiveReport}
reportId={report.id}
reportType={report.reportType}
fetchReportsByState={mockFetchReportsByState}
modalDisclosure={{
isOpen: true,
onClose: mockCloseHandler,
}}
/>
</ReportContext.Provider>
</RouterWrappedComponent>
);

describe("<ArchiveReportModal />", () => {
describe("Test ArchiveReportModal", () => {
beforeEach(async () => {
mockedUseStore.mockReturnValue(mockUseStore);
render(modalComponent);
});

afterEach(() => {
jest.clearAllMocks();
});

test("the modal opens with correct content", () => {
expect(screen.getByText(wpVerbiage.modalArchive.heading)).toBeTruthy();
expect(screen.getByText(wpVerbiage.modalArchive.body)).toBeTruthy();
expect(screen.getByRole("button", { name: "Cancel" })).toBeTruthy();
expect(screen.getByRole("button", { name: "Archive" })).toBeTruthy();
});

test("after correct user input, archive button is enabled", async () => {
expect(screen.getByRole("button", { name: "Archive" })).not.toBeEnabled();
const inputTextbox = screen.getByTestId("modal-input");
await userEvent.type(inputTextbox, "ARCHIVE");
expect(screen.getByRole("button", { name: "Archive" })).toBeEnabled();
});

test("Archive button successfully archives the program", async () => {
const inputTextbox = screen.getByTestId("modal-input");
await userEvent.type(inputTextbox, "ARCHIVE");
const archiveButton = screen.getByTestId("modal-archive-button");
await userEvent.click(archiveButton);
await expect(mockReportMethods.archiveReport).toHaveBeenCalledTimes(1);
});
});

testA11yAct(modalComponent);
});
Loading

0 comments on commit 5a44b68

Please sign in to comment.