diff --git a/.github/workflows/archive.yml b/.github/workflows/archive.yml index 7d5bffbc5..b41918a7d 100644 --- a/.github/workflows/archive.yml +++ b/.github/workflows/archive.yml @@ -22,7 +22,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@v4 + uses: aws-actions/configure-aws-credentials@v4.0.2 with: aws-region: us-gov-west-1 role-to-assume: ${{ vars.AWS_ASSUME_ROLE }} @@ -142,7 +142,7 @@ jobs: run: tar -c main/out/ -cf ${{ env.BUILD_TYPE }}.tar.bz2 . - name: Configure AWS Credentials - uses: aws-actions/configure-aws-credentials@v4 + uses: aws-actions/configure-aws-credentials@v4.0.2 with: aws-region: us-gov-west-1 role-to-assume: ${{ vars.AWS_ASSUME_ROLE }} diff --git a/.github/workflows/content-release-dev.yml b/.github/workflows/content-release-dev.yml new file mode 100644 index 000000000..d1aff63a4 --- /dev/null +++ b/.github/workflows/content-release-dev.yml @@ -0,0 +1,26 @@ +name: "Content release: Dev" +on: + # Can be manually triggered + workflow_dispatch: + # Runs 5:05 am EDT Monday to Friday. + # This currently UTC -> EDT. + schedule: + - cron: "05 9 * * 1-5" + # Runs each time there is a new Production Tag created. + workflow_run: + workflows: ['Create Production Tag'] + types: [completed] + branches: [main] + +concurrency: next-build-content-release-dev + +jobs: + content-release-dev: + # This job should run for any valid event besides workflow_run, or workflow_run if the conclusion was successful. + if: ${{ github.event_name != 'workflow_run' || github.event.workflow_run.conclusion == 'success' }} + uses: department-of-veterans-affairs/next-build/.github/workflows/content-release.yml@main + with: + build_type: "dev" + secrets: inherit + + diff --git a/.github/workflows/content-release-prod.yml b/.github/workflows/content-release-prod.yml new file mode 100644 index 000000000..02bb86865 --- /dev/null +++ b/.github/workflows/content-release-prod.yml @@ -0,0 +1,23 @@ +name: "Content release: Prod" +on: + # Can be manually triggered + workflow_dispatch: + # Runs automatically every 30 minutes from 8am to 8pm Monday to Friday. + # This currently UTC -> EDT. + schedule: + - cron: "*/30 0,12-23 * * 1-5" + # Runs on API call. Used for CMS-driven build triggers. + repository_dispatch: + types: [content-release] + +concurrency: next-build-content-release-prod + +jobs: + content-release: + uses: department-of-veterans-affairs/next-build/.github/workflows/content-release.yml@main + with: + build_type: "prod" + secrets: inherit + + + diff --git a/.github/workflows/content-release-staging.yml b/.github/workflows/content-release-staging.yml new file mode 100644 index 000000000..ba9c435c6 --- /dev/null +++ b/.github/workflows/content-release-staging.yml @@ -0,0 +1,26 @@ +name: "Content release: Staging" +on: + # Can be manually triggered + workflow_dispatch: + # Runs 5:35 am EDT Monday to Friday. + # This currently UTC -> EDT. + schedule: + - cron: "35 9 * * 1-5" + # Runs each time there is a new Production Tag created. + workflow_run: + workflows: ['Create Production Tag'] + types: [completed] + branches: [main] + +concurrency: next-build-content-release-staging + +jobs: + content-release-staging: + # This job should run for any valid event besides workflow_run, or workflow_run if the conclusion was successful. + if: ${{ github.event_name != 'workflow_run' || github.event.workflow_run.conclusion == 'success' }} + uses: department-of-veterans-affairs/next-build/.github/workflows/content-release.yml@main + with: + build_type: "staging" + secrets: inherit + + diff --git a/.github/workflows/content-release.yml b/.github/workflows/content-release.yml index da6db5ac1..89eddbe4b 100644 --- a/.github/workflows/content-release.yml +++ b/.github/workflows/content-release.yml @@ -5,12 +5,7 @@ permissions: contents: read # This is required for actions/checkout on: - repository_dispatch: - types: [content-release] - workflow_run: - workflows: ['Create Production Tag'] - types: [completed] - branches: [main] + # Runs when called from other workflows. Used for ongoing releases for dev/staging/prod. workflow_call: inputs: build_type: @@ -18,6 +13,7 @@ on: description: "Environment this workflow runs against" required: true default: 'PROD' + # Manual release. workflow_dispatch: inputs: build_type: @@ -31,7 +27,7 @@ on: - prod concurrency: - group: ${{ inputs.build_type || 'prod' }} + group: ${{ inputs.build_type || 'prod' }} env: SLACK_CHANNEL: C06DSBT7CBW #status-next-build @@ -42,7 +38,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@v4 + uses: aws-actions/configure-aws-credentials@v4.0.2 with: aws-region: us-gov-west-1 role-to-assume: ${{ vars.AWS_ASSUME_ROLE }} @@ -107,7 +103,7 @@ jobs: continue-on-error: true with: payload: '{"attachments": [{"color": "#2EB67D","blocks": [{"type": "section","text": {"type": "mrkdwn","text": "Stand by, content release for next-build coming up (using ${{ needs.validate-build-status.outputs.TAG }}). "}}]}]}' - channel_id: ${{ env.SLACK_CHANNEL }} + channel_id: ${{ env.SLACK_CHANNEL }} aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} @@ -133,14 +129,14 @@ jobs: env: NODE_EXTRA_CA_CERTS: /etc/ssl/certs/ca-certificates.crt APP_ENV: ${{ inputs.build_type || 'prod' }} - + ports: - 80 volumes: - /etc/ssl/certs:/etc/ssl/certs steps: - + - name: Export setup start time id: export-setup-start-time run: echo SETUP_START_TIME=$(date +"%s") >> $GITHUB_OUTPUT @@ -208,12 +204,12 @@ jobs: cd out ls -l fi - + - name: Build sitemap run: cd main && yarn build:sitemap - name: Configure AWS Credentials - uses: aws-actions/configure-aws-credentials@v4 + uses: aws-actions/configure-aws-credentials@v4.0.2 with: aws-region: us-gov-west-1 role-to-assume: ${{ vars.AWS_ASSUME_ROLE }} @@ -237,7 +233,7 @@ jobs: DEST: s3://next-content.dev.va.gov - if: inputs.build_type == 'staging' name: Deploy to S3 - run: | + run: | cd main && ./scripts/github-actions/deploy.sh -s $SRC -d $DEST -v ls cd out @@ -251,8 +247,8 @@ jobs: env: SRC: ./out/ DEST: s3://next-content.www.va.gov - - - if: inputs.build_type == '' + + - if: inputs.build_type == '' name: Deploy to S3 run: cd main && ./scripts/github-actions/deploy.sh -s $SRC -d $DEST -v env: @@ -262,7 +258,7 @@ jobs: - name: Export deploy end time id: export-deploy-end-time run: echo DEPLOY_END_TIME=$(date +"%s") >> $GITHUB_OUTPUT - + notify-success: name: Notify Success needs: [validate-build-status, build] @@ -282,7 +278,7 @@ jobs: aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@v4 + uses: aws-actions/configure-aws-credentials@v4.0.2 with: aws-region: us-gov-west-1 role-to-assume: ${{ vars.AWS_ASSUME_ROLE }} @@ -336,7 +332,7 @@ jobs: aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@v4 + uses: aws-actions/configure-aws-credentials@v4.0.2 with: aws-region: us-gov-west-1 role-to-assume: ${{ vars.AWS_ASSUME_ROLE }} @@ -380,7 +376,7 @@ jobs: METRIC_NAMESPACE: dsva_vagov.next_build steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v4 #uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Get current timestamp diff --git a/.github/workflows/gha-metrics-datadog.yml b/.github/workflows/gha-metrics-datadog.yml index 5d7f48377..04552240a 100644 --- a/.github/workflows/gha-metrics-datadog.yml +++ b/.github/workflows/gha-metrics-datadog.yml @@ -11,7 +11,7 @@ jobs: timeout-minutes: 10 steps: - name: Configure AWS Credentials - uses: aws-actions/configure-aws-credentials@e1e17a757e536f70e52b5a12b2e8d1d1c60e04ef # v2.0.0 + uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2 with: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} @@ -25,7 +25,7 @@ jobs: env_variable_name: GHA_CONTENT_BUILD_DATADOG_API_KEY - name: Send GitHub Actions metrics to DataDog - uses: int128/datadog-actions-metrics@5dbc8b81eb6d1b3cbd24099ff83373df472e0e36 # v1.95.0 + uses: int128/datadog-actions-metrics@85755d0566a4b458f10acbaf68661eb1060cb2fe # v1.96.0 with: datadog-api-key: ${{ env.GHA_CONTENT_BUILD_DATADOG_API_KEY }} collect-job-metrics: true diff --git a/.github/workflows/mirror-images.yml b/.github/workflows/mirror-images.yml index efd296eb3..a962d1604 100644 --- a/.github/workflows/mirror-images.yml +++ b/.github/workflows/mirror-images.yml @@ -67,7 +67,7 @@ jobs: echo "IMAGE_TAG=$(cat tag.txt)" >> $GITHUB_ENV - name: Configure AWS Credentials - uses: aws-actions/configure-aws-credentials@v4 + uses: aws-actions/configure-aws-credentials@v4.0.2 with: aws-region: us-gov-west-1 role-to-assume: ${{ vars.AWS_ASSUME_ROLE }} diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index e097a8180..b10e7d461 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -13,7 +13,7 @@ jobs: if: github.event.deployment_status.state == 'success' steps: - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@v4 + uses: aws-actions/configure-aws-credentials@v4.0.2 with: aws-region: us-gov-west-1 role-to-assume: ${{ vars.AWS_ASSUME_ROLE }} diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml index a23b52052..25e9d125c 100644 --- a/.github/workflows/preview.yml +++ b/.github/workflows/preview.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@v4 + uses: aws-actions/configure-aws-credentials@v4.0.2 with: aws-region: us-gov-west-1 role-to-assume: ${{ vars.AWS_ASSUME_ROLE }} diff --git a/.github/workflows/recurring-release.yml b/.github/workflows/recurring-release.yml deleted file mode 100644 index 32031df82..000000000 --- a/.github/workflows/recurring-release.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: recurring release -on: - workflow_dispatch: - - schedule: - - cron: "*/30 8-20 * * 1-5" # run a build to prod every 30 minutes from 8am to 8pm monday to friday - -jobs: - content-release: - uses: department-of-veterans-affairs/next-build/.github/workflows/content-release.yml@main - with: - build_type: "prod" - secrets: inherit - - content-release-dev: - uses: department-of-veterans-affairs/next-build/.github/workflows/content-release.yml@main - with: - build_type: "dev" - secrets: inherit - - content-release-staging: - uses: department-of-veterans-affairs/next-build/.github/workflows/content-release.yml@main - with: - build_type: "staging" - secrets: inherit - - diff --git a/.github/workflows/update-manifest.yml b/.github/workflows/update-manifest.yml index 1c2d5729e..cd39b7e53 100644 --- a/.github/workflows/update-manifest.yml +++ b/.github/workflows/update-manifest.yml @@ -66,7 +66,7 @@ jobs: echo "IMAGE_TAG=$(cat tag.txt)" >> $GITHUB_ENV - name: Configure AWS Credentials - uses: aws-actions/configure-aws-credentials@v4 + uses: aws-actions/configure-aws-credentials@v4.0.2 with: aws-region: us-gov-west-1 role-to-assume: ${{ vars.AWS_ASSUME_ROLE }} diff --git a/.yarn/cache/@mswjs-interceptors-npm-0.35.0-965cf913d0-5bba94b027.zip b/.yarn/cache/@mswjs-interceptors-npm-0.35.0-965cf913d0-5bba94b027.zip deleted file mode 100644 index f64854488..000000000 Binary files a/.yarn/cache/@mswjs-interceptors-npm-0.35.0-965cf913d0-5bba94b027.zip and /dev/null differ diff --git a/.yarn/cache/@mswjs-interceptors-npm-0.35.8-8fc56ce517-1ba90a4974.zip b/.yarn/cache/@mswjs-interceptors-npm-0.35.8-8fc56ce517-1ba90a4974.zip new file mode 100644 index 000000000..a28c8c0e3 Binary files /dev/null and b/.yarn/cache/@mswjs-interceptors-npm-0.35.8-8fc56ce517-1ba90a4974.zip differ diff --git a/.yarn/cache/@next-swc-darwin-arm64-npm-14.2.9-efe42f73a9-8.zip b/.yarn/cache/@next-swc-darwin-arm64-npm-14.2.9-efe42f73a9-8.zip new file mode 100644 index 000000000..fe966b3e7 Binary files /dev/null and b/.yarn/cache/@next-swc-darwin-arm64-npm-14.2.9-efe42f73a9-8.zip differ diff --git a/.yarn/cache/@next-swc-linux-arm64-gnu-npm-14.2.9-9bc682653b-8.zip b/.yarn/cache/@next-swc-linux-arm64-gnu-npm-14.2.9-9bc682653b-8.zip new file mode 100644 index 000000000..cfdacfa57 Binary files /dev/null and b/.yarn/cache/@next-swc-linux-arm64-gnu-npm-14.2.9-9bc682653b-8.zip differ diff --git a/.yarn/cache/@next-swc-linux-arm64-musl-npm-14.2.9-d6d526ec92-8.zip b/.yarn/cache/@next-swc-linux-arm64-musl-npm-14.2.9-d6d526ec92-8.zip new file mode 100644 index 000000000..ec1799fe6 Binary files /dev/null and b/.yarn/cache/@next-swc-linux-arm64-musl-npm-14.2.9-d6d526ec92-8.zip differ diff --git a/.yarn/cache/msw-npm-2.4.4-701fcac5a9-9942c90ffe.zip b/.yarn/cache/msw-npm-2.4.4-701fcac5a9-9942c90ffe.zip deleted file mode 100644 index e5079c097..000000000 Binary files a/.yarn/cache/msw-npm-2.4.4-701fcac5a9-9942c90ffe.zip and /dev/null differ diff --git a/.yarn/cache/msw-npm-2.4.9-254c98033d-add5a614ce.zip b/.yarn/cache/msw-npm-2.4.9-254c98033d-add5a614ce.zip new file mode 100644 index 000000000..544e5b114 Binary files /dev/null and b/.yarn/cache/msw-npm-2.4.9-254c98033d-add5a614ce.zip differ diff --git a/.yarn/cache/path-to-regexp-npm-6.2.2-0bf7f6805c-b7b0005c36.zip b/.yarn/cache/path-to-regexp-npm-6.2.2-0bf7f6805c-b7b0005c36.zip deleted file mode 100644 index 9ba9990fc..000000000 Binary files a/.yarn/cache/path-to-regexp-npm-6.2.2-0bf7f6805c-b7b0005c36.zip and /dev/null differ diff --git a/.yarn/cache/path-to-regexp-npm-6.3.0-ee2cdde576-eca78602e6.zip b/.yarn/cache/path-to-regexp-npm-6.3.0-ee2cdde576-eca78602e6.zip new file mode 100644 index 000000000..a48cf19d9 Binary files /dev/null and b/.yarn/cache/path-to-regexp-npm-6.3.0-ee2cdde576-eca78602e6.zip differ diff --git a/READMEs/business-logic.md b/READMEs/business-logic.md new file mode 100644 index 000000000..1d0aa4375 --- /dev/null +++ b/READMEs/business-logic.md @@ -0,0 +1,94 @@ +# Business Logic + +The purpose of this README is to record and track business logic. What does it do? Who uses it? Why is it important? + +> [!NOTE] +> Copy and paste the accordion below to use as a template for documenting new business logic. + +
+Business logic template + +### Overview + +### Detailed Explanation + +### Examples + +## Implementation + +This is implemented on all event pages. The file that handles the time zone localization is date.ts + +## Contact/Owner + +Contact the Design Team for decisions on how timezones should appear. + +
+ +--- + +
+Node-Event Timezones + +### Overview + +08/2024 [Slack Thread](https://dsva.slack.com/archives/C01SR56755H/p1723476807939299) +For event articles, it was decided to keep time localization on Next rather than mimic production in which the articles were set in the timezone that the article was created in. + +### Detailed Explanation + +- What it does + - Time localization refers to the process of adapting the time displayed in an application to the correct time zone of the user. +- Why it's necessary + - This is important in applications that are used across different time zones to ensure that all users see times and dates that are relevant to their location. +- How it interacts with other components or steps + - This is referenced in all events. + +### Examples + +- Given a user wants to know about when an event is being held. +- When the user opens an event article about the event on www.va.gov/``/events +- Then on the event article, the `when` section should show the user the date and time, updated to the user's time localization, of when the event is being held. + Screenshot 2024-09-23 at 2 30 35 PM + +## Implementation + +The timezone calculations can be found in the [date.ts](src/lib/utils/date.ts) file line 219 `deriveFormattedTimestamp`. + +## Contact/Owner + +Design Team and Sitewide + +
+ +
+Node-Event Registered Events + +### Overview + +Next has a condition that detects whether an event has passed. If the event has passed then the register link becomes red text saying "This event already happened." + +### Detailed Explanation + +- What it does + - It prevents users from getting access to the register link for a past event. +- Why it's necessary + - This prevents users from being redirected to a site with an expired registration event. It enhances the user experience by ensuring users only interact with current and relevant events. +- How it interacts with other components or steps + - This is referenced in all events. + +### Examples + +- Given a user wants to register for an event. +- When the user opens the event article and the event has passed, +- Then the text "This event already happened" should be placed where the registration link would have been. + Screenshot 2024-09-24 at 11 43 42 AM + +## Implementation + +The business logic can be found in the [event index.ts](src/templates/layouts/event/index.tsx) file line 224. + +## Contact/Owner + +As of now this is an AP implementation. + +
diff --git a/READMEs/devops/content-release.md b/READMEs/devops/content-release.md index 68001e28f..36bb22f46 100644 --- a/READMEs/devops/content-release.md +++ b/READMEs/devops/content-release.md @@ -4,11 +4,27 @@ Content Release is what VA teams call the process of moving new published conten See [CMS Content Release](https://github.com/department-of-veterans-affairs/va.gov-cms/blob/main/READMES/cms-content-release.md) for more information on how content release is currently triggered via CMS for `content-build` and BRD. -In the short term, next-build will operate in very much the same way. When content is published in Drupal, a dispatch to our [content-release workflow](/.github/workflows/content-release.yml) will be triggered. This workflow builds all the static pages and assets currently known to next-build (as discovered by `RESOURCE_TYPES_TO_BUILD` in the catchall [slug file](/READMEs/slug.md)). It also generates a sitemap for these pages. Once the build process is completed, all of these items are pushed to the appropriate [S3 bucket](/READMEs/devops/infrastructure.md). Once the files are uploaded to S3, they are available for public traffic. +In the short term, next-build will operate in very much the same way. All content that is managed by Next Build will be built with each content release, regardless of whether it is new/changed or unchanged. -This workflow also happens whenever new code is merged to the main branch, to ensure the S3 bucket has the most up-to-date changes. +## Production content release -Right now, the workflow always runs using prod.cms.va.gov as it's data source and pushes output to the production next-content.www S3 bucket. If/when the workflow is parameterized to run against multiple targets (similar to how content-build builds `vagovdev`, `vagovstaging` and `vagovprod`), the sources and output buckets should also be adjusted. +Production content release currently is triggered by the following events: + +- On a schedule, every 30 minutes between 8 am and 8 pm ET +- Manually through the Github Actions interface +- When specific content is published in the CMS + +Production content releases use https://prod.cms.va.gov/ as their content source. + +## Dev and Staging content release + +Dev and Staging content releases are triggered by the following events: + +- On a schedule, nightly at 5:05 am ET or 5:35 am ET for Dev arnd Staging respectively. This keeps content relatively fresh even when there are no code changes to trigger a Dev or Staging content release. +- When any code is merged to the `main` branch of Next Build and has a successfull CI run on main - this is to keep Dev and Staging up-to-date with code changes they come in. +- Manually through the Github Actions interface + +Dev and Staging content releases use https://main-medc0xjkxm4jmpzxl3tfbcs7qcddsivh.ci.cms.va.gov/ as their content source. # Archiving diff --git a/READMEs/env-loader.md b/READMEs/env-loader.md index de14357ba..ceeac5062 100644 --- a/READMEs/env-loader.md +++ b/READMEs/env-loader.md @@ -4,17 +4,17 @@ The env-loader package is our custom solution for ingesting environment variable It collects variables from: -1. appropriate `.env` file in `envs/` based on the `APP_ENV` env var +1. the CMS environment's defined feature flags -- (defaults to `.env.local`) +- which CMS enviroment determined via `NEXT_PUBLIC_BASE_DRUPAL_URL` env var -2. the CMS environment's defined feature flags +2. appropriate `.env` file in `envs/` based on the `APP_ENV` env var -- which CMS enviroment determined via `NEXT_PUBLIC_BASE_DRUPAL_URL` env var +- (defaults to `.env.local`) 3. CLI options included with the command -After collecting (and overwriting values as needed based on the order above), all env vars are set and the command runs. +After collecting (and overwriting values as needed based on the order above), all env vars are set and the command runs. Keep in mind the ordering. If the same environment variable is set in both the CMS feature flags and in the .env file, the value in the .env file will be chosen. For a full list of CLI options available, see [cli-options.tsx](packages/env-loader/src/cli-options.ts) diff --git a/READMEs/images/feature-toggle-admin.png b/READMEs/images/feature-toggle-admin.png new file mode 100644 index 000000000..cf7951381 Binary files /dev/null and b/READMEs/images/feature-toggle-admin.png differ diff --git a/READMEs/layout-rollout.md b/READMEs/layout-rollout.md new file mode 100644 index 000000000..27b9f5d72 --- /dev/null +++ b/READMEs/layout-rollout.md @@ -0,0 +1,191 @@ +# Feature Flags + +Creating a template for CMS content in Next Build requires coordination between Next Build and the CMS. Migrating an existing template in Content Build into Next Build additionally requires coordination in that repo. + +We want to be able to work on a layout without fear that Next Build will attempt to build and deploy the template before it is ready. We also want to be able to control whether the template is built from one system or the other, without needing to coordinate deploys. + +## CMS feature flags + +The CMS has a feature flag system which it calls 'Feature Toggles'. These are strings with a corresponding boolean value, which can be controlled through the CMS admin UI. + +### Admin + +In the CMS, the Feature Toggle admin can be found at [https://prod.cms.va.gov/admin/config/system/feature_toggle](https://prod.cms.va.gov/admin/config/system/feature_toggle) for Prod, or the equivalent URL on the CMS environment you're working with (admin required). + +![The VA CMS Feature Toggle admin page](images/feature-toggle-admin.png) + +A checked value corresponds to 'on' or 'true' for the string in question. + +### Adding a new feature flag + +Adding a new feature flag is a CMS code change. The list of feature flags is maintained in the repo at [config/sync/feature_toggle.features.yml](https://github.com/department-of-veterans-affairs/va.gov-cms/blob/main/config/sync/feature_toggle.features.yml). Adding a new flag is as simple as adding a new item under `features:`. + +### Using feature flags in code + +In order to help understand how the feature flags work, there is [a set of testing steps that shows how feature flags should function in code](#local-testing-of-feature-flags) at the end of this readme. + +#### Next Build + +In Next Build, the feature flag values for the connected CMS instance are made available as environment variables. So for example, if there is a feature flag `FEATURE_NEXT_BUILD_CONTENT_LANDING_PAGE` in the CMS, in Next Build it can be referenced at any time via `process.env.FEATURE_NEXT_BUILD_CONTENT_LANDING_PAGE`. + +An enabled feature flag environment variable has a **string** value of `'true'`. Any other value is false. + +#### Content Build + +In Content Build, CMS feature flags are loaded as a global. They can be referenced with this code line: + +``` + const { cmsFeatureFlags } = global; +``` + +This global variable becomes available after options have loaded, and cannot be referenced until then. + +In Content Build, feature flag values are 'truthy' or 'falsy'. For example, `cmsFeatureFlags.FEATURE_ALL_HUB_SIDE_NAVS` will evaluate to `true` or `false` and can be used as such. + +#### CMS + +In the CMS, the class that allows code to retrieve flag values is `Drupal\feature_toggle\FeatureStatus`. Typically, this class is loaded into another class via dependency injection. Values can be retrieved via the method `FeatureStatus->getStatus($flag_name)`. + +## CMS requirements for rollout + +In order for rollout to proceed, a few things need to be done on the CMS side. + +1. **The content type must exist in the CMS.** This should be obvious, but you cannot retrieve data for a content type if it doesn't exist. + +1. **A Next Drupal content entity must exist for the content type.** The primary function of this content entity is to control how the CMS manages content preview for the content type. The procedure for creating a content entity is described in the [Preview documentation under "Content Configuration"](./preview.md#content-configuration). + +1. **A feature flag must exist for the content type.** Feature flags for content types are of the form `FEATURE_NEXT_BUILD_CONTENT_`, where the machine name is the machine name of that content type in Drupal, in all caps. The machine name should match the machine name in Drupal, even if that machine name is truncated or misspelled. So for example: + + - `FEATURE_NEXT_BUILD_CONTENT_VBA_FACILITY` + - `FEATURE_NEXT_BUILD_CONTENT_HEALTH_CARE_REGION_DETAIL_PAGE` + - `FEATURE_NEXT_BUILD_CONTENT_VAMC_SYSTEM_MEDICAL_RECORDS_OFFI` + +## Next Build use of feature flags + +When Next Build connects to a CMS instance, it will load the feature flag state of that CMS instance. In [[[...slug]].tsx](./[[...slug]].md), this feature flag state is used to determine whether a content type should be allowed to build or not. This is in addition to the addition of a given content type to `PAGE_RESOURCE_TYPES` in [resourceTypes.ts](../src/lib/constants/resourceTypes.ts). + +If the feature flag for a given content type is not active, or an equivalent environment variable is not set for that content type, [[[...slug]].tsx](./[[...slug]].md) will not build the page. + +### Development + +During local development, you will need to activate the content type's feature flag or environment variable, so that you can build pages that are otherwise not active. This can be done one of two ways: + +1. **Turn the flag on in your local CMS.** If you are developing against a local CMS, you are free to enable the appropriate flag in that CMS. This will be located at https://va-gov-cms.ddev.site/admin/config/system/feature_toggle. + +2. **Set the environment variable in your .env.local file.** You can enable a specific content type by adding its environment variable with a value of `true`. This will override the flag value you are receiving from the CMS instance. + + For example, if you want to enable the Vet Center content type (machine name `vet_center`), you would add the following to your .env.local file: + + ``` + FEATURE_NEXT_BUILD_CONTENT_VET_CENTER=true + ``` + + Alternately, setting the following special environment variable will bypass the flag system and enable all content types that Next Build is aware of: + + ``` + FEATURE_NEXT_BUILD_CONTENT_ALL=true + ``` + + It is best to only use this environment variable locally. + +### Review & Tests + +In order to effectively review and test the use of these flags, they will need to be enabled for the Tugboat and Test environments. This is because those environments make use of databases that derive from the Production database, and the feature flags must not be set on the Production CMS. + +When you are submitting a PR, add your feature flag variable to .env.test and .env.tugboat, so that the content type is enabled for those environments. + +### Feature Flag variables on Dev, Staging, Prod + +When you are merging a new layout template and need to test it on Dev and Staging, you will need to add the feature flag variable to those environments. This is because the database for those environments is derived from the Production database, and the feature flag should not be enabled on Production until launch. These will need to be added to .env.dev and .env.staging, if testing on those environments is desired. + +Feature flag variables should _never_ be added to the .env.prod file. Feature flags on Prod must _always_ be controlled from the Prod CMS itself. + +## Content Build use of feature flags + +Feature flag usage in Content Build will primarily consist of disabling certain GraphQL queries. This should only be done if you feel very confident that you can roll out the content type in Next Build and simultaneously disable it in Content Build without issues. + +Work will most likely be done in [GetAllPages.graphql.js](https://github.com/department-of-veterans-affairs/content-build/blob/main/src/site/stages/build/drupal/graphql/GetAllPages.graphql.js), as this is where full retrieving of content types takes place. Let's say we want to allow Event Listing queries to be controlled by flags. The [Event Listing query fragment](https://github.com/department-of-veterans-affairs/content-build/blob/main/src/site/stages/build/drupal/graphql/GetAllPages.graphql.js#L118) is included in a larger GraphQL query which is structured as a string literal: + +```Javascript +// Surrounding context removed; see link above +` + ... bioPage + ... benefitListingPage + ... nodeEventListing + ... nodeEvent + ... storyListingPage +` +``` + +Using the flag can be done by using `${}` within that string literal to include JavaScript that can be interpolated: + +```Javascript +` + ... bioPage + ... benefitListingPage + ${ + // If the flag is not present and set, query and build event listings. + !cmsFeatureFlags.FEATURE_NEXT_BUILD_CONTENT_EVENT_LISTING + ? `... nodeEventListing` + : '' + } + ... nodeEvent + ... storyListingPage +` +``` + +Note the negation in front of the feature flag value. In most cases we want this code to be active when the feature flag is _inactive_. Activating the feature flag should deactivate the code. + +## Layout Rollout to Production + +In order to roll out a content type on production, the procedure is simple: + +1. **Ensure the flag for that content type is not checked in the Prod CMS.** This should be true from the beginning of the development process, but it is important to check this before deployment. + +1. **Deploy all code for Next Build and Content Build (if using flags in Content Build).** Provided the flag is inactive, code handling the templating of a given content type will not become active in production. Code deployments do not need to be coordinated. + +1. **Enable the flag in the Prod CMS.** This will activate the content type. When the flag becomes active, the following thing happen: + + a. Next Build production will become able to build the content type. + + b. If flags are used in Content Build, the change will also become active there. Typically this would turn off that content type in Content Build. + + c. CMS will begin using Next Build Preview Server links for that content type. Without the flag active, a content type will use Content Build Preview for its preview. Turning the flag on tells the CMS to use the Next Build link. + +## Local testing of feature flags + +To get a handle on how feature flags work, the following testing steps may help demonstrate how it is intended to work. + +### Setup + +1. In your local CMS instance, check out main, pull the latest DB (`ddev pull va --skip-files`), and then ensure it is running correctly. +2. Check this branch out for Next Build. +3. Make sure that your .env.local file is pointed towards your local CMS in .env.local. Make sure this is `http://va-gov-cms.ddev.site` rather than `https` +4. Start Next Build locally: `yarn dev` + +### First tests - enabling content types from the CMS. + +1. Visit an events listing page: http://localhost:3999/pittsburgh-health-care/events/. This should return a 404/page not found. +2. Visit the system feature toggle page, https://va-gov-cms.ddev.site/admin/config/system/feature_toggle. Find the Event Listing flag, check it, and save (`FEATURE_NEXT_BUILD_CONTENT_EVENT_LISTING`). +3. Stop and restart local Next Build. +4. Reload http://localhost:3999/pittsburgh-health-care/events/ (it may reload on its own). This should now load. +5. Visit any event page, i.e. http://localhost:3999/pittsburgh-health-care/events/72337/. It should return a 404. +6. Visit the system feature toggle page, https://va-gov-cms.ddev.site/admin/config/system/feature_toggle. Find the Event flag, check it, and save (`FEATURE_NEXT_BUILD_CONTENT_EVENT`). +7. Stop and restart local Next Build. +8. Reload http://localhost:3999/pittsburgh-health-care/events/72337/ (it may reload on its own). This page should now load. + +### Enabling content types from the environment file. + +1. Start your local Next Build if it is not running. +2. Visit a Vet Center page: http://localhost:3999/oklahoma-city-vet-center/. It should return a 404. +3. In your envs/.env.local file, add the following variable: `FEATURE_NEXT_BUILD_CONTENT_VET_CENTER=true` +4. Stop and restart local Next Build. +5. Reload http://localhost:3999/oklahoma-city-vet-center/ (it may reload on its own). The page should now load. + +### Testing the special all content variable. + +1. Start your local Next Build if it is not running. +2. Visit a Story page: http://localhost:3999/portland-health-care/stories/portland-veteran-receives-first-place-award-for-poetry-entry/. It should return a 404. +3. In your envs/.env.local file, add the following variable: `FEATURE_NEXT_BUILD_CONTENT_ALL=true` +4. Stop and restart local Next Build. +5. Reload http://localhost:3999/portland-health-care/stories/portland-veteran-receives-first-place-award-for-poetry-entry/ (it may reload on its own). The page should now load. diff --git a/READMEs/quickstart.md b/READMEs/quickstart.md new file mode 100644 index 000000000..09e3706b0 --- /dev/null +++ b/READMEs/quickstart.md @@ -0,0 +1,244 @@ +# Quickstart + +The goal of this document is to be used as a reference sheet to quickstart developing the frontend of next-build. It should be used as a reminder of common steps in the development process and redirect you to the relating documentation for more in-depth understanding. + +## Recommended READMEs to start with + +- [generators.md](READMEs/generators.md) : Read to understand how to quickly generate layout, component, and query templates +- [queries.md](READMEs/quickstart.md) : Read to understand the database queries or search parameters that are being used in your project, as this file typically contains information or documentation related to database interactions. +- [templates.md](READMEs/templates.md) : Read to understand the structure and organization of front-end templates in the src/templates directory, including their categorization, required files, and usage of React components and types. +- [typescript.md](READMEs/typescript.md) : Read to understand how Typescript is used in the next-build application, including the structure and usage of specific types, the flow of data through the application, and how to configure Typescript for development. It also provides insights into the application's architecture and the rationale behind certain design decisions. +- [testing.md](READMEs/testing.md) : Read to understand the testing procedures. +- [[...slug.md]]() : Read to understand how next-build handles page routing and the history and thought process to its decision. +- [preview.md](READMEs/preview.md) : Recommended README for preview issue during setup + + The rest of the READMEs still hold valuable information, but might be running in the background, used for specific situations, or holds information that will make the development process easier, but is not mandatory to get things up and running + +## Setting up the environment + +[Link to environment setup documentation](https://github.com/department-of-veterans-affairs/next-build/tree/main?tab=readme-ov-file#next-build) +A video walkthrough should be available to assist in setting up. If not compressed and posted here yet. The Slack thread in which they exist is [here](https://dsva.slack.com/archives/D071CCW690E/p1723650927105169). The 7 minute video is for setting up Next-Build. + +### Next-Build walkthrough setup + +> [!IMPORTANT] +> In order for next-build to have access to drupal data, safely acquire the `DRUPAL_CLIENT_ID` and the `DRUPAL_CLIENT_SECRET` from AWS SSM or someone with access to those values to implement in your env.local file. +> +> ``` +> DRUPAL_CLIENT_ID=Retrieve this from AWS SSM /cms/consumers/next-build/client_id +> DRUPAL_CLIENT_SECRET=Retrieve this from AWS SSM /cms/consumers/next-build/client_secret +> ``` + +> [!NOTE] +> Make sure you socks is on with `vtk socks on` if you are not using local CMS preview. +> +> - Without socks on, you won't be able to view tugboat, which is another area of testing that occurs after making a pull request. Un able to view tugboat prevents access to tugboats error logs. +> - [Mac installation for sock](https://vfs.atlassian.net/wiki/spaces/~6218e48cc34549007199170b/pages/2178187323/Install+SOCKS+proxy+on+Mac) +> - [Windos installation for socks](https://depo-platform-documentation.scrollhelp.site/getting-started/accessing-internal-tools-via-socks-proxy) + +## Structure + +This is a high-level breakdown of what will the core areas in the repository you will frequently hop between during development. + +- Queries + - In a single query file there are three areas that are often modified + - Define `query params` + - Update `data loader` + - Modify `formatter` +- Template + - The template refers to a folder with 3 files where the index.ts file is where you inject the formatted data and build the html structure +- Types + - When generating new layouts, new types will be created and existing types might need to be updated to work with new layouts. + +## Generating a layout + +As listed above, please read [generators.md](READMEs/generators.md) + +[Link to environment setup documentation](https://github.com/department-of-veterans-affairs/next-build/tree/main?tab=readme-ov-file#next-build) +A video walkthrough should be available to assist in setting up. If not compressed and posted here yet. The Slack thread in which they exist is [here](https://dsva.slack.com/archives/D071CCW690E/p1723650927105169). The 30 minute video is the layout creation walkthrough. + +> [!NOTE] +> Next-Build is not involve in the creation of new layouts from scratch at the moment. The goal is to translate all of Content-Build's existing layouts into Next-Build. + +> [!NOTE] +> Not all generated files are required to be used. It acts as a structured template of what is needed to build a layout. + +When creating a new layout, create a new feature branch from main and use `yarn plop` to generate a layout template. Running this comand will prompt you to choose the type of content you want to generate. The following instructions will go through each option. + +> [!NOTE] +> Branch naming has not been consistent and had followed the trend of what works best for the team. The AP Team of 2024 followed the naming conventions of `issue_#_(summary of ticket/task)` + +- Yarn Plop > Select **Content Type** + + Screenshot 2024-09-19 at 11 40 53 AM + + - **Content Type** generate these files + - Path `src/templates/layouts/` + - Within `` + - `index.ts` + - Define component and component rendering + - `index.test.tsx` + - Test suite for index.ts to pass Jest test and coverage + - `.stories.ts` + - Help develop component isolation and visually tests its behavior with various input + - Path `src/types/formatted/` + - Define the object and its properties + - Path `src/data/queries/` + - Interact with Drupal backend to fetch, format, and handle the data + - Path `src/data/queries/tests/` + - Jest test file for `.tsx` module + - Path `src/data/queries/tests/snapshots/` + - Automatically generated jest snapshot + - Compares current output of `formatData` to the snapshot + - Snapshot may not update immediately and would require to run a manual `yarn test -- -u`. Details from [testing.md](READMEs/testing.md) + - Path `src/mocks/` + - Copy and paste one JSON object from Drupal API to be used in Jest tests + - Path `playwright/tests/` + - Test Suite for playwright + +- Yarn Plop > Select **Component** + - This will only generate the component folder `` and the relating three files ` index.ts, index.tsx, and .stories.ts` under the `component` folder +- Yarn Plop > Select **Query** + - This will generate query file under the data/queries folder relating test + +## Development breakdown + +Formatting data, updating data, and creating new data types and objects will be the majority of the development time. +This is the suggested order to approach development, to not be overwhelmed with too many error messages. You can develop in any order. + +> [!TIP] +> I highly recommend starting with a layout that shares a similar structure as an existing one in Next-Build for easier transition. + +1. Start with api-explorer.ts and your layout query[^1] to set up and format the data that is needed for your layout + + - Api-explorer to see the values Drupal is sending via the JSON:API + - `yarn dev` to turn localhost on and then navigate to [http://localhost:3999/\_playground/api-explorer/](http://localhost:3999/_playground/api-explorer/) + - Useful for filling out mock.json and traversing through nested values + - if properties with nested properties are required, utilize the `...getNestedIncludes()` function to traverse through the nested properties in the api-explorer and for your query file's `query param` section. + + - `.getResourceCollection()` is where you specify the node, paragraph, etc from Drupal to grab + - `.addInclude([])` will return the highest level JSON of the specified node + - Specify which fields of interests to obtain the nest property information + - `.getNestedIncludes()` used to get multi-nested properties within fields + + - This function can cause more unexpected work, especially if the type needed to traverse the property has not been made yet. Existing ones would be `media-image` and `media-document` You might have to create a new component and/or query to fulfill the input needed to use `...getNestedIncludes()`. + +2. In layout query file[^2] + - Update the `query params` section with the properties needed for the layout. + - Update the `data loader` to use the correct `RESOURCE_TYPES`. + - Create more defined fields in the `formatter` and map the data to those fields. The new fields should be refined to hold only the necessary data needed to build your layout and remove the excess data. +3. Setting types the layout's formatted file[^3] + - A formatted file will generate as a part of the layout template. Here you will need to set the correct data types to the new fields created from the `formatter` in the relating query file[^4] + - This should resolve any errors relating to type conflicts or error messages claiming that property does not exist in the query file[^5]. +4. In the index.tsx file from the layout folder[^6] + - This is where the layout object is declared and uses the object's properties made from the `formatter` as arguments to be injects into the html structure to be rendered + +> [!IMPORTANT] +> Try to use va-components whenever possible. The va-components are imported to next build and exist in the `additional.d.ts` file. There will be some instance where va-component, such as content-build is not using the va-component and we must match production as closely as possible or there is a data-widget-type handling the rendering. + +> [!WARNING] +> The main tag is already applied to the wrapper file. Translate content below the main tag of the liquid template to prevent confusion on Ally or accessibility applications with having two `
` tags + +## Other existing relevant files + +Most of these files will also need to be updated when you create a new layout. + +- Pagination and Listings + - pageSizes.ts + - listingPages.ts +- Growing aggregated area for media types + - media.ts (both formatted/ and drupal/) +- Create identifies and Typescript types for resources + - resourceTypes.ts +- Folder types/drupal contains all the interfaces to extract and extend. + Folders listed below are likely need to be updated with new interfaces + - node.ts + - paragraph.ts +- If content goes to multiple organization levels like news story applies for VA and TRICARE + - constants.ts +- Helpful files for development + - api-explorer.tsx + - [[...slug]].tsx +- Reuse existing field type + - field_types_d.ts +- Another area to add your new node and types here for everything to connect + - queries/index.ts + +## Passing tests + +You won’t be able to commit unless: + +- There are no errors + + - Passing threshold must be 80% or above + + - Opening this file in the browser can identify which lines of code are not covered. `coverage/lcov-report/index.html` + + - To bypass with intentions to created draft PRs for code help and review you can use the -–no-verify with your commit command + +- Yarn test will run tests on the entirety of next-build + - Once you commit and push for pull request, a series of tests will run on the pull request +- One of the common points of failed passing is tugboat which will have an error log to view why tugboat failed + - Our [tugboat ReadME](READMEs/tugboat.md) is brief but should redirect to the VA tugboat doc for more information. + +## Test commands + +- yarn test +- yarn test:format +- yarn test:coverage +- yarn test – -u + - used to update snapshot when you receive an error that they are conflicting + +## Helpful tools and commands + +- yarn test:types + - List files that did not pass typechecks +- yarn test:formatted + - List files failing to pass Prettier formatting +- yarn test: coverage + - Shows list of information regarding coverage + - Passing threshold is 80% +- yarn test — -u + - Running `yarn test -- -u` will pass the `-u` flag to the underlying jest command being run with `yarn test` + - Also, updates snapshots in case the test is failing due to conflicting snapshots +- Working around shadow DOMs for Jest testing: + - Use .innerHTML to check if something is rendered + - Using the event callbacks bound to the component.\_\_events value + +## Troubleshooting + +- Placing console.log + - in the catch error section of [[...slug]].tsx can output helpful error messages in your terminal + - Cycle yarn dev and refresh your localhost to generate more detailed error message in your terminal + - Before return might appear like an error, but it should still work. React just doesn't like it. +- Identifying areas to increase passing score for Jest + - Open coverage/lcov-report/index.html in a browser to find which files and lines that are not being covered + +## Specific errors and failures + +- Tugboat failed: + - Check that quota limit has been reached and then merge the dependabots to make room + - Check tugboat logs + - Data may be null for specific fields + - Update field in your formatter (data/queries/.ts) +- Getting TypeError on Storybook on all paragraphs, layouts, commons, and components + - Delete & install node modules + - Delete & install yarn.lock +- Getting TypeError … null… static-pages.entry.js + - Check if you are calling a null property in your index.tsx +- If you see /bin/sh: : No such file or directory + - You might be using < > in your test title and should remove them +- If you get this error `if (typeof window !== "undefined") {throw new Error("You should not call getQueryParams on the client. This is a server-only call.");}` + - Then check if you have /_\*\* @jest-environment node_/ placed on your test file; otherwise your window will return defined rather than undefined + +[^1]: Refers to this file `src/data/queries/` + +[^2]: Refers to this file `src/data/queries/` + +[^3]: Refers to this file `src/types/formatted/` + +[^4]: Refers to this file `src/data/queries/` + +[^5]: Refers to this file `src/data/queries/` + +[^6]: Refers to files in this folder `src/templates/layouts/` diff --git a/envs/.env.dev b/envs/.env.dev index f65e47b86..928e70742 100644 --- a/envs/.env.dev +++ b/envs/.env.dev @@ -19,3 +19,7 @@ DRUPAL_PREVIEW_SECRET=secret NEXT_PUBLIC_GOOGLE_TAG_MANAGER_ID=GTM-WFJWBD NEXT_PUBLIC_GOOGLE_TAG_MANAGER_AUTH=N9BisSDKAwJENFQtQIEvXQ NEXT_PUBLIC_GOOGLE_TAG_MANAGER_PREVIEW=env-423 + +# Feature flags for enabling content types. These should only be added when you are preparing to go to prod and are testing on dev. +FEATURE_NEXT_BUILD_CONTENT_EVENT=true +FEATURE_NEXT_BUILD_CONTENT_EVENT_LISTING=true diff --git a/envs/.env.example b/envs/.env.example index bb3c91e8b..00f3f12cb 100644 --- a/envs/.env.example +++ b/envs/.env.example @@ -27,3 +27,13 @@ NEXT_PUBLIC_GOOGLE_TAG_MANAGER_PREVIEW=env-423 # Configure the localhost port for the Next.js dev server PORT=3999 + +# Set CMS feature flag values here in order to override values provided by the CMS. +# See /flags_list in your target CMS for these values, +# and /admin/config/system/feature_toggle to modify those values at the source. +# For example, enabling the following var tells Next Build to build Vet Center content. +# FEATURE_NEXT_BUILD_CONTENT_VET_CENTER=true + +# Enabling the following var tells Next Build to build all content types it knows about. +# Only use this locally or in testing. +# FEATURE_NEXT_BUILD_CONTENT_ALL=true diff --git a/envs/.env.prod b/envs/.env.prod index 25fe20ada..a3d830ad8 100644 --- a/envs/.env.prod +++ b/envs/.env.prod @@ -19,3 +19,13 @@ DRUPAL_PREVIEW_SECRET=secret NEXT_PUBLIC_GOOGLE_TAG_MANAGER_ID=GTM-WFJWBD NEXT_PUBLIC_GOOGLE_TAG_MANAGER_AUTH=XWK-rHkcb1wp4DCOCzhPiQ NEXT_PUBLIC_GOOGLE_TAG_MANAGER_PREVIEW=env-1 + +# FEATURE FLAG VARIABLES FOR CONTENT TYPES SHOULD NEVER BE ADDED TO THE PRODUCTION ENVIRONMENT HERE. +# Prod's values for these feature flags should always be controlled from the Prod CMS. +# For example, never add and enable a variable like the following to this file: +# FEATURE_NEXT_BUILD_CONTENT_EVENT=true +# Again, do NOT add these here. + +# ... Except, prior to initial launch, we will need these here for prod testing. +FEATURE_NEXT_BUILD_CONTENT_EVENT=true +FEATURE_NEXT_BUILD_CONTENT_EVENT_LISTING=true diff --git a/envs/.env.staging b/envs/.env.staging index ba84acf53..7c6d796bd 100644 --- a/envs/.env.staging +++ b/envs/.env.staging @@ -16,3 +16,7 @@ NEXT_PUBLIC_SITE_URL=https://staging.va.gov NEXT_PUBLIC_GOOGLE_TAG_MANAGER_ID=GTM-WFJWBD NEXT_PUBLIC_GOOGLE_TAG_MANAGER_AUTH=inC4EKQce9vlWpRVcowiyQ NEXT_PUBLIC_GOOGLE_TAG_MANAGER_PREVIEW=env-661 + +# Feature flags for enabling content types. These should only be added when you are preparing to go to prod and are testing on staging. +FEATURE_NEXT_BUILD_CONTENT_EVENT=true +FEATURE_NEXT_BUILD_CONTENT_EVENT_LISTING=true diff --git a/envs/.env.test b/envs/.env.test index d8b95a2c9..578a40c1f 100644 --- a/envs/.env.test +++ b/envs/.env.test @@ -14,3 +14,14 @@ NEXT_PUBLIC_SITE_URL=http://127.0.0.1:8001 # Configure the localhost port for the next.js dev server PORT=3999 + +# The Testing environment file list of flags should always match .env.tugboat's list. +# Tugboat is used for Playwright testing, and this environment is use for unit testing. +# Please keep these in sync. +FEATURE_NEXT_BUILD_CONTENT_EVENT=true +FEATURE_NEXT_BUILD_CONTENT_EVENT_LISTING=true +FEATURE_NEXT_BUILD_CONTENT_NEWS_STORY=true +FEATURE_NEXT_BUILD_CONTENT_STORY_LISTING=true +FEATURE_NEXT_BUILD_CONTENT_PRESS_RELEASE=true +FEATURE_NEXT_BUILD_CONTENT_PRESS_RELEASES_LISTING=true +FEATURE_NEXT_BUILD_CONTENT_VET_CENTER=true diff --git a/envs/.env.tugboat b/envs/.env.tugboat index b67352afe..95f17100a 100644 --- a/envs/.env.tugboat +++ b/envs/.env.tugboat @@ -22,3 +22,16 @@ DRUPAL_PREVIEW_SECRET=secret # Configure the localhost port for the Next.js server. This is used for Preview Servers on CMS Tugboats. https://tugboat.vfs.va.gov/5fd3b8ee7b4657022b5722d6 # Tugboat PR environments for next-build https://tugboat.vfs.va.gov/64d5537c2d3036648da7c7ff do not use this, as they build static files served via nginx. PORT=3999 + +# These flags are required to enable testing for specific content types that are not yet enabled on Prod. +# Add a flag here for a given content type layout if you are in the process of testing it. +# If you add a new content type flag variable here, you must also add it to .env.test. +# Please keep these in sync. +FEATURE_NEXT_BUILD_CONTENT_EVENT=true +FEATURE_NEXT_BUILD_CONTENT_EVENT_LISTING=true +FEATURE_NEXT_BUILD_CONTENT_NEWS_STORY=true +FEATURE_NEXT_BUILD_CONTENT_STORY_LISTING=true +FEATURE_NEXT_BUILD_CONTENT_PRESS_RELEASE=true +FEATURE_NEXT_BUILD_CONTENT_PRESS_RELEASES_LISTING=true +FEATURE_NEXT_BUILD_CONTENT_VET_CENTER=true + diff --git a/package.json b/package.json index f2be62066..b66c35c7f 100644 --- a/package.json +++ b/package.json @@ -128,7 +128,7 @@ "jest-environment-jsdom": "^29.7.0", "jest-watch-typeahead": "^2.2.2", "lint-staged": "^15.2.2", - "msw": "^2.3.1", + "msw": "^2.4.9", "nock": "^13.5.4", "node_extra_ca_certs_mozilla_bundle": "^1.0.6", "npm": "^10.8.2", diff --git a/packages/env-loader/src/index.ts b/packages/env-loader/src/index.ts index a6778341a..acf553f6f 100644 --- a/packages/env-loader/src/index.ts +++ b/packages/env-loader/src/index.ts @@ -33,8 +33,8 @@ export const processEnv = async (command: string): Promise => { process.env = { ...process.env, ...{ - ...envVars, ...cmsFeatureFlags, + ...envVars, ...cliOptions, }, } diff --git a/src/pages/[[...slug]].tsx b/src/pages/[[...slug]].tsx index a6f4ee22f..860f14e00 100644 --- a/src/pages/[[...slug]].tsx +++ b/src/pages/[[...slug]].tsx @@ -23,7 +23,10 @@ import { shouldHideHomeBreadcrumb } from '@/lib/utils/breadcrumbs' import { Event } from '@/templates/layouts/event' import { EventListing } from '@/templates/layouts/eventListing' import { getStaticPathsByResourceType } from '@/lib/drupal/staticPaths' -import { RESOURCE_TYPES } from '@/lib/constants/resourceTypes' +import { + RESOURCE_TYPES, + PAGE_RESOURCE_TYPES, +} from '@/lib/constants/resourceTypes' import { getExpandedStaticPropsContext, getStaticPropsResource, @@ -44,17 +47,31 @@ import { ResourcesSupport } from '@/templates/layouts/resourcesSupport' import { VetCenter as FormattedVetCenter } from '@/types/formatted/vetCenter' import { VetCenter } from '@/templates/layouts/vetCenter' -// We define this here because, theoretically, another file could build other types. -export const RESOURCE_TYPES_TO_BUILD = [ - RESOURCE_TYPES.STORY_LISTING, - RESOURCE_TYPES.STORY, - RESOURCE_TYPES.EVENT, - RESOURCE_TYPES.EVENT_LISTING, - RESOURCE_TYPES.PRESS_RELEASE, - RESOURCE_TYPES.PRESS_RELEASE_LISTING, - RESOURCE_TYPES.RESOURCES_SUPPORT, - RESOURCE_TYPES.VET_CENTER, -] as const +// IMPORTANT: in order for a content type to build in Next Build, it must have an appropriate +// environment variable set in one of two places: +// 1. The CMS feature flags for the target environment +// 2. The .env file for the given environment (i.e. .env.local) +// +// Please see READMEs/layout-rollout.md for more detailed information. + +// RESOURCE_TYPES_TO_BUILD technically is not guaranteed to be reassigned. +// eslint-disable-next-line prefer-const +let RESOURCE_TYPES_TO_BUILD = [] +// FEATURE_NEXT_BUILD_CONTENT_ALL is checked to allow local developers to bypass flag checks. +if (process.env.FEATURE_NEXT_BUILD_CONTENT_ALL === 'true') { + RESOURCE_TYPES_TO_BUILD = PAGE_RESOURCE_TYPES +} else { + // Check the env variables loaded from the CMS feature flags and env files to determine what + // content types to build. + for (let x = 0; x < PAGE_RESOURCE_TYPES.length; x++) { + const typeName = PAGE_RESOURCE_TYPES[x].replace(/^node--/, '').toUpperCase() + const flagName = `FEATURE_NEXT_BUILD_CONTENT_${typeName}` + // Note 'true' as a string is correct here. Env variables are always strings. + if (process.env[flagName] === 'true') { + RESOURCE_TYPES_TO_BUILD.push(PAGE_RESOURCE_TYPES[x]) + } + } +} export const DynamicBreadcrumbs = dynamic( () => import('@/templates/common/breadcrumbs'), diff --git a/yarn.lock b/yarn.lock index 650217022..09de3cf08 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2606,9 +2606,9 @@ __metadata: languageName: node linkType: hard -"@mswjs/interceptors@npm:^0.35.0": - version: 0.35.0 - resolution: "@mswjs/interceptors@npm:0.35.0" +"@mswjs/interceptors@npm:^0.35.8": + version: 0.35.8 + resolution: "@mswjs/interceptors@npm:0.35.8" dependencies: "@open-draft/deferred-promise": ^2.2.0 "@open-draft/logger": ^0.3.0 @@ -2616,7 +2616,7 @@ __metadata: is-node-process: ^1.2.0 outvariant: ^1.4.3 strict-event-emitter: ^0.5.1 - checksum: 5bba94b027f4e83e6f3c64f09962893799d31da7c36fbe5c2d2a6319b913bbd1e3bc47fb590e720f3a562d1c5d37b52d6eb9166dd6442ca5a8d22df8cf3ec9c9 + checksum: 1ba90a4974cd52d02d54f9d6c6c23c060b2ddbd25ab46ae10d3b5fc64ef5a9d3b72588730e3d246937c843953cbd85f249f5bed0329a399941c7ff547247d4a9 languageName: node linkType: hard @@ -13475,15 +13475,15 @@ __metadata: languageName: node linkType: hard -"msw@npm:^2.3.1": - version: 2.4.4 - resolution: "msw@npm:2.4.4" +"msw@npm:^2.4.9": + version: 2.4.9 + resolution: "msw@npm:2.4.9" dependencies: "@bundled-es-modules/cookie": ^2.0.0 "@bundled-es-modules/statuses": ^1.0.1 "@bundled-es-modules/tough-cookie": ^0.1.6 "@inquirer/confirm": ^3.0.0 - "@mswjs/interceptors": ^0.35.0 + "@mswjs/interceptors": ^0.35.8 "@open-draft/until": ^2.1.0 "@types/cookie": ^0.6.0 "@types/statuses": ^2.0.4 @@ -13492,7 +13492,7 @@ __metadata: headers-polyfill: ^4.0.2 is-node-process: ^1.2.0 outvariant: ^1.4.2 - path-to-regexp: ^6.2.0 + path-to-regexp: ^6.3.0 strict-event-emitter: ^0.5.1 type-fest: ^4.9.0 yargs: ^17.7.2 @@ -13503,7 +13503,7 @@ __metadata: optional: true bin: msw: cli/index.js - checksum: 9942c90ffe16bab04d7833f714726b84f4be8f7b1f92814a377bc973c153f303aaef6d30f824d6da8f034904b3abd3174655b4eea817dc86a6c8cebd058d15e5 + checksum: add5a614ce58f5e75c65afcb59b76d0d807b9103b7fb3aaf23efd6ebd82d79415ecd9bc55dd48bcc4c31ec7ce196a75ace46d94224f0a80567c89a190e367ba8 languageName: node linkType: hard @@ -13621,7 +13621,7 @@ __metadata: lint-staged: ^15.2.2 lodash: ^4.17.21 mq-polyfill: ^1.1.8 - msw: ^2.3.1 + msw: ^2.4.9 next: ^14.2.5 next-drupal: ^1.6.0 next-drupal-query: ^0.4.0 @@ -14870,10 +14870,10 @@ __metadata: languageName: node linkType: hard -"path-to-regexp@npm:^6.2.0": - version: 6.2.2 - resolution: "path-to-regexp@npm:6.2.2" - checksum: b7b0005c36f5099f9ed1fb20a820d2e4ed1297ffe683ea1d678f5e976eb9544f01debb281369dabdc26da82e6453901bf71acf2c7ed14b9243536c2a45286c33 +"path-to-regexp@npm:^6.3.0": + version: 6.3.0 + resolution: "path-to-regexp@npm:6.3.0" + checksum: eca78602e6434a1b6799d511d375ec044e8d7e28f5a48aa5c28d57d8152fb52f3fc62fb1cfc5dfa2198e1f041c2a82ed14043d75740a2fe60e91b5089a153250 languageName: node linkType: hard