From b6a4e72693e04b8ee01e452d7f22f217afb291c4 Mon Sep 17 00:00:00 2001 From: R Ranathunga Date: Sun, 9 Jun 2024 18:10:58 -0700 Subject: [PATCH 1/8] feat: add toast after file upload RFI template 1 and 2 --- .../Analyst/RFI/RFIAnalystUpload.tsx | 37 +++++ app/components/AppProvider.tsx | 60 +++++++ app/components/Toast.tsx | 2 +- app/lib/theme/widgets/FileWidget.tsx | 57 +++++-- app/pages/_app.tsx | 7 +- .../Analyst/RFI/RFIAnalystUpload.test.ts | 157 ++++++++++++++++++ app/tests/components/Form/FileWidget.test.tsx | 50 ++++++ app/tests/utils/componentTestingHelper.tsx | 11 +- app/tests/utils/pageTestingHelper.tsx | 11 +- 9 files changed, 371 insertions(+), 21 deletions(-) create mode 100644 app/components/AppProvider.tsx diff --git a/app/components/Analyst/RFI/RFIAnalystUpload.tsx b/app/components/Analyst/RFI/RFIAnalystUpload.tsx index 882da3027e..de29413583 100644 --- a/app/components/Analyst/RFI/RFIAnalystUpload.tsx +++ b/app/components/Analyst/RFI/RFIAnalystUpload.tsx @@ -13,6 +13,8 @@ import styled from 'styled-components'; import { useCreateNewFormDataMutation } from 'schema/mutations/application/createNewFormData'; import useHHCountUpdateEmail from 'lib/helpers/useHHCountUpdateEmail'; import useRfiCoverageMapKmzUploadedEmail from 'lib/helpers/useRfiCoverageMapKmzUploadedEmail'; +import { useToast } from 'components/AppProvider'; +import Link from 'next/link'; const Flex = styled('header')` display: flex; @@ -20,6 +22,10 @@ const Flex = styled('header')` width: 100%; `; +const StyledLink = styled(Link)` + color: ${(props) => props.theme.color.white}; +`; + const RfiAnalystUpload = ({ query }) => { const queryFragment = useFragment( graphql` @@ -52,6 +58,7 @@ const RfiAnalystUpload = ({ query }) => { rowId: applicationId, ccbcNumber, } = applicationByRowId; + const { showToast, hideToast } = useToast(); const { rfiNumber } = rfiDataByRowId; @@ -94,9 +101,30 @@ const RfiAnalystUpload = ({ query }) => { // eslint-disable-next-line react-hooks/exhaustive-deps }, [templateData]); + const getToastMessage = () => { + return ( + <> + {' '} + `Template {templateData?.templateNumber} data changed successfully, new + values for{' '} + {templateData?.templateNumber === 1 + ? 'Total Households and Indigenous Households' + : 'Total eligible costs and Total project costs'}{' '} + data in the application now reflect template uploads. Please see{' '} + + history page + {' '} + for details.` + + ); + }; + const handleSubmit = () => { const updatedExcelFields = excelImportFields.join(', '); const reasonForChange = `Auto updated from upload of ${updatedExcelFields} for RFI: ${rfiNumber}`; + hideToast(); updateRfi({ variables: { input: { @@ -129,6 +157,15 @@ const RfiAnalystUpload = ({ query }) => { } ); } + if ( + templateData?.templateNumber === 1 || + templateData?.templateNumber === 2 + ) { + showToast(getToastMessage(), 'success', 100000000); + } + router.push( + `/analyst/application/${router.query.applicationId}/rfi` + ); }, }); } diff --git a/app/components/AppProvider.tsx b/app/components/AppProvider.tsx new file mode 100644 index 0000000000..bc03c7dd53 --- /dev/null +++ b/app/components/AppProvider.tsx @@ -0,0 +1,60 @@ +import React, { + createContext, + useContext, + useState, + useCallback, + useMemo, + ReactNode, +} from 'react'; +import Toast, { ToastType } from 'components/Toast'; + +type ToastContextType = { + showToast?: (message: ReactNode, type?: ToastType, timeout?: number) => void; + hideToast?: () => void; +}; + +const ToastContext = createContext({}); + +export const useToast = () => { + return useContext(ToastContext); +}; + +export const AppProvider = ({ children }) => { + const [toast, setToast] = useState<{ + visible: boolean; + message?: ReactNode; + type?: ToastType; + timeout?: number; + }>({ visible: false }); + + const showToast = useCallback( + ( + message: ReactNode, + type: ToastType = 'success', + timeout: number = 10000 + ) => { + setToast({ visible: true, message, type, timeout }); + }, + [] + ); + + const hideToast = useCallback(() => { + setToast({ visible: false }); + }, []); + + const contextValue = useMemo( + () => ({ showToast, hideToast }), + [showToast, hideToast] + ); + + return ( + + {children} + {toast?.visible && ( + + {toast.message} + + )} + + ); +}; diff --git a/app/components/Toast.tsx b/app/components/Toast.tsx index d14edf9f04..c1f8c6333a 100644 --- a/app/components/Toast.tsx +++ b/app/components/Toast.tsx @@ -9,7 +9,7 @@ import { import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { theme } from 'styles/GlobalTheme'; -type ToastType = 'success' | 'warning' | 'error'; +export type ToastType = 'success' | 'warning' | 'error'; type ToastDirection = 'left' | 'right'; diff --git a/app/lib/theme/widgets/FileWidget.tsx b/app/lib/theme/widgets/FileWidget.tsx index c0b7bca6ad..342018abf8 100644 --- a/app/lib/theme/widgets/FileWidget.tsx +++ b/app/lib/theme/widgets/FileWidget.tsx @@ -13,6 +13,7 @@ import bytesToSize from 'utils/bytesToText'; import FileComponent from 'lib/theme/components/FileComponent'; import useDisposeOnRouteChange from 'lib/helpers/useDisposeOnRouteChange'; import { DateTime } from 'luxon'; +import { useToast } from 'components/AppProvider'; type File = { id: string | number; @@ -65,6 +66,7 @@ const FileWidget: React.FC = ({ const maxFileSizeInBytes = 104857600; const fileId = isFiles && value[0].id; const { setTemplateData } = formContext; + const { showToast, hideToast } = useToast(); useEffect(() => { if (rawErrors?.length > 0) { @@ -73,27 +75,29 @@ const FileWidget: React.FC = ({ }, [rawErrors, setErrors]); const getValidatedFile = async (file: any, formId: number) => { + let isTemplateValid = true; if (templateValidate) { const fileFormData = new FormData(); if (file) { fileFormData.append('file', file); if (setTemplateData) { - await fetch( + const response = await fetch( `/api/applicant/template?templateNumber=${templateNumber}`, { method: 'POST', body: fileFormData, } - ).then((response) => { - if (response.ok) { - response.json().then((data) => { - setTemplateData({ - templateNumber, - data, - }); + ); + if (response.ok) { + response.json().then((data) => { + setTemplateData({ + templateNumber, + data, }); - } - }); + }); + } else { + isTemplateValid = false; + } } } } @@ -109,6 +113,7 @@ const FileWidget: React.FC = ({ } return { + isTemplateValid, input: { attachment: { file, @@ -153,6 +158,17 @@ const FileWidget: React.FC = ({ }); }; + const getToastMessage = (files: any[], isSuccess: boolean = true) => { + const fields = + templateNumber === 1 + ? 'Total Households and Indigenous Households data' + : 'Total eligible costs and Total project costs data'; + if (isSuccess) { + return `Template ${templateNumber} validation successful, new values for ${fields} data in the application will update upon 'Save'`; + } + return `Template ${templateNumber} validation failed : ${files.join(', ')} did not validate due to formatting issues. ${fields} in the application will not update.`; + }; + const handleChange = async (e: React.ChangeEvent) => { const transaction = Sentry.startTransaction({ name: 'ccbc.function' }); const span = transaction.startChild({ @@ -161,6 +177,7 @@ const FileWidget: React.FC = ({ }); if (loading) return; + hideToast(); const formId = parseInt(router?.query?.id as string, 10) || parseInt(router?.query?.applicationId as string, 10); @@ -177,6 +194,8 @@ const FileWidget: React.FC = ({ const validatedFiles = resp.filter((file) => file.input); setErrors(resp.filter((file) => file.error)); + const validationErrors = resp.filter((file) => !file.isTemplateValid); + const uploadResponse = await Promise.all( validatedFiles.map(async (payload) => handleUpload(payload)) ); @@ -190,6 +209,24 @@ const FileWidget: React.FC = ({ } else { span.setStatus('ok'); } + + if (templateValidate) { + if (validationErrors.length > 0) { + showToast( + getToastMessage( + validationErrors.map( + (error) => error.fileName || error.input?.attachment?.fileName + ), + false + ), + 'error', + 100000000 + ); + } else if (validationErrors.length === 0 && uploadErrors.length === 0) { + showToast(getToastMessage(fileDetails), 'success', 100000000); + } + } + span.finish(); transaction.finish(); diff --git a/app/pages/_app.tsx b/app/pages/_app.tsx index 0736cdfc67..ae8816b045 100644 --- a/app/pages/_app.tsx +++ b/app/pages/_app.tsx @@ -18,6 +18,7 @@ import GlobalStyle from 'styles/GobalStyles'; import GlobalTheme from 'styles/GlobalTheme'; import BCGovTypography from 'components/BCGovTypography'; import { SessionExpiryHandler } from 'components'; +import { AppProvider } from 'components/AppProvider'; config.autoAddCss = false; @@ -94,8 +95,10 @@ const MyApp = ({ Component, pageProps }: AppProps) => { }> - {typeof window !== 'undefined' && } - {component} + + {typeof window !== 'undefined' && } + {component} + diff --git a/app/tests/components/Analyst/RFI/RFIAnalystUpload.test.ts b/app/tests/components/Analyst/RFI/RFIAnalystUpload.test.ts index 2ef65710e1..c47c6179b4 100644 --- a/app/tests/components/Analyst/RFI/RFIAnalystUpload.test.ts +++ b/app/tests/components/Analyst/RFI/RFIAnalystUpload.test.ts @@ -200,6 +200,8 @@ describe('The RFIAnalystUpload component', () => { expect(screen.getByText('template_one.xlsx')).toBeInTheDocument(); + expect(screen.getByText(/Template 1 validation successful/)).toBeVisible(); + const saveButton = screen.getByRole('button', { name: 'Save', }); @@ -318,5 +320,160 @@ describe('The RFIAnalystUpload component', () => { ); expect(mockNotifyRfiCoverageMapKmzUploaded).toHaveBeenCalledTimes(1); + expect( + screen.getByText(/Template 1 data changed successfully/) + ).toBeVisible(); + }); + + it('should render success toast for template two when upload successful', async () => { + componentTestingHelper.loadQuery(); + componentTestingHelper.renderComponent(); + + // @ts-ignore + global.fetch = jest.fn(() => + Promise.resolve({ + ok: true, + status: 200, + json: () => + Promise.resolve({ + result: { + totalEligibleCosts: 92455, + totalProjectCosts: 101230, + }, + }), + }) + ); + + const dateInput = screen.getAllByPlaceholderText('YYYY-MM-DD')[0]; + + await act(async () => { + fireEvent.change(dateInput, { + target: { + value: '2025-07-01', + }, + }); + }); + + const file = new File([new ArrayBuffer(1)], 'template_two.xlsx', { + type: 'application/excel', + }); + + const inputFile = screen.getAllByTestId('file-test')[1]; + + await act(async () => { + fireEvent.change(inputFile, { target: { files: [file] } }); + }); + + componentTestingHelper.expectMutationToBeCalled( + 'createAttachmentMutation', + { + input: { + attachment: { + file: expect.anything(), + fileName: 'template_two.xlsx', + fileSize: '1 Bytes', + fileType: 'application/excel', + applicationId: expect.anything(), + }, + }, + } + ); + + await act(async () => { + componentTestingHelper.environment.mock.resolveMostRecentOperation({ + data: { + createAttachment: { + attachment: { + rowId: 1, + file: 'string', + }, + }, + }, + }); + }); + + expect(screen.getByText('template_two.xlsx')).toBeInTheDocument(); + + expect(screen.getByText(/Template 2 validation successful/)).toBeVisible(); + + const saveButton = screen.getByRole('button', { + name: 'Save', + }); + + await act(async () => { + fireEvent.click(saveButton); + }); + + componentTestingHelper.expectMutationToBeCalled( + 'updateWithTrackingRfiMutation', + { + input: { + jsonData: { + rfiType: [], + rfiAdditionalFiles: { + detailedBudgetRfi: true, + eligibilityAndImpactsCalculatorRfi: true, + detailedBudget: expect.anything(), + geographicCoverageMapRfi: true, + geographicCoverageMap: expect.anything(), + }, + }, + rfiRowId: 1, + }, + } + ); + + act(() => { + componentTestingHelper.environment.mock.resolveMostRecentOperation({ + data: { + updateWithTrackingRfi: { + rfiData: { + rowId: 1, + jsonData: { + rfiAdditionalFiles: { + detailedBudgetRfi: true, + eligibilityAndImpactsCalculatorRfi: true, + detailedBudget: expect.anything(), + geographicCoverageMapRfi: true, + geographicCoverageMap: expect.anything(), + }, + }, + }, + }, + }, + }); + }); + + componentTestingHelper.expectMutationToBeCalled( + 'createNewFormDataMutation', + { + input: { + applicationRowId: 1, + jsonData: { + benefits: { + householdsImpactedIndigenous: 13, + numberOfHouseholds: 12, + }, + budgetDetails: { + totalEligibleCosts: 92455, + totalProjectCost: 101230, + }, + }, + reasonForChange: + 'Auto updated from upload of Template 2 for RFI: RFI-01', + formSchemaId: 1, + }, + } + ); + + act(() => { + componentTestingHelper.environment.mock.resolveMostRecentOperation({ + data: {}, + }); + }); + + expect( + screen.getByText(/Template 2 data changed successfully/) + ).toBeVisible(); }); }); diff --git a/app/tests/components/Form/FileWidget.test.tsx b/app/tests/components/Form/FileWidget.test.tsx index 6ce3a775c6..108c70c09d 100644 --- a/app/tests/components/Form/FileWidget.test.tsx +++ b/app/tests/components/Form/FileWidget.test.tsx @@ -52,6 +52,7 @@ const componentTestingHelper = new ComponentTestingHelper({ application: data.application, pageNumber: getFormPage(uiSchema['ui:order'], 'coverage'), query: data.query, + formContext: { setTemplateData: jest.fn() }, }), }); @@ -535,6 +536,55 @@ describe('The FileWidget', () => { { body: formData, method: 'POST' } ); }); + + it('displays an error toast when template validation fails', async () => { + componentTestingHelper.loadQuery(); + componentTestingHelper.renderComponent((data) => ({ + application: data.application, + pageNumber: 11, + query: data.query, + })); + + const mockFetchPromiseTemplateOne = Promise.resolve({ + json: () => Promise.resolve(null), + }); + + global.fetch = jest.fn(() => { + return mockFetchPromiseTemplateOne; + }); + + const file = new File([new ArrayBuffer(1)], 'file.xlsx', { + type: 'application/vnd.ms-excel', + }); + + const inputFile = screen.getAllByTestId('file-test')[0]; + await act(async () => { + fireEvent.change(inputFile, { target: { files: [file] } }); + }); + const formData = new FormData(); + formData.append('file', file); + expect(global.fetch).toHaveBeenCalledOnce(); + expect(global.fetch).toHaveBeenCalledWith( + '/api/applicant/template?templateNumber=1', + { body: formData, method: 'POST' } + ); + + await act(async () => { + componentTestingHelper.environment.mock.resolveMostRecentOperation({ + data: { + createAttachment: { + attachment: { + rowId: 1, + file: 'string', + }, + }, + }, + }); + }); + + expect(screen.getByText(/Template 1 validation failed/)).toBeVisible(); + }); + afterEach(() => { jest.clearAllMocks(); }); diff --git a/app/tests/utils/componentTestingHelper.tsx b/app/tests/utils/componentTestingHelper.tsx index ce2fc8871b..df545a65a8 100644 --- a/app/tests/utils/componentTestingHelper.tsx +++ b/app/tests/utils/componentTestingHelper.tsx @@ -10,6 +10,7 @@ import { MockResolvers } from 'relay-test-utils/lib/RelayMockPayloadGenerator'; import GlobalTheme from 'styles/GlobalTheme'; import GlobalStyle from 'styles/GobalStyles'; import { RouterContext } from 'next/dist/shared/lib/router-context.shared-runtime'; +import { AppProvider } from 'components/AppProvider'; import TestingHelper from './TestingHelper'; interface ComponentTestingHelperOptions { @@ -85,10 +86,12 @@ class ComponentTestingHelper< - + + + diff --git a/app/tests/utils/pageTestingHelper.tsx b/app/tests/utils/pageTestingHelper.tsx index 4ca685c3bb..0fc9d94a6c 100644 --- a/app/tests/utils/pageTestingHelper.tsx +++ b/app/tests/utils/pageTestingHelper.tsx @@ -10,6 +10,7 @@ import { ConcreteRequest, OperationType } from 'relay-runtime'; import { MockResolvers } from 'relay-test-utils/lib/RelayMockPayloadGenerator'; import GlobalTheme from 'styles/GlobalTheme'; import { RouterContext } from 'next/dist/shared/lib/router-context.shared-runtime'; +import { AppProvider } from 'components/AppProvider'; import TestingHelper from './TestingHelper'; interface PageTestingHelperOptions { @@ -66,10 +67,12 @@ class PageTestingHelper extends TestingHelper { - + + + From ddd4c92c926c4e5d7b800ee1d4a3e734f99e29af Mon Sep 17 00:00:00 2001 From: R Ranathunga Date: Mon, 10 Jun 2024 08:06:06 -0700 Subject: [PATCH 2/8] refactor: toast hide and show --- .../Analyst/RFI/RFIAnalystUpload.tsx | 3 -- app/components/AppProvider.tsx | 13 +++-- app/lib/theme/widgets/FileWidget.tsx | 50 +++++++++---------- 3 files changed, 33 insertions(+), 33 deletions(-) diff --git a/app/components/Analyst/RFI/RFIAnalystUpload.tsx b/app/components/Analyst/RFI/RFIAnalystUpload.tsx index de29413583..832a689593 100644 --- a/app/components/Analyst/RFI/RFIAnalystUpload.tsx +++ b/app/components/Analyst/RFI/RFIAnalystUpload.tsx @@ -163,9 +163,6 @@ const RfiAnalystUpload = ({ query }) => { ) { showToast(getToastMessage(), 'success', 100000000); } - router.push( - `/analyst/application/${router.query.applicationId}/rfi` - ); }, }); } diff --git a/app/components/AppProvider.tsx b/app/components/AppProvider.tsx index bc03c7dd53..91ccd6d17b 100644 --- a/app/components/AppProvider.tsx +++ b/app/components/AppProvider.tsx @@ -8,18 +8,21 @@ import React, { } from 'react'; import Toast, { ToastType } from 'components/Toast'; -type ToastContextType = { +type AppContextType = { showToast?: (message: ReactNode, type?: ToastType, timeout?: number) => void; hideToast?: () => void; }; -const ToastContext = createContext({}); +const AppContext = createContext({}); export const useToast = () => { - return useContext(ToastContext); + return useContext(AppContext); }; export const AppProvider = ({ children }) => { + /** + * handling global toast messages + */ const [toast, setToast] = useState<{ visible: boolean; message?: ReactNode; @@ -48,13 +51,13 @@ export const AppProvider = ({ children }) => { ); return ( - + {children} {toast?.visible && ( {toast.message} )} - + ); }; diff --git a/app/lib/theme/widgets/FileWidget.tsx b/app/lib/theme/widgets/FileWidget.tsx index 342018abf8..9dd1a5bcb7 100644 --- a/app/lib/theme/widgets/FileWidget.tsx +++ b/app/lib/theme/widgets/FileWidget.tsx @@ -14,6 +14,7 @@ import FileComponent from 'lib/theme/components/FileComponent'; import useDisposeOnRouteChange from 'lib/helpers/useDisposeOnRouteChange'; import { DateTime } from 'luxon'; import { useToast } from 'components/AppProvider'; +import { ToastType } from 'components/Toast'; type File = { id: string | number; @@ -81,23 +82,24 @@ const FileWidget: React.FC = ({ if (file) { fileFormData.append('file', file); if (setTemplateData) { - const response = await fetch( + await fetch( `/api/applicant/template?templateNumber=${templateNumber}`, { method: 'POST', body: fileFormData, } - ); - if (response.ok) { - response.json().then((data) => { - setTemplateData({ - templateNumber, - data, + ).then((response) => { + if (response.ok) { + response.json().then((data) => { + setTemplateData({ + templateNumber, + data, + }); }); - }); - } else { - isTemplateValid = false; - } + } else { + isTemplateValid = false; + } + }); } } } @@ -158,15 +160,17 @@ const FileWidget: React.FC = ({ }); }; - const getToastMessage = (files: any[], isSuccess: boolean = true) => { + const showToastMessage = (files, type: ToastType = 'success') => { const fields = templateNumber === 1 ? 'Total Households and Indigenous Households data' : 'Total eligible costs and Total project costs data'; - if (isSuccess) { - return `Template ${templateNumber} validation successful, new values for ${fields} data in the application will update upon 'Save'`; - } - return `Template ${templateNumber} validation failed : ${files.join(', ')} did not validate due to formatting issues. ${fields} in the application will not update.`; + const message = + type === 'success' + ? `Template ${templateNumber} validation successful, new values for ${fields} data in the application will update upon 'Save'` + : `Template ${templateNumber} validation failed: ${files.join(', ')} did not validate due to formatting issues. ${fields} in the application will not update.`; + + showToast(message, type, 100000000); }; const handleChange = async (e: React.ChangeEvent) => { @@ -212,18 +216,14 @@ const FileWidget: React.FC = ({ if (templateValidate) { if (validationErrors.length > 0) { - showToast( - getToastMessage( - validationErrors.map( - (error) => error.fileName || error.input?.attachment?.fileName - ), - false + showToastMessage( + validationErrors.map( + (error) => error.fileName || error.input?.attachment?.fileName ), - 'error', - 100000000 + 'error' ); } else if (validationErrors.length === 0 && uploadErrors.length === 0) { - showToast(getToastMessage(fileDetails), 'success', 100000000); + showToastMessage(fileDetails.map((file) => file.name)); } } From 4b6653c69423cc4768380392996f7be5c1b6792d Mon Sep 17 00:00:00 2001 From: CCBC Service Account <116113628+ccbc-service-account@users.noreply.github.com> Date: Mon, 10 Jun 2024 20:51:16 +0000 Subject: [PATCH 3/8] chore: Update registry.access.redhat.com/ubi9/s2i-base Docker digest to 798d3d9 --- app/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Dockerfile b/app/Dockerfile index 8087788e1a..016ea37128 100644 --- a/app/Dockerfile +++ b/app/Dockerfile @@ -1,4 +1,4 @@ -FROM registry.access.redhat.com/ubi9/s2i-base@sha256:9af1318d4d016b4aab0723aafdaf739972065919559107eadaccac4c8f350f37 +FROM registry.access.redhat.com/ubi9/s2i-base@sha256:798d3d983bde082429eaced15475722585c994612ba062dbce6428877ee3ca32 ENV SUMMARY="An image for the CONN-CCBC-portal app" \ DESCRIPTION="This image contains the compiled CONN-CCBC-portal node app" From 0163d32e23c11a0e5cb5830c8f4b37b6c14701b7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 13 Jun 2024 15:06:20 +0000 Subject: [PATCH 4/8] chore: bump github/codeql-action from 3.25.7 to 3.25.10 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.25.7 to 3.25.10. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/f079b8493333aace61c81488f8bd40919487bd9f...23acc5c183826b7a8a97bce3cecc52db901f8251) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/scorecards.yml | 2 +- .github/workflows/test-checks.yaml | 10 +++++----- .github/workflows/test-code.yaml | 2 +- .github/workflows/test-containers.yaml | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml index 56e8448b0c..0cf9e1d9d5 100644 --- a/.github/workflows/scorecards.yml +++ b/.github/workflows/scorecards.yml @@ -57,6 +57,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@f079b8493333aace61c81488f8bd40919487bd9f # tag=v3.25.7 + uses: github/codeql-action/upload-sarif@23acc5c183826b7a8a97bce3cecc52db901f8251 # tag=v3.25.10 with: sarif_file: results.sarif diff --git a/.github/workflows/test-checks.yaml b/.github/workflows/test-checks.yaml index 5f128e5e52..e9a9dd0b94 100644 --- a/.github/workflows/test-checks.yaml +++ b/.github/workflows/test-checks.yaml @@ -41,7 +41,7 @@ jobs: ignore-unfixed: false severity: UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL - name: Upload Trivy scan results to GitHub Security tab - uses: github/codeql-action/upload-sarif@f079b8493333aace61c81488f8bd40919487bd9f + uses: github/codeql-action/upload-sarif@23acc5c183826b7a8a97bce3cecc52db901f8251 with: sarif_file: 'trivy-results.sarif' @@ -61,13 +61,13 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 - name: Initialize CodeQL - uses: github/codeql-action/init@f079b8493333aace61c81488f8bd40919487bd9f + uses: github/codeql-action/init@23acc5c183826b7a8a97bce3cecc52db901f8251 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@f079b8493333aace61c81488f8bd40919487bd9f + uses: github/codeql-action/autobuild@23acc5c183826b7a8a97bce3cecc52db901f8251 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@f079b8493333aace61c81488f8bd40919487bd9f + uses: github/codeql-action/analyze@23acc5c183826b7a8a97bce3cecc52db901f8251 cocogitto: runs-on: ubuntu-latest @@ -92,7 +92,7 @@ jobs: - uses: actions/checkout@v4 - run: ./.bin/install-gitleaks-linux-x64.sh - run: ./gitleaks detect --exit-code 0 --report-format sarif --report-path "gitleaks.sarif" - - uses: github/codeql-action/upload-sarif@f079b8493333aace61c81488f8bd40919487bd9f + - uses: github/codeql-action/upload-sarif@23acc5c183826b7a8a97bce3cecc52db901f8251 with: sarif_file: 'gitleaks.sarif' diff --git a/.github/workflows/test-code.yaml b/.github/workflows/test-code.yaml index 8c53f1430c..b092a2418a 100644 --- a/.github/workflows/test-code.yaml +++ b/.github/workflows/test-code.yaml @@ -59,7 +59,7 @@ jobs: fs.writeFileSync('results.sarif', JSON.stringify(sarifJson, null, 2)); EOF working-directory: ./app - - uses: github/codeql-action/upload-sarif@f079b8493333aace61c81488f8bd40919487bd9f + - uses: github/codeql-action/upload-sarif@23acc5c183826b7a8a97bce3cecc52db901f8251 with: sarif_file: app/results.sarif diff --git a/.github/workflows/test-containers.yaml b/.github/workflows/test-containers.yaml index 5cac7b4619..2bd0112a0f 100644 --- a/.github/workflows/test-containers.yaml +++ b/.github/workflows/test-containers.yaml @@ -37,7 +37,7 @@ jobs: severity: CRITICAL timeout: 10m0s - name: Upload Trivy scan results to GitHub Security tab - uses: github/codeql-action/upload-sarif@f079b8493333aace61c81488f8bd40919487bd9f + uses: github/codeql-action/upload-sarif@23acc5c183826b7a8a97bce3cecc52db901f8251 with: sarif_file: 'trivy-results.sarif' - name: Get Results Length From Sarif @@ -64,7 +64,7 @@ jobs: severity: CRITICAL timeout: 10m0s - name: Upload Trivy scan results to GitHub Security tab - uses: github/codeql-action/upload-sarif@f079b8493333aace61c81488f8bd40919487bd9f + uses: github/codeql-action/upload-sarif@23acc5c183826b7a8a97bce3cecc52db901f8251 with: sarif_file: 'trivy-results.sarif' - name: Get Results Length From Sarif From dac45ae07be773a962e1a2780a9dfb2f517f3f09 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 13 Jun 2024 15:38:43 +0000 Subject: [PATCH 5/8] chore: bump braces from 3.0.2 to 3.0.3 in /app Bumps [braces](https://github.com/micromatch/braces) from 3.0.2 to 3.0.3. - [Changelog](https://github.com/micromatch/braces/blob/master/CHANGELOG.md) - [Commits](https://github.com/micromatch/braces/compare/3.0.2...3.0.3) --- updated-dependencies: - dependency-name: braces dependency-type: indirect ... Signed-off-by: dependabot[bot] --- app/yarn.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/app/yarn.lock b/app/yarn.lock index 9f82ac5d77..15dd341cce 100644 --- a/app/yarn.lock +++ b/app/yarn.lock @@ -6009,11 +6009,11 @@ brace-expansion@^2.0.1: balanced-match "^1.0.0" braces@^3.0.2, braces@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== dependencies: - fill-range "^7.0.1" + fill-range "^7.1.1" browser-process-hrtime@^1.0.0: version "1.0.0" @@ -8115,10 +8115,10 @@ file-entry-cache@^6.0.1: dependencies: flat-cache "^3.0.4" -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== dependencies: to-regex-range "^5.0.1" From f01114ecc262db3fbc07ad69aeab6001661158df Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 13 Jun 2024 15:56:17 +0000 Subject: [PATCH 6/8] chore: bump happo-cypress from 4.1.1 to 4.2.0 in /app Bumps [happo-cypress](https://github.com/happo/happo-cypress) from 4.1.1 to 4.2.0. - [Release notes](https://github.com/happo/happo-cypress/releases) - [Commits](https://github.com/happo/happo-cypress/compare/v4.1.1...v4.2.0) --- updated-dependencies: - dependency-name: happo-cypress dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- app/package.json | 2 +- app/yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/package.json b/app/package.json index 75ffdf855c..858d839af1 100644 --- a/app/package.json +++ b/app/package.json @@ -150,7 +150,7 @@ "eslint-plugin-react-hooks": "^4.6.2", "eslint-plugin-relay": "^1.8.3", "fse": "^4.0.1", - "happo-cypress": "^4.1.1", + "happo-cypress": "^4.2.0", "happo-e2e": "^2.6.0", "happo.io": "^8.3.3", "jest": "^28.1.0", diff --git a/app/yarn.lock b/app/yarn.lock index 15dd341cce..517087d037 100644 --- a/app/yarn.lock +++ b/app/yarn.lock @@ -8703,10 +8703,10 @@ gray-percentage@^2.0.0: resolved "https://registry.yarnpkg.com/gray-percentage/-/gray-percentage-2.0.0.tgz#b72a274d1b1379104a0050b63b207dc53fe56f99" integrity sha1-tyonTRsTeRBKAFC2OyB9xT/lb5k= -happo-cypress@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/happo-cypress/-/happo-cypress-4.1.1.tgz#d10f064fad72a6a733a22f2baa234518e582b6bc" - integrity sha512-qMSjOOlCGjGis+i/VTzcL8/2te73I2jrNcQkx+rJgcbgYV7x13tiEVVo/MrR5lCg7kHtXiNNXAXgw7XUxNh3pQ== +happo-cypress@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/happo-cypress/-/happo-cypress-4.2.0.tgz#899c6e2e16af197e8b65a89b6f056c541df6be7f" + integrity sha512-58OheJOeZpfXE78FkMJ4qv0LI5IjUcPyUaDrBAKkqlgAYtt6ZhCYSUH2V3AYDIIz+tWqAE4roF93/5sueggy5Q== happo-e2e@^2.6.0: version "2.6.0" From 565dc56327bf0f617f8015713428e633d46159da Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 13 Jun 2024 17:00:07 +0000 Subject: [PATCH 7/8] chore: bump dayjs from 1.11.8 to 1.11.11 in /app Bumps [dayjs](https://github.com/iamkun/dayjs) from 1.11.8 to 1.11.11. - [Release notes](https://github.com/iamkun/dayjs/releases) - [Changelog](https://github.com/iamkun/dayjs/blob/dev/CHANGELOG.md) - [Commits](https://github.com/iamkun/dayjs/compare/v1.11.8...v1.11.11) --- updated-dependencies: - dependency-name: dayjs dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- app/package.json | 2 +- app/yarn.lock | 13 ++++--------- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/app/package.json b/app/package.json index 858d839af1..38bffee044 100644 --- a/app/package.json +++ b/app/package.json @@ -65,7 +65,7 @@ "connect-pg-simple": "^7.0.0", "convict": "^6.2.4", "cookie-parser": "^1.4.6", - "dayjs": "^1.11.8", + "dayjs": "^1.11.11", "debug": "^4.1.7", "delay": "^5.0.0", "dotenv": "^16.3.1", diff --git a/app/yarn.lock b/app/yarn.lock index 517087d037..2717749ccc 100644 --- a/app/yarn.lock +++ b/app/yarn.lock @@ -6887,15 +6887,10 @@ data-urls@^3.0.1: whatwg-mimetype "^3.0.0" whatwg-url "^11.0.0" -dayjs@^1.10.4: - version "1.11.2" - resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.2.tgz#fa0f5223ef0d6724b3d8327134890cfe3d72fbe5" - integrity sha512-F4LXf1OeU9hrSYRPTTj/6FbO4HTjPKXvEIC1P2kcnFurViINCVk3ZV0xAS3XVx9MkMsXbbqlK6hjseaYbgKEHw== - -dayjs@^1.11.8: - version "1.11.8" - resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.8.tgz#4282f139c8c19dd6d0c7bd571e30c2d0ba7698ea" - integrity sha512-LcgxzFoWMEPO7ggRv1Y2N31hUf2R0Vj7fuy/m+Bg1K8rr+KAs1AEy4y9jd5DXe8pbHgX+srkHNS7TH6Q6ZhYeQ== +dayjs@^1.10.4, dayjs@^1.11.11: + version "1.11.11" + resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.11.tgz#dfe0e9d54c5f8b68ccf8ca5f72ac603e7e5ed59e" + integrity sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg== debug@2.6.9: version "2.6.9" From a61476413c84396797a2764f4d48b578d6589655 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 13 Jun 2024 17:28:44 +0000 Subject: [PATCH 8/8] chore: bump braces from 3.0.2 to 3.0.3 Bumps [braces](https://github.com/micromatch/braces) from 3.0.2 to 3.0.3. - [Changelog](https://github.com/micromatch/braces/blob/master/CHANGELOG.md) - [Commits](https://github.com/micromatch/braces/compare/3.0.2...3.0.3) --- updated-dependencies: - dependency-name: braces dependency-type: indirect ... Signed-off-by: dependabot[bot] --- yarn.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/yarn.lock b/yarn.lock index 468b63427b..6aa65220aa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -406,11 +406,11 @@ brace-expansion@^1.1.7: concat-map "0.0.1" braces@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== dependencies: - fill-range "^7.0.1" + fill-range "^7.1.1" buffer-from@^1.0.0: version "1.1.2" @@ -1140,10 +1140,10 @@ file-uri-to-path@2: resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-2.0.0.tgz#7b415aeba227d575851e0a5b0c640d7656403fba" integrity sha512-hjPFI8oE/2iQPVe4gbrJ73Pp+Xfub2+WI2LlXDbsaJBwT5wuMh35WNWVYYTpnz895shtwfyutMFLFywpQAFdLg== -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== dependencies: to-regex-range "^5.0.1"