diff --git a/.github/ISSUE_TEMPLATE/research-conversation-guide.md b/.github/ISSUE_TEMPLATE/research-conversation-guide.md new file mode 100644 index 0000000000..263cea3f88 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/research-conversation-guide.md @@ -0,0 +1,39 @@ +--- +name: Research Conversation Guide +about: Use this template when you are drafting a conversation guide +title: Draft [PRODUCT/INITIATIVE] conversation guide +labels: UX, Research +assignees: '' + +--- + +## Description + +### User story +**AS A** Researcher +**I WANT** to document the details for conducting [PRODUCT/INITIATIVE] research +**SO THAT** the research will achieve the stated goals and answer the research questions + +### Templates + +Use the appropriate template for the group you're conducting research with: +- [Editor-facing Conversation Guide Template](https://github.com/department-of-veterans-affairs/va.gov-team/blob/master/platform/cms/research/editor-moderation-guide.md) +- [Veteran-facing Conversation Guide Template](https://github.com/department-of-veterans-affairs/va.gov-team/blob/master/platform/research/planning/conversation-guide-template.md) + +## Suggested workflow/tasks: +- [ ] Brainstorm potential tasks +- [ ] Create initial draft of conversation guide +- [ ] Solicit review/feedback from Sitewide UX Lead +- [ ] Solicit review/feedback from Product Manager (PM) and/or other team members +- [ ] Solicit review/feedback from VA Product Owner (PO) async or in a meeting w/PM +- [ ] Test prototype(s) with conversation guide and align +- [ ] Post on github in project research folder for final approval before submitting to Research Review cycle + +## Acceptance Criteria +- [ ] Conversation guide drafted +- [ ] Feedback incorporated from Sitewide UX Lead +- [ ] Feedback incorporated from PM and/or other team members +- [ ] Feedback incorporated from VA PO +- [ ] Conversation guide aligns with prototype(s) +- [ ] Conversation guide posted on github in project research folder +- [ ] Final approval obtained from VA PO and documented at the bottom of the file in preparation for Research Review cycle diff --git a/.github/ISSUE_TEMPLATE/research-discovery.md b/.github/ISSUE_TEMPLATE/research-discovery.md new file mode 100644 index 0000000000..be5500260b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/research-discovery.md @@ -0,0 +1,32 @@ +--- +name: Research Discovery +about: Use this template when exploring if research is needed/viable +title: Discovery for [PRODUCT/INITIATIVE] research +labels: UX, Research +assignees: '' + +--- + +## Description + +Research Discovery is a time to establish the fundamental approach for a research initiative. Possible tasks may include: + +**What do we want to know?** +- [ ] Align with Product Manager & Product Owner on the high-level purpose and scope of the research +- [ ] Review Product outline to understand background context +- [ ] Draft big picture research questions + +**Has anyone else researched this before?** +- [ ] Review previous research on this Product (if available) +- [ ] Review Research Repo for previous relevant research from other teams +- [ ] Summarize findings from research review + +**How might we learn more?** +- [ ] Consider methodologies - do we have the right tools to build a useful prototype? +- [ ] Consider participants - do we have access to the right users? +- [ ] Consider timeline - how long will this take? how much time do we have? + +## Acceptance Criteria +- [ ] High-level scope of research is drafted and agreed upon +- [ ] Subsequent tickets are created + diff --git a/.github/ISSUE_TEMPLATE/research-plan-and-conversation-guide.md b/.github/ISSUE_TEMPLATE/research-plan.md similarity index 67% rename from .github/ISSUE_TEMPLATE/research-plan-and-conversation-guide.md rename to .github/ISSUE_TEMPLATE/research-plan.md index ae7075b2ed..d37c1ee0e0 100644 --- a/.github/ISSUE_TEMPLATE/research-plan-and-conversation-guide.md +++ b/.github/ISSUE_TEMPLATE/research-plan.md @@ -1,7 +1,7 @@ --- -name: Research Plan and Conversation Guide -about: Use this template when you are drafting a research plan & conversation guide -title: Draft [PRODUCT/INITIATIVE] Research Plan & Conversation Guide +name: Research Plan +about: Use this template when you are drafting a research plan +title: Draft [PRODUCT/INITIATIVE] research plan labels: UX, Research assignees: '' @@ -9,11 +9,9 @@ assignees: '' ## Description -Use the appropriate templates for the type of research you are conducting: +DEMO Use the appropriate templates for the type of research you are conducting: - [Editor-facing Research Plan Template](https://github.com/department-of-veterans-affairs/va.gov-team/blob/master/platform/cms/research/sitewide-cms-editor-research-plan-template.md) -- [Editor-facing Conversation Guide Template](https://github.com/department-of-veterans-affairs/va.gov-team/blob/master/platform/cms/research/editor-moderation-guide.md) - [Veteran-facing Research Plan Template](https://github.com/department-of-veterans-affairs/va.gov-team/blob/master/platform/research/research-plan-template.md) -- [Veteran-facing Conversation Guide Template](https://github.com/department-of-veterans-affairs/va.gov-team/blob/master/platform/research/planning/conversation-guide-template.md) Suggested workflow: - [ ] Create your initial drafts in Sharepoint for collaborative editing diff --git a/.github/ISSUE_TEMPLATE/research-recruitment-and-scheduling.md b/.github/ISSUE_TEMPLATE/research-prep.md similarity index 93% rename from .github/ISSUE_TEMPLATE/research-recruitment-and-scheduling.md rename to .github/ISSUE_TEMPLATE/research-prep.md index 819d3c07d7..b38086963e 100644 --- a/.github/ISSUE_TEMPLATE/research-recruitment-and-scheduling.md +++ b/.github/ISSUE_TEMPLATE/research-prep.md @@ -1,9 +1,8 @@ --- -name: Research Recruitment and Scheduling -about: Use this template when recruting and scheduling participants for a research - study -title: Recruit and schedule participants for [PRODUCT/INITIATIVE] research -labels: Design, Research +name: Research Prep Tasks +about: Use this template when prepping for a research study +title: Prep for [PRODUCT/INITIATIVE] research +labels: UX, Research assignees: '' --- diff --git a/.github/ISSUE_TEMPLATE/research-readout-and-documentation.md b/.github/ISSUE_TEMPLATE/research-readout-and-post-task.md similarity index 91% rename from .github/ISSUE_TEMPLATE/research-readout-and-documentation.md rename to .github/ISSUE_TEMPLATE/research-readout-and-post-task.md index f00b711202..446025cc56 100644 --- a/.github/ISSUE_TEMPLATE/research-readout-and-documentation.md +++ b/.github/ISSUE_TEMPLATE/research-readout-and-post-task.md @@ -1,8 +1,7 @@ --- -name: Research Readout and Documentation -about: Use this template when reporting your research via readouts and documentation. -title: Conduct [PRODUCT/INITIATIVE] Research Readout and Document Findings in Research - Repository +name: Research Readout and Post-Research tasks +about: Use this template when sharing your research via readouts and doing final clean-up tasks. +title: Conduct [PRODUCT/INITIATIVE] research readout and complete post-research tasks labels: Research, UX assignees: '' diff --git a/.github/ISSUE_TEMPLATE/research-sessions.md b/.github/ISSUE_TEMPLATE/research-sessions.md index 528c1fcfd1..1a7124788d 100644 --- a/.github/ISSUE_TEMPLATE/research-sessions.md +++ b/.github/ISSUE_TEMPLATE/research-sessions.md @@ -1,7 +1,7 @@ --- name: Research Sessions about: Use this template when you are conducting research session -title: Conduct [PRODUCT/INITIATIVE] Research Sessions +title: Conduct [PRODUCT/INITIATIVE] research sessions labels: UX, Research assignees: '' diff --git a/.github/ISSUE_TEMPLATE/research-synthesis-and-topline-summary.md b/.github/ISSUE_TEMPLATE/research-synthesis-and-repoting.md similarity index 90% rename from .github/ISSUE_TEMPLATE/research-synthesis-and-topline-summary.md rename to .github/ISSUE_TEMPLATE/research-synthesis-and-repoting.md index 4b0f24fba0..4892c5b593 100644 --- a/.github/ISSUE_TEMPLATE/research-synthesis-and-topline-summary.md +++ b/.github/ISSUE_TEMPLATE/research-synthesis-and-repoting.md @@ -1,8 +1,7 @@ --- -name: Research Synthesis and Topline Summary -about: Use this template when synthesizing your research and reporting the topline - findings. -title: Synthesize [PRODUCT/INITIATIVE] Research & Create Topline Summary +name: Research Synthesis and Reporting +about: Use this template when synthesizing your research and reporting the topline findings. +title: Synthesize [PRODUCT/INITIATIVE] research & create Topline Summary labels: Research, UX assignees: '' diff --git a/.github/ISSUE_TEMPLATE/runbook---ux-research.md b/.github/ISSUE_TEMPLATE/runbook---ux-research.md index ce407a8444..a8313db6bc 100644 --- a/.github/ISSUE_TEMPLATE/runbook---ux-research.md +++ b/.github/ISSUE_TEMPLATE/runbook---ux-research.md @@ -10,21 +10,20 @@ assignees: '' ## Description -Here are the steps to follow when setting up a new UX research process: -**Pre-work** -- [ ] Align with Product Manager & Product Owner on the high-level purpose and scope of the research -- [ ] Review Research Repo for previous relevant research -- [ ] Read and understand [Platform's Research Guidleines](https://depo-platform-documentation.scrollhelp.site/research-design/). This runbook is meant help reduce time creating tickets, not to replace or overrule those guidelines. +Here are the steps to follow when setting up a new UX research epic: **Setting up your Research Epic** +- [ ] Read and understand [Platform's Research Guidleines](https://depo-platform-documentation.scrollhelp.site/research-design/). This runbook is meant help reduce time creating tickets, not to replace or overrule those guidelines. - [ ] Create a Research [Epic](https://github.com/department-of-veterans-affairs/va.gov-cms/issues/new?assignees=&labels=Epic%2C+Needs+refining&template=cms-epic.md&title=%3CInsert+summary+of+epic%3E) for your product/initiative - [ ] Create a Research Folder following [Platform's Research guidance](https://depo-platform-documentation.scrollhelp.site/research-design/research-checklist#ResearchChecklist-1.Planningforresearch) -- [ ] Create a [Research Plan & Conversation Guide](https://github.com/department-of-veterans-affairs/va.gov-cms/issues/new?assignees=&labels=UX%2C+Research&template=research-plan-and-conversation-guide.md&title=Draft+%5BPRODUCT%2FINITIATIVE%5D+Research+Plan+%26+Conversation+Guide) issue -- [ ] Create a [Research Review Cycle](https://github.com/department-of-veterans-affairs/va.gov-cms/issues/new?assignees=&labels=UX%2C+Research&template=research-review-cycle.md&title=Conduct+%5BPRODUCT%2FINITIATIVE%5D+Research+Review+Cycle) issue -- [ ] Create a [Research Recruitment & Scheduling](https://github.com/department-of-veterans-affairs/va.gov-cms/issues/new?assignees=&labels=UX%2C+Research&template=research-recruitment-and-scheduling.md&title=Recruit+and+schedule+participants+for+%5BPRODUCT%2FINITIATIVE%5D+research) issue -- [ ] Create a [Research Sessions](https://github.com/department-of-veterans-affairs/va.gov-cms/issues/new?assignees=&labels=UX%2C+Research&template=research-sessions.md&title=Conduct+%5BPRODUCT%2FINITIATIVE%5D+Research+Sessions) issue -- [ ] Create a [Research Synthesis & Topline Summary](https://github.com/department-of-veterans-affairs/va.gov-cms/issues/new?assignees=&labels=UX%2C+Research&template=research-synthesis-and-topline-report.md&title=Synthesize+%5BPRODUCT%2FINITIATIVE%5D+Research+%26+Create+Topline+Summary) issue -- [ ] Create a [Research Readout & Documentation](https://github.com/department-of-veterans-affairs/va.gov-cms/issues/new?assignees=&labels=UX%2C+Research&template=research-readout-and-documentation.md&title=Conduct+%5BPRODUCT%2FINITIATIVE%5D+Research+Readout+and+Document+Findings+in+Research+Repository) issue +- [ ] Create a [Research Discovery](ADD LINK AS LAST STEP) issue +- [ ] Create a [Research Plan](ADD LINK AS LAST STEP) issue +- [ ] Create a [Research Conversation Guide](ADD LINK AS LAST STEP) issue +- [ ] Create a [Research Review Cycle](ADD LINK AS LAST STEP) issue +- [ ] Create a [Research Prep](ADD LINK AS LAST STEP) issue +- [ ] Create a [Research Sessions](ADD LINK AS LAST STEP) issue +- [ ] Create a [Research Synthesis & Reporting](ADD LINK AS LAST STEP) issue +- [ ] Create a [Research Readout & Post-tasks](ADD LINK AS LAST STEP) issue - [ ] Add all the above issues to the Research Epic and add dependencies ## Acceptance Criteria diff --git a/.gitignore b/.gitignore index 39f475fda7..89b52fc6b7 100644 --- a/.gitignore +++ b/.gitignore @@ -104,6 +104,9 @@ datadog-setup.php # Ignore Next (next-build) next +# Ignore oauth keys used for validating next-build preview api requests +public.key +private.key # Temporary .deb packages *.deb diff --git a/.tugboat/config.yml b/.tugboat/config.yml index c4a7c97f68..96e452dd70 100644 --- a/.tugboat/config.yml +++ b/.tugboat/config.yml @@ -104,6 +104,10 @@ services: - cp "${TUGBOAT_ROOT}"/.tugboat/*.crt /usr/local/share/ca-certificates - update-ca-certificates + # Write OAuth keys to files for next-build Preview Server validation + - echo "${OAUTH_PUBLIC_KEY}" >> ${TUGBOAT_ROOT}/public.key + - echo "${OAUTH_PRIVATE_KEY}" >> ${TUGBOAT_ROOT}/private.key + # Install drush-launcher, if desired. - wget -O /usr/local/bin/drush https://github.com/drush-ops/drush-launcher/releases/download/0.6.0/drush.phar - chmod +x /usr/local/bin/drush @@ -233,9 +237,17 @@ services: - find -L "${DOCROOT}/vendor/va-gov/content-build/node_modules/.bin" -type f -exec chmod +x {} \+ - find "${DOCROOT}/vendor/va-gov/content-build/script" -type f -exec chmod +x {} \+ - # Build storybook and the frontends in parallel + # Put necessary env variables in place for next's Drupal Preview before building server + # Need to construct this way instead of TUGBOAT_DEFAULT_SERVICE_URL in order to drop the trailing / + - echo "NEXT_PUBLIC_DRUPAL_BASE_URL=https://cms-${TUGBOAT_SERVICE_TOKEN}.${TUGBOAT_SERVICE_CONFIG_DOMAIN}" >> ${TUGBOAT_ROOT}/next/envs/.env.tugboat + - echo "NEXT_IMAGE_DOMAIN=https://cms-${TUGBOAT_SERVICE_TOKEN}.${TUGBOAT_SERVICE_CONFIG_DOMAIN}" >> ${TUGBOAT_ROOT}/next/envs/.env.tugboat + - echo "DRUPAL_CLIENT_ID=${DRUPAL_CLIENT_ID}" >> ${TUGBOAT_ROOT}/next/envs/.env.tugboat + - echo "DRUPAL_CLIENT_SECRET=${DRUPAL_CLIENT_SECRET}" >> ${TUGBOAT_ROOT}/next/envs/.env.tugboat + + # Build storybook and the frontends (web, next) in parallel - bash -lc 'time task --taskfile=tugboat.yml' - # Build next build server + + # Start the next build server - bash -lc 'composer va:next:start' memcache: diff --git a/READMES/drush.md b/READMES/drush.md index 5e01ea9751..8190798b89 100644 --- a/READMES/drush.md +++ b/READMES/drush.md @@ -14,6 +14,12 @@ See [SiteStatusCommands.php](../docroot/modules/custom/va_gov_build_trigger/src/ ### Content Release +There is a gradual migration taking place from the existing system to a refactored version intended to decouple behavior from environment, accomodate multiple frontends, etc. + +#### Current + +The current system's commands mostly relate to continuous builds and management of the content release state machine: + See [ContentReleaseCommands.php](../docroot/modules/custom/va_gov_build_trigger/src/Commands/ContentReleaseCommands.php). - `va-gov:content-release:advance-state` -- Advance the state like an external system would do through HTTP. @@ -22,19 +28,32 @@ See [ContentReleaseCommands.php](../docroot/modules/custom/va_gov_build_trigger/ - `va-gov:content-release:get-frontend-version` -- Get the frontend version that was requested by the user. - `va-gov:content-release:get-state` -- Get the current release state. - `va-gov:content-release:is-continuous-release-enabled` -- Check continuous release state. -- `va-gov:content-release:request-frontend-build` -- Request a frontend build (but do not initiate it). - `va-gov:content-release:reset-frontend-version` -- Reset the content release frontend version. - `va-gov:content-release:reset-state` -- Reset the content release state. - `va-gov:content-release:toggle-continuous` -- Toggle continuous release. +#### New + +Housed in the new system: + +See [RequestCommands.php](../docroot/modules/custom/va_gov_content_release/src/Commands/RequestCommands.php). + +- `va-gov-content-release:request:submit` -- Request a frontend build (but do not initiate it). + +See [FrontendVersionCommands.php](../docroot/modules/custom/va_gov_content_release/src/Commands/FrontendVersionCommands.php). + +- `va-gov-content-release:frontend-version:get` -- Get the currently selected version of the selected frontend (defaults to `content_build`). +- `va-gov-content-release:frontend-version:reset` -- Reset (to default, or `main`) the currently selected version of the selected frontend (defaults to `content_build`). +- `va-gov-content-release:frontend-version:set` -- Set the currently selected version of the selected frontend (defaults to `content_build`). + ### Metrics See [MetricsCommands.php](../docroot/modules/custom/va_gov_backend/src/Commands/MetricsCommands.php). - `va-gov:metrics:send` -- Send various application metrics to DataDog. - ### Outdated Content + See [CMS Notification System](https://github.com/department-of-veterans-affairs/va.gov-cms/tree/main/docroot/modules/custom/va_gov_notifications/README.md) for commands to test or execute the various outdated content sends. diff --git a/composer.lock b/composer.lock index f3d0db6162..5af212dc52 100644 --- a/composer.lock +++ b/composer.lock @@ -18395,16 +18395,16 @@ }, { "name": "phpstan/phpstan", - "version": "1.10.40", + "version": "1.10.41", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "93c84b5bf7669920d823631e39904d69b9c7dc5d" + "reference": "c6174523c2a69231df55bdc65b61655e72876d76" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/93c84b5bf7669920d823631e39904d69b9c7dc5d", - "reference": "93c84b5bf7669920d823631e39904d69b9c7dc5d", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/c6174523c2a69231df55bdc65b61655e72876d76", + "reference": "c6174523c2a69231df55bdc65b61655e72876d76", "shasum": "" }, "require": { @@ -18453,7 +18453,7 @@ "type": "tidelift" } ], - "time": "2023-10-30T14:48:31+00:00" + "time": "2023-11-05T12:57:57+00:00" }, { "name": "phpstan/phpstan-deprecation-rules", diff --git a/config/sync/next.next_site.next_build_preview_server.yml b/config/sync/next.next_site.next_build_preview_server.yml new file mode 100644 index 0000000000..3e3a99c8bb --- /dev/null +++ b/config/sync/next.next_site.next_build_preview_server.yml @@ -0,0 +1,11 @@ +uuid: 75dd1bfb-8507-4981-90b6-3830400e1434 +langcode: en +status: true +dependencies: { } +id: next_build_preview_server +label: 'Next Build Preview Server' +base_url: 'http://localhost:3000' +preview_url: 'http://localhost:3000/api/preview' +preview_secret: secret +revalidate_url: '' +revalidate_secret: '' diff --git a/config/sync/next.settings.yml b/config/sync/next.settings.yml index 19893cfd6f..6d1945a747 100644 --- a/config/sync/next.settings.yml +++ b/config/sync/next.settings.yml @@ -6,3 +6,7 @@ site_previewer_configuration: width: 100% sync_route: false sync_route_skip_routes: '' +preview_url_generator: simple_oauth +preview_url_generator_configuration: + secret_expiration: 300 +debug: false diff --git a/config/sync/simple_oauth.settings.yml b/config/sync/simple_oauth.settings.yml index f58228bc1d..0cffd710fb 100644 --- a/config/sync/simple_oauth.settings.yml +++ b/config/sync/simple_oauth.settings.yml @@ -3,7 +3,9 @@ _core: access_token_expiration: 300 authorization_code_expiration: 300 refresh_token_expiration: 1209600 -remember_clients: true token_cron_batch_size: 0 +public_key: ../public.key +private_key: ../private.key +remember_clients: true use_implicit: false disable_openid_connect: false diff --git a/config/sync/user.role.next_js.yml b/config/sync/user.role.next_js.yml index 20eeaa6867..aaab07f0a1 100644 --- a/config/sync/user.role.next_js.yml +++ b/config/sync/user.role.next_js.yml @@ -3,17 +3,24 @@ langcode: en status: true dependencies: module: + - content_moderation + - media - node - subrequests + - system - va_gov_backend third_party_settings: va_gov_backend: vgb_description: 'Role for Next.js JSON API data access.' id: next_js label: Next.js -weight: 8 +weight: 7 is_admin: null permissions: + - 'access content' - 'access user profiles' - - 'bypass node access' - 'issue subrequests' + - 'view all revisions' + - 'view any unpublished content' + - 'view latest version' + - 'view media' diff --git a/cypress.config.js b/cypress.config.js index 83620d5f18..95b3b8dd48 100644 --- a/cypress.config.js +++ b/cypress.config.js @@ -13,7 +13,7 @@ const path = require("path"); // This function is called when a project is opened or re-opened (e.g. due to // the project's config changing) -const BASE_URL = "http://va-gov-cms.ddev.site"; +const BASE_URL = process.env.BASE_URL || "https://va-gov-cms.ddev.site"; async function setupNodeEvents(on, config) { // This is required for the preprocessor to be able to generate JSON reports after each run, and more, diff --git a/docroot/modules/custom/va_gov_build_trigger/css/build_trigger_form.css b/docroot/modules/custom/va_gov_build_trigger/css/build_trigger_form.css deleted file mode 100644 index 5f608931b5..0000000000 --- a/docroot/modules/custom/va_gov_build_trigger/css/build_trigger_form.css +++ /dev/null @@ -1,42 +0,0 @@ -/** - * Content release form styling. - */ - -form.va-gov-build-trigger-build-trigger-form { - margin-top: 2em; -} - -form h2 { - margin-top: 2em; -} - -.form-actions .form-item-confirm { - margin-top: 2em; -} - -.form-item.form-item-details { - margin-top: 2em; -} - -fieldset.form-item { - margin-top: 1em; -} - -#edit-content-release-status-block--2 { - margin-top: 1.5em; -} - -#edit-content-release-status-block--2 [colspan]:not([colspan='1']) { - font-style: italic; - padding: 1.5em; - text-align: center; -} - -.form-item-cta.button--primary a { - color: #fff; -} - -/* ensures button to release content is on its own line */ -.va-gov-build-trigger-build-trigger-form .form-actions { - flex-direction: column; -} diff --git a/docroot/modules/custom/va_gov_build_trigger/drush.services.yml b/docroot/modules/custom/va_gov_build_trigger/drush.services.yml index e2dad42392..2d51d89184 100644 --- a/docroot/modules/custom/va_gov_build_trigger/drush.services.yml +++ b/docroot/modules/custom/va_gov_build_trigger/drush.services.yml @@ -9,7 +9,7 @@ services: arguments: - '@va_gov_build_trigger.release_state_manager' - '@va_gov_build_trigger.build_scheduler' - - '@va_gov_build_trigger.build_requester' + - '@va_gov_content_release.request' - '@state' - '@logger.factory' tags: diff --git a/docroot/modules/custom/va_gov_build_trigger/js/content_release_status_block.es6.js b/docroot/modules/custom/va_gov_build_trigger/js/content_release_status_block.es6.js deleted file mode 100644 index 794bd67d1d..0000000000 --- a/docroot/modules/custom/va_gov_build_trigger/js/content_release_status_block.es6.js +++ /dev/null @@ -1,23 +0,0 @@ -/** - * @file - */ - -(($, Drupal, once) => { - function refreshStatusBlock(url) { - $.get(url, (data) => { - $(".content-release-status-block").html(data); - }); - } - - Drupal.behaviors.contentReleaseStatusBlock = { - attach: (context, settings) => { - $(once("contentReleaseStatusBlock", "body", context)).on("load", () => { - window.setInterval(() => { - refreshStatusBlock( - settings.contentReleaseStatusBlock.blockRefreshPath - ); - }, 10000); - }); - }, - }; -})(jQuery, window.Drupal, window.once); diff --git a/docroot/modules/custom/va_gov_build_trigger/js/content_release_status_block.js b/docroot/modules/custom/va_gov_build_trigger/js/content_release_status_block.js deleted file mode 100644 index 799c8f8841..0000000000 --- a/docroot/modules/custom/va_gov_build_trigger/js/content_release_status_block.js +++ /dev/null @@ -1,22 +0,0 @@ -/** -* DO NOT EDIT THIS FILE. -* See the following change record for more information, -* https://www.drupal.org/node/2815083 -* @preserve -**/ -(function ($, Drupal, once) { - function refreshStatusBlock(url) { - $.get(url, function (data) { - $(".content-release-status-block").html(data); - }); - } - Drupal.behaviors.contentReleaseStatusBlock = { - attach: function attach(context, settings) { - $(once("contentReleaseStatusBlock", "body", context)).on("load", function () { - window.setInterval(function () { - refreshStatusBlock(settings.contentReleaseStatusBlock.blockRefreshPath); - }, 10000); - }); - } - }; -})(jQuery, window.Drupal, window.once); \ No newline at end of file diff --git a/docroot/modules/custom/va_gov_build_trigger/src/Commands/ContentReleaseCommands.php b/docroot/modules/custom/va_gov_build_trigger/src/Commands/ContentReleaseCommands.php index f7c74cb74b..45bc8bc85e 100644 --- a/docroot/modules/custom/va_gov_build_trigger/src/Commands/ContentReleaseCommands.php +++ b/docroot/modules/custom/va_gov_build_trigger/src/Commands/ContentReleaseCommands.php @@ -6,11 +6,10 @@ use Drupal\Core\State\StateInterface; use Drupal\va_gov_build_trigger\Controller\ContentReleaseNotificationController; use Drupal\va_gov_build_trigger\EventSubscriber\ContinuousReleaseSubscriber; -use Drupal\va_gov_build_trigger\Service\BuildRequester; -use Drupal\va_gov_build_trigger\Service\BuildRequesterInterface; use Drupal\va_gov_build_trigger\Service\BuildSchedulerInterface; use Drupal\va_gov_build_trigger\Service\ReleaseStateManager; use Drupal\va_gov_build_trigger\Service\ReleaseStateManagerInterface; +use Drupal\va_gov_content_release\Request\RequestInterface; use Drush\Commands\DrushCommands; /** @@ -25,18 +24,18 @@ class ContentReleaseCommands extends DrushCommands { protected $releaseStateManager; /** - * The build requester service. + * The build scheduler service. * - * @var \Drupal\va_gov_build_trigger\Service\BuildRequesterInterface + * @var \Drupal\va_gov_build_trigger\Service\BuildSchedulerInterface */ - protected $buildRequester; + protected $buildScheduler; /** - * The build scheduler service. + * The content release request service. * - * @var \Drupal\va_gov_build_trigger\Service\BuildSchedulerInterface + * @var \Drupal\va_gov_content_release\Request\RequestInterface */ - protected $buildScheduler; + protected $requestService; /** * The state management service. @@ -59,8 +58,8 @@ class ContentReleaseCommands extends DrushCommands { * The release state manager service. * @param \Drupal\va_gov_build_trigger\Service\BuildSchedulerInterface $buildScheduler * The build scheduler service. - * @param \Drupal\va_gov_build_trigger\Service\BuildRequesterInterface $buildRequester - * The build requester service. + * @param \Drupal\va_gov_content_release\Request\RequestInterface $requestService + * The request service. * @param \Drupal\Core\State\StateInterface $state * The state service. * @param \Drupal\Core\Logger\LoggerChannelFactoryInterface $loggerChannelFactory @@ -69,13 +68,13 @@ class ContentReleaseCommands extends DrushCommands { public function __construct( ReleaseStateManagerInterface $releaseStateManager, BuildSchedulerInterface $buildScheduler, - BuildRequesterInterface $buildRequester, + RequestInterface $requestService, StateInterface $state, LoggerChannelFactoryInterface $loggerChannelFactory ) { $this->releaseStateManager = $releaseStateManager; $this->buildScheduler = $buildScheduler; - $this->buildRequester = $buildRequester; + $this->requestService = $requestService; $this->state = $state; $this->logger = $loggerChannelFactory->get('va_gov_build_trigger'); } @@ -91,19 +90,6 @@ public function resetState() { $this->logger()->info('Content release state has been reset to \'ready\'.'); } - /** - * Reset the content release frontend version. - * - * @command va-gov:content-release:reset-frontend-version - * @aliases va-gov-content-release-reset-frontend-version - */ - public function resetFrontendVersion() { - $this->state->delete(BuildRequester::VA_GOV_FRONTEND_VERSION); - $this->logger()->info('Content release state has been reset to @state.', [ - '@state' => ReleaseStateManager::STATE_DEFAULT, - ]); - } - /** * Advance the state like an external system would do through HTTP. * @@ -131,17 +117,6 @@ public function advanceState($state) { ]); } - /** - * Get the frontend version that was requested by the user. - * - * @command va-gov:content-release:get-frontend-version - * @aliases va-gov-content-release-get-frontend-version - */ - public function getFrontendVersion() { - $state = $this->state->get(BuildRequester::VA_GOV_FRONTEND_VERSION, '__default'); - $this->io()->write($state); - } - /** * Get the current release state. * @@ -153,18 +128,6 @@ public function getReleaseState() { $this->io()->write($state); } - /** - * Request a frontend build (but do not initiate it). - * - * @command va-gov:content-release:request-frontend-build - * @aliases va-gov-content-release-request-frontend-build - */ - public function requestFrontendBuild() { - $this->buildRequester->resetFrontendVersion(); - $this->buildRequester->requestFrontendBuild('Build requested via Drush.'); - $this->io()->writeln('Frontend build has been requested'); - } - /** * Make sure builds are going out at least hourly during business hours. * @@ -184,7 +147,7 @@ public function checkScheduledBuild() { public function checkStale() { if ($this->releaseStateManager->releaseStateIsStale()) { $this->resetState(); - $this->requestFrontendBuild(); + $this->requestService->submitRequest('Submitting new request due to staleness.'); } } diff --git a/docroot/modules/custom/va_gov_build_trigger/src/Controller/ContentReleaseRequestController.php b/docroot/modules/custom/va_gov_build_trigger/src/Controller/ContentReleaseRequestController.php index b94c42b8e4..ff939a5874 100644 --- a/docroot/modules/custom/va_gov_build_trigger/src/Controller/ContentReleaseRequestController.php +++ b/docroot/modules/custom/va_gov_build_trigger/src/Controller/ContentReleaseRequestController.php @@ -3,10 +3,10 @@ namespace Drupal\va_gov_build_trigger\Controller; use Drupal\Core\Controller\ControllerBase; +use Drupal\va_gov_content_release\Request\RequestInterface; use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\HttpFoundation\Response; -use Drupal\va_gov_build_trigger\Service\BuildRequesterInterface; use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; /** @@ -15,11 +15,11 @@ class ContentReleaseRequestController extends ControllerBase { /** - * The release state manager. + * The request service. * - * @var \Drupal\va_gov_build_trigger\Service\BuildRequesterInterface + * @var \Drupal\va_gov_content_release\Request\RequestInterface */ - protected $buildRequester; + protected $requestService; /** * The current request stack. @@ -31,13 +31,13 @@ class ContentReleaseRequestController extends ControllerBase { /** * Constructor for the content release request controller. * - * @param \Drupal\va_gov_build_trigger\Service\BuildRequesterInterface $buildRequester + * @param \Drupal\va_gov_content_release\Request\RequestInterface $requestService * The build requester service. * @param \Symfony\Component\HttpFoundation\RequestStack $requestStack * The current request stack. */ - public function __construct(BuildRequesterInterface $buildRequester, RequestStack $requestStack) { - $this->buildRequester = $buildRequester; + public function __construct(RequestInterface $requestService, RequestStack $requestStack) { + $this->requestService = $requestService; $this->requestStack = $requestStack; } @@ -46,7 +46,7 @@ public function __construct(BuildRequesterInterface $buildRequester, RequestStac */ public static function create(ContainerInterface $container) { return new static( - $container->get('va_gov_build_trigger.build_requester'), + $container->get('va_gov_content_release.request'), $container->get('request_stack') ); } @@ -63,7 +63,7 @@ public function requestBuild() { throw new BadRequestHttpException('Must provide a reason for requesting a frontend build.'); } - $this->buildRequester->requestFrontendBuild($reason); + $this->requestService->submitRequest($reason); return new Response('Build requested.'); } diff --git a/docroot/modules/custom/va_gov_build_trigger/src/Controller/FrontEndBranchAutocompleteController.php b/docroot/modules/custom/va_gov_build_trigger/src/Controller/FrontEndBranchAutocompleteController.php deleted file mode 100644 index d909d2e1ba..0000000000 --- a/docroot/modules/custom/va_gov_build_trigger/src/Controller/FrontEndBranchAutocompleteController.php +++ /dev/null @@ -1,174 +0,0 @@ -cbGitHubClient = $cbGitHubClient; - $this->cbBranchSearch = $cbBranchSearch; - $this->logger = $logger->get('va_gov_build_trigger'); - } - - /** - * {@inheritdoc} - */ - public static function create(ContainerInterface $container) { - return new static( - $container->get('va_gov_git.branch_search.content_build'), - $container->get('va_gov_github.api_client.content_build'), - $container->get('logger.factory') - ); - } - - /** - * Handler for autocomplete request. - * - * @param \Symfony\Component\HttpFoundation\Request $request - * The current request. - * @param int $count - * Number of results to return. - * - * @return \Symfony\Component\HttpFoundation\Response - * The json response object. - */ - public function handleAutocomplete(Request $request, $count) : Response { - $results = []; - - if ($input = $request->query->get('q')) { - $string = mb_strtolower($input); - $results = $this->getMatchingRefs($string, $count); - } - - return JsonResponse::create($results); - } - - /** - * Get branch and PR git references matching the given search string. - * - * @param string $string - * Search string. - * @param int $count - * Number of references to return. - * - * @return string[] - * Array of labeled git references - */ - private function getMatchingRefs(string $string, int $count) : array { - // @todo parallelize with https://github.com/spatie/async? - $results = []; - - $individual_count = (int) ($count / 2); - - $branches = $this->searchFrontEndBranches($string); - for ($i = 0; $i < $individual_count; $i++) { - if (!empty($branches[$i])) { - $results[] = [ - 'label' => "BRANCH {$branches[$i]}", - 'value' => "BRANCH {$branches[$i]} ({$branches[$i]})", - ]; - } - } - - $frontEndPrs = $this->searchFrontEndPrs($string); - for ($i = 0; $i < $individual_count; $i++) { - if (!empty($frontEndPrs['items'][$i])) { - $item = $frontEndPrs['items'][$i]; - $results[] = [ - 'label' => "PR {$item['number']} ({$item['title']})", - 'value' => "PR {$item['number']} - {$item['title']} ({$item['number']})", - ]; - } - } - - return $results; - } - - /** - * Return front end branch names matching the given string. - * - * @param string $string - * Search string. - * - * @return string[] - * Array of branch names. - */ - private function searchFrontEndBranches(string $string) : array { - try { - return $this->cbBranchSearch->getRemoteBranchNamesContaining($string); - } - catch (\Throwable $exception) { - $this->logger->error('Error searching for branches: @message', [ - '@message' => $exception->getMessage(), - ]); - return []; - } - } - - /** - * Search Front End PRs. - * - * @param string $string - * Search string. - * @param int $count - * Number of PRs to return. - * - * @return string[] - * Array of PRs - */ - private function searchFrontEndPrs(string $string, int $count = 20) { - $results = []; - - try { - $results = $this->cbGitHubClient->searchPullRequests($string); - } - catch (\Exception $e) { - $variables = Error::decodeException($e); - $this->logger->error('%type: @message in %function (line %line of %file).', $variables); - } - - return $results; - } - -} diff --git a/docroot/modules/custom/va_gov_build_trigger/src/Environment/EnvironmentDiscovery.php b/docroot/modules/custom/va_gov_build_trigger/src/Environment/EnvironmentDiscovery.php index a4f5f65d25..55d099bec3 100644 --- a/docroot/modules/custom/va_gov_build_trigger/src/Environment/EnvironmentDiscovery.php +++ b/docroot/modules/custom/va_gov_build_trigger/src/Environment/EnvironmentDiscovery.php @@ -150,16 +150,6 @@ protected function isCli() : bool { return PHP_SAPI === 'cli'; } - /** - * Returns the Build Trigger Form class for the current environment. - * - * @return string - * Class name. - */ - public function getBuildTriggerFormClass() : string { - return $this->getEnvironment()->getBuildTriggerFormClass(); - } - /** * Determine whether or not build log and frontend version are displayed. * diff --git a/docroot/modules/custom/va_gov_build_trigger/src/Environment/EnvironmentInterface.php b/docroot/modules/custom/va_gov_build_trigger/src/Environment/EnvironmentInterface.php index d6c9959744..798e823978 100644 --- a/docroot/modules/custom/va_gov_build_trigger/src/Environment/EnvironmentInterface.php +++ b/docroot/modules/custom/va_gov_build_trigger/src/Environment/EnvironmentInterface.php @@ -32,14 +32,6 @@ public function triggerFrontendBuild() : void; */ public function contentEditsShouldTriggerFrontendBuild() : bool; - /** - * The Build Trigger Form Class. - * - * @return string - * The build trigger form class - */ - public function getBuildTriggerFormClass() : string; - /** * Determine whether or not build log and frontend version are displayed. * diff --git a/docroot/modules/custom/va_gov_build_trigger/src/EventSubscriber/ContentReleaseErrorSubscriber.php b/docroot/modules/custom/va_gov_build_trigger/src/EventSubscriber/ContentReleaseErrorSubscriber.php index dfb1a38d6c..54ebaa727f 100644 --- a/docroot/modules/custom/va_gov_build_trigger/src/EventSubscriber/ContentReleaseErrorSubscriber.php +++ b/docroot/modules/custom/va_gov_build_trigger/src/EventSubscriber/ContentReleaseErrorSubscriber.php @@ -5,8 +5,8 @@ use Drupal\Core\State\StateInterface; use Drupal\va_gov_build_trigger\Event\ReleaseStateTransitionEvent; use Drupal\va_gov_build_trigger\Plugin\MetricsCollector\ContentReleaseAttemptsSinceLastSuccess; -use Drupal\va_gov_build_trigger\Service\BuildRequesterInterface; use Drupal\va_gov_build_trigger\Service\ReleaseStateManager; +use Drupal\va_gov_content_release\Request\RequestInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** @@ -22,22 +22,22 @@ class ContentReleaseErrorSubscriber implements EventSubscriberInterface { protected $state; /** - * The build requester service. + * The content release request service. * - * @var \Drupal\va_gov_build_trigger\Service\BuildRequesterInterface + * @var \Drupal\va_gov_content_release\Request\RequestInterface */ - protected $buildRequester; + protected $requestService; /** * Constructor for ContentReleaseErrorSubscriber objects. * - * @param \Drupal\va_gov_build_trigger\Service\BuildRequesterInterface $buildRequester + * @param \Drupal\va_gov_content_release\Request\RequestInterface $requestService * The build requester service. * @param \Drupal\Core\State\StateInterface $state * The state service. */ - public function __construct(BuildRequesterInterface $buildRequester, StateInterface $state) { - $this->buildRequester = $buildRequester; + public function __construct(RequestInterface $requestService, StateInterface $state) { + $this->requestService = $requestService; $this->state = $state; } @@ -57,7 +57,7 @@ public static function getSubscribedEvents() { */ public function handleError(ReleaseStateTransitionEvent $event) { if ($event->getNewReleaseState() === ReleaseStateManager::STATE_ERROR) { - $this->buildRequester->requestFrontendBuild('Retrying build after build failure.'); + $this->requestService->submitRequest('Retrying build after build failure.'); } if ($event->getNewReleaseState() === ReleaseStateManager::STATE_DISPATCHED) { diff --git a/docroot/modules/custom/va_gov_build_trigger/src/EventSubscriber/ContinuousReleaseSubscriber.php b/docroot/modules/custom/va_gov_build_trigger/src/EventSubscriber/ContinuousReleaseSubscriber.php index 2717632310..4038d7aa60 100644 --- a/docroot/modules/custom/va_gov_build_trigger/src/EventSubscriber/ContinuousReleaseSubscriber.php +++ b/docroot/modules/custom/va_gov_build_trigger/src/EventSubscriber/ContinuousReleaseSubscriber.php @@ -6,9 +6,9 @@ use Drupal\Core\Datetime\DateFormatterInterface; use Drupal\Core\State\StateInterface; use Drupal\va_gov_build_trigger\Event\ReleaseStateTransitionEvent; -use Drupal\va_gov_build_trigger\Service\BuildRequesterInterface; use Drupal\va_gov_build_trigger\Service\ReleaseStateManager; use Drupal\va_gov_build_trigger\Traits\RunsDuringBusinessHours; +use Drupal\va_gov_content_release\Request\RequestInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** @@ -27,11 +27,11 @@ class ContinuousReleaseSubscriber implements EventSubscriberInterface { protected $state; /** - * The build requester service. + * The content release request service. * - * @var \Drupal\va_gov_build_trigger\Service\BuildRequesterInterface + * @var \Drupal\va_gov_content_release\Request\RequestInterface */ - protected $buildRequester; + protected $requestService; /** * Constructs a new ContentReleaseIntervalSubscriber object. @@ -40,15 +40,15 @@ class ContinuousReleaseSubscriber implements EventSubscriberInterface { * The state service. * @param \Drupal\Component\Datetime\TimeInterface $time * The time service. - * @param \Drupal\va_gov_build_trigger\Service\BuildRequesterInterface $buildRequester + * @param \Drupal\va_gov_content_release\Request\RequestInterface $requestService * The build requester service. * @param \Drupal\Core\Datetime\DateFormatterInterface $dateFormatter * The date formatter service. */ - public function __construct(StateInterface $state, TimeInterface $time, BuildRequesterInterface $buildRequester, DateFormatterInterface $dateFormatter) { + public function __construct(StateInterface $state, TimeInterface $time, RequestInterface $requestService, DateFormatterInterface $dateFormatter) { $this->state = $state; $this->time = $time; - $this->buildRequester = $buildRequester; + $this->requestService = $requestService; $this->dateFormatter = $dateFormatter; } @@ -72,7 +72,7 @@ public function releaseContinuously(ReleaseStateTransitionEvent $event) { if ($is_complete && $is_enabled) { $this->runDuringBusinessHours(function () { - $this->buildRequester->requestFrontendBuild('Continuous release'); + $this->requestService->submitRequest('Continuous release'); }); } } diff --git a/docroot/modules/custom/va_gov_build_trigger/src/Plugin/Block/ContentReleaseStatusBlock.php b/docroot/modules/custom/va_gov_build_trigger/src/Plugin/Block/ContentReleaseStatusBlock.php deleted file mode 100644 index 2986edc27b..0000000000 --- a/docroot/modules/custom/va_gov_build_trigger/src/Plugin/Block/ContentReleaseStatusBlock.php +++ /dev/null @@ -1,223 +0,0 @@ -get('state'), - $container->get('date.formatter'), - $container->get('va_gov.build_trigger.environment_discovery'), - ); - } - - /** - * Constructs a \Drupal\Component\Plugin\PluginBase object. - * - * @param array $configuration - * A configuration array containing information about the plugin instance. - * @param string $plugin_id - * The plugin_id for the plugin instance. - * @param mixed $plugin_definition - * The plugin implementation definition. - * @param \Drupal\Core\State\StateInterface $state - * The state service. - * @param \Drupal\Core\Datetime\DateFormatterInterface $dateFormatter - * The date formatter service. - * @param \Drupal\va_gov_build_trigger\Environment\EnvironmentDiscovery $environmentDiscovery - * The environment discovery service. - */ - public function __construct( - array $configuration, - $plugin_id, - $plugin_definition, - StateInterface $state, - DateFormatterInterface $dateFormatter, - EnvironmentDiscovery $environmentDiscovery - ) { - $this->configuration = $configuration; - $this->pluginId = $plugin_id; - $this->pluginDefinition = $plugin_definition; - $this->state = $state; - $this->dateFormatter = $dateFormatter; - $this->environmentDiscovery = $environmentDiscovery; - } - - /** - * {@inheritdoc} - */ - public function build() { - $build = []; - - $release_state = $this->state->get('va_gov_build_trigger.release_state', 'ready'); - $last_release = $this->state->get('va_gov_build_trigger.last_release_complete', 0); - - $items = []; - - // If the frontend has been built, display a link to the environment. - $front_end_link = $this->t('Front end has not been built yet.'); - $front_end_description = $this->t('Once a release is completed successfully, this section will update with a link to the newly built VA.gov front end.'); - if ($last_release !== 0) { - $target = $this->environmentDiscovery->getWebUrl(); - $target_url = Url::fromUri($target, ['attributes' => ['target' => '_blank']]); - $front_end_link = Link::fromTextAndUrl($this->t('View front end'), $target_url); - $front_end_description = $this->t('See how your content will appear to site visitors on the front end.'); - } - - $items['frontend_link'] = [ - 'title' => $this->t('Front end link'), - 'description' => $front_end_description, - 'value' => $front_end_link, - ]; - - $items['release_state'] = [ - 'title' => $this->t('Release state'), - 'value' => $this->getHumanReadableState($release_state), - ]; - - $items['last_release'] = [ - 'title' => $this->t('Last release'), - 'value' => $this->formatTimestamp($last_release), - ]; - - if ($this->environmentDiscovery->shouldDisplayBuildDetails()) { - $current_frontend_version = $this->state->get(BuildRequester::VA_GOV_FRONTEND_VERSION, '[default]'); - $build_log_link = - - $items['front_end_version'] = [ - 'title' => $this->t('Front end version'), - 'value' => $current_frontend_version, - ]; - - // If the frontend has been built, display a link to the environment. - $build_log_link = $this->t('No build log available'); - $build_log_description = $this->t('Once a release is completed successfully, this section will update with a link to the full log output of the content release (including a broken link report).'); - if ($last_release !== 0) { - $target = $this->environmentDiscovery->getWebUrl(); - $target_url = Url::fromUserInput('/sites/default/files/build.txt', ['attributes' => ['target' => '_blank']]); - $build_log_link = Link::fromTextAndUrl($this->t('Build log'), $target_url); - $build_log_description = $this->t('View the full output of the last completed build process (including a broken link report).'); - } - $items['build_log'] = [ - 'title' => $this->t('Build log'), - 'description' => $build_log_description, - 'value' => $build_log_link, - ]; - } - - $status = [ - '#theme' => 'status_report_grouped', - '#grouped_requirements' => [ - [ - 'title' => $this->t('Content release status'), - 'type' => 'content-release-status', - 'items' => $items, - ], - ], - ]; - - $build['#attached']['library'][] = 'va_gov_build_trigger/content_release_status_block'; - $build['#attached']['drupalSettings']['contentReleaseStatusBlock'] = [ - 'blockRefreshPath' => Url::fromRoute( - 'va_gov_build_trigger.content_release_status_block_controller_get_block' - )->toString(), - ]; - - $build['content_release_status_block'] = $status; - - return $build; - } - - /** - * Formats our internal state names for end-user consumption. - * - * @param string $state - * Internal content release state. - * - * @return string - * User-facing content release state. - */ - protected function getHumanReadableState(string $state) : string { - switch ($state) { - case 'ready': - case 'requested': - return $this->t('Ready'); - - case 'dispatched': - case 'starting': - return $this->t('Preparing'); - - case 'inprogress': - return $this->t('In Progress'); - - case 'complete': - return $this->t('Complete'); - } - - return 'unknown'; - } - - /** - * Format a timestamp using the site standard date format and timezone. - * - * @param int $timestamp - * A unix timestamp. - * - * @return string - * A formatted date/time. - */ - protected function formatTimestamp(int $timestamp) : string { - if ($timestamp === 0) { - return $this->t('Never'); - } - - return $this->dateFormatter->format($timestamp, 'standard'); - } - -} diff --git a/docroot/modules/custom/va_gov_build_trigger/src/Plugin/VAGov/Environment/BRD.php b/docroot/modules/custom/va_gov_build_trigger/src/Plugin/VAGov/Environment/BRD.php index 89ab1e4434..04d51f7fd1 100644 --- a/docroot/modules/custom/va_gov_build_trigger/src/Plugin/VAGov/Environment/BRD.php +++ b/docroot/modules/custom/va_gov_build_trigger/src/Plugin/VAGov/Environment/BRD.php @@ -6,7 +6,6 @@ use Drupal\Core\Site\Settings; use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\va_gov_build_trigger\Environment\EnvironmentPluginBase; -use Drupal\va_gov_build_trigger\Form\BrdBuildTriggerForm; use Drupal\va_gov_github\Api\Client\ApiClientInterface; use Psr\Log\LoggerInterface; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -108,13 +107,6 @@ public function contentEditsShouldTriggerFrontendBuild(): bool { return TRUE; } - /** - * {@inheritDoc} - */ - public function getBuildTriggerFormClass() : string { - return BrdBuildTriggerForm::class; - } - /** * Check for a pending content-release workflow run. */ diff --git a/docroot/modules/custom/va_gov_build_trigger/src/Plugin/VAGov/Environment/Local.php b/docroot/modules/custom/va_gov_build_trigger/src/Plugin/VAGov/Environment/Local.php index 8b90eeae04..8e532c9acb 100644 --- a/docroot/modules/custom/va_gov_build_trigger/src/Plugin/VAGov/Environment/Local.php +++ b/docroot/modules/custom/va_gov_build_trigger/src/Plugin/VAGov/Environment/Local.php @@ -3,7 +3,6 @@ namespace Drupal\va_gov_build_trigger\Plugin\VAGov\Environment; use Drupal\va_gov_build_trigger\Environment\EnvironmentPluginBase; -use Drupal\va_gov_build_trigger\Form\LocalBuildTriggerForm; /** * Local Plugin for Environment. @@ -15,13 +14,6 @@ */ class Local extends EnvironmentPluginBase { - /** - * {@inheritDoc} - */ - public function getBuildTriggerFormClass() : string { - return LocalBuildTriggerForm::class; - } - /** * {@inheritDoc} */ diff --git a/docroot/modules/custom/va_gov_build_trigger/src/Plugin/VAGov/Environment/Tugboat.php b/docroot/modules/custom/va_gov_build_trigger/src/Plugin/VAGov/Environment/Tugboat.php index d0d267e9c5..ef4a7af822 100644 --- a/docroot/modules/custom/va_gov_build_trigger/src/Plugin/VAGov/Environment/Tugboat.php +++ b/docroot/modules/custom/va_gov_build_trigger/src/Plugin/VAGov/Environment/Tugboat.php @@ -3,7 +3,6 @@ namespace Drupal\va_gov_build_trigger\Plugin\VAGov\Environment; use Drupal\va_gov_build_trigger\Environment\EnvironmentPluginBase; -use Drupal\va_gov_build_trigger\Form\TugboatBuildTriggerForm; /** * Tugboat Plugin for Environment. @@ -15,13 +14,6 @@ */ class Tugboat extends EnvironmentPluginBase { - /** - * {@inheritDoc} - */ - public function getBuildTriggerFormClass() : string { - return TugboatBuildTriggerForm::class; - } - /** * {@inheritDoc} */ diff --git a/docroot/modules/custom/va_gov_build_trigger/src/Service/BuildRequester.php b/docroot/modules/custom/va_gov_build_trigger/src/Service/BuildRequester.php deleted file mode 100644 index 371b4bd967..0000000000 --- a/docroot/modules/custom/va_gov_build_trigger/src/Service/BuildRequester.php +++ /dev/null @@ -1,67 +0,0 @@ -state = $state; - $this->buildQueue = $entityTypeManager - ->getStorage('advancedqueue_queue') - ->load('content_release'); - } - - /** - * {@inheritDoc} - */ - public function requestFrontendBuild(string $reason) : void { - $job = Job::create('va_gov_content_release_request', ['reason' => $reason]); - $this->buildQueue->enqueueJob($job); - } - - /** - * {@inheritDoc} - */ - public function switchFrontendVersion(string $commitish) : void { - $this->state->set(self::VA_GOV_FRONTEND_VERSION, $commitish); - } - - /** - * {@inheritDoc} - */ - public function resetFrontendVersion() : void { - $this->state->delete(self::VA_GOV_FRONTEND_VERSION); - } - -} diff --git a/docroot/modules/custom/va_gov_build_trigger/src/Service/BuildRequesterInterface.php b/docroot/modules/custom/va_gov_build_trigger/src/Service/BuildRequesterInterface.php deleted file mode 100644 index dfe1177122..0000000000 --- a/docroot/modules/custom/va_gov_build_trigger/src/Service/BuildRequesterInterface.php +++ /dev/null @@ -1,31 +0,0 @@ -buildRequester = $buildRequester; + public function __construct(RequestInterface $requestService, StateInterface $state, TimeInterface $time, DateFormatterInterface $dateFormatter) { + $this->requestService = $requestService; $this->state = $state; $this->time = $time; $this->dateFormatter = $dateFormatter; @@ -59,10 +60,10 @@ public function checkScheduledBuild() : void { $this->runDuringBusinessHours(function () use ($currentTime, $time_since_last_build) { if ($time_since_last_build >= 3600) { - $this->buildRequester->requestFrontendBuild('Scheduled hourly build'); + $this->requestService->submitRequest('Scheduled hourly build'); $this->state->set(self::VA_GOV_LAST_SCHEDULED_BUILD_REQUEST, $currentTime); } - }, $this->buildRequester, $this->state, $time_since_last_build); + }, $this->requestService, $this->state, $time_since_last_build); } } diff --git a/docroot/modules/custom/va_gov_build_trigger/src/Service/ReleaseStateManager.php b/docroot/modules/custom/va_gov_build_trigger/src/Service/ReleaseStateManager.php index 4b08dc7b6c..570df6756f 100644 --- a/docroot/modules/custom/va_gov_build_trigger/src/Service/ReleaseStateManager.php +++ b/docroot/modules/custom/va_gov_build_trigger/src/Service/ReleaseStateManager.php @@ -326,4 +326,11 @@ protected function updateReleaseState($new_state) : void { } } + /** + * {@inheritDoc} + */ + public function getLastReleaseCompleteTimestamp() : int { + return $this->state->get(self::LAST_RELEASE_COMPLETE_KEY, 0); + } + } diff --git a/docroot/modules/custom/va_gov_build_trigger/src/Service/ReleaseStateManagerInterface.php b/docroot/modules/custom/va_gov_build_trigger/src/Service/ReleaseStateManagerInterface.php index 31ab535744..6bcd2cba00 100644 --- a/docroot/modules/custom/va_gov_build_trigger/src/Service/ReleaseStateManagerInterface.php +++ b/docroot/modules/custom/va_gov_build_trigger/src/Service/ReleaseStateManagerInterface.php @@ -77,6 +77,14 @@ public function recordStatusNotification() : void; */ public function releaseStateIsStale() : bool; + /** + * Get the last-release-complete timestamp. + * + * @return int + * The last-release-complete timestamp. + */ + public function getLastReleaseCompleteTimestamp() : int; + /** * Handle an error condition. */ diff --git a/docroot/modules/custom/va_gov_build_trigger/va_gov_build_trigger.libraries.yml b/docroot/modules/custom/va_gov_build_trigger/va_gov_build_trigger.libraries.yml deleted file mode 100644 index faf84191d1..0000000000 --- a/docroot/modules/custom/va_gov_build_trigger/va_gov_build_trigger.libraries.yml +++ /dev/null @@ -1,14 +0,0 @@ -build_trigger_form: - version: 1.x - css: - theme: - css/build_trigger_form.css: {} - -content_release_status_block: - version: 1.x - js: - js/content_release_status_block.js: {} - dependencies: - - core/jquery - - core/once - - core/drupalSettings diff --git a/docroot/modules/custom/va_gov_build_trigger/va_gov_build_trigger.routing.yml b/docroot/modules/custom/va_gov_build_trigger/va_gov_build_trigger.routing.yml index 015ff3c77a..d3344d0c84 100644 --- a/docroot/modules/custom/va_gov_build_trigger/va_gov_build_trigger.routing.yml +++ b/docroot/modules/custom/va_gov_build_trigger/va_gov_build_trigger.routing.yml @@ -1,18 +1,3 @@ -va_gov_build_trigger.front_end_branches_autocomplete: - path: '/admin/content/deploy/front_end_branches_autocomplete/{count}' - defaults: - _controller: '\Drupal\va_gov_build_trigger\Controller\FrontEndBranchAutocompleteController::handleAutocomplete' - _format: json - requirements: - _permission: "va gov deploy content build" - -va_gov_build_trigger.content_release_status_block_controller_get_block: - path: '/admin/content_release_status_block/ajax' - defaults: - _controller: '\Drupal\va_gov_build_trigger\Controller\ContentReleaseStatusBlockController::getBlock' - requirements: - _permission: "va gov deploy content build" - route_callbacks: - '\Drupal\va_gov_build_trigger\RouteProvider::buildRequestRoutes' - '\Drupal\va_gov_build_trigger\RouteProvider::notificationRoutes' diff --git a/docroot/modules/custom/va_gov_build_trigger/va_gov_build_trigger.services.yml b/docroot/modules/custom/va_gov_build_trigger/va_gov_build_trigger.services.yml index 1ceb30c221..d6f9a1fb95 100644 --- a/docroot/modules/custom/va_gov_build_trigger/va_gov_build_trigger.services.yml +++ b/docroot/modules/custom/va_gov_build_trigger/va_gov_build_trigger.services.yml @@ -10,7 +10,7 @@ services: parent: default_plugin_manager va_gov_build_trigger.content_release_error_subscriber: class: Drupal\va_gov_build_trigger\EventSubscriber\ContentReleaseErrorSubscriber - arguments: ['@va_gov_build_trigger.build_requester', '@state'] + arguments: ['@va_gov_content_release.request', '@state'] tags: - { name: event_subscriber } va_gov_build_trigger.content_release_interval_subscriber: @@ -25,7 +25,7 @@ services: - { name: event_subscriber } va_gov_build_trigger.continuous_release_subscriber: class: Drupal\va_gov_build_trigger\EventSubscriber\ContinuousReleaseSubscriber - arguments: ['@state', '@datetime.time', '@va_gov_build_trigger.build_requester', '@date.formatter'] + arguments: ['@state', '@datetime.time', '@va_gov_content_release.request', '@date.formatter'] tags: - { name: event_subscriber } va_gov_build_trigger.release_state_manager: @@ -34,9 +34,6 @@ services: va_gov.site_status: class: Drupal\va_gov_build_trigger\SiteStatus\SiteStatus arguments: ['@state'] - va_gov_build_trigger.build_requester: - class: Drupal\va_gov_build_trigger\Service\BuildRequester - arguments: ['@entity_type.manager', '@state'] va_gov_build_trigger.build_scheduler: class: Drupal\va_gov_build_trigger\Service\BuildScheduler - arguments: ['@va_gov_build_trigger.build_requester', '@state', '@datetime.time', '@date.formatter'] + arguments: ['@va_gov_content_release.request', '@state', '@datetime.time', '@date.formatter'] diff --git a/docroot/modules/custom/va_gov_content_release/drush.services.yml b/docroot/modules/custom/va_gov_content_release/drush.services.yml index 6d076f6423..d15d38a00b 100644 --- a/docroot/modules/custom/va_gov_content_release/drush.services.yml +++ b/docroot/modules/custom/va_gov_content_release/drush.services.yml @@ -5,3 +5,10 @@ services: - '@va_gov_content_release.frontend_version' tags: - { name: drush.command } + + va_gov_content_release.request_commands: + class: \Drupal\va_gov_content_release\Commands\RequestCommands + arguments: + - '@va_gov_content_release.request' + tags: + - { name: drush.command } diff --git a/docroot/modules/custom/va_gov_content_release/src/Commands/FrontendVersionCommands.php b/docroot/modules/custom/va_gov_content_release/src/Commands/FrontendVersionCommands.php index 810bed4eca..d8b972b11e 100644 --- a/docroot/modules/custom/va_gov_content_release/src/Commands/FrontendVersionCommands.php +++ b/docroot/modules/custom/va_gov_content_release/src/Commands/FrontendVersionCommands.php @@ -2,6 +2,7 @@ namespace Drupal\va_gov_content_release\Commands; +use Drupal\va_gov_content_release\Frontend\Frontend; use Drupal\va_gov_content_release\FrontendVersion\FrontendVersionInterface; use Drush\Commands\DrushCommands; @@ -29,36 +30,69 @@ public function __construct( $this->frontendVersion = $frontendVersion; } + /** + * Get the frontend. + * + * @param string $frontend + * The frontend whose version we are getting. + * + * @return \Drupal\va_gov_content_release\Frontend\Frontend + * The frontend. + */ + public function getFrontend(string $frontend) { + try { + return Frontend::from($frontend); + } + catch (\Throwable $exception) { + $this->io()->error($exception->getMessage()); + exit(1); + } + } + /** * Get the frontend version. * + * @param string $frontend + * The frontend whose version we are getting. + * * @command va-gov-content-release:frontend-version:get * @aliases va-gov-content-release-frontend-version-get */ - public function get() { - $value = $this->frontendVersion->get(); + public function getVersion(string $frontend = 'content_build') { + $frontend = $this->getFrontend($frontend); + $value = $this->frontendVersion->getVersion($frontend); $this->io()->write($value); } /** * Reset the frontend version. * + * @param string $frontend + * The frontend whose version we are resetting. + * * @command va-gov-content-release:frontend-version:reset * @aliases va-gov-content-release-frontend-version-reset */ - public function reset() { - $this->frontendVersion->reset(); + public function resetVersion(string $frontend = 'content_build') { + $frontend = $this->getFrontend($frontend); + $this->frontendVersion->resetVersion($frontend); $this->io()->success('Frontend version reset.'); } /** * Set the frontend version. * + * @param string $frontend + * The frontend whose version we are getting. + * @param string $version + * The version to set. + * * @command va-gov-content-release:frontend-version:set * @aliases va-gov-content-release-frontend-version-set */ - public function set($version) { - $this->frontendVersion->set($version); + public function setVersion(string $frontend = 'content_build', $version = '_default') { + $frontend = $this->getFrontend($frontend); + $this->frontendVersion->setVersion($frontend, $version); $this->io()->success('Frontend version set to ' . $version); } diff --git a/docroot/modules/custom/va_gov_content_release/src/Commands/RequestCommands.php b/docroot/modules/custom/va_gov_content_release/src/Commands/RequestCommands.php new file mode 100644 index 0000000000..865d6d0312 --- /dev/null +++ b/docroot/modules/custom/va_gov_content_release/src/Commands/RequestCommands.php @@ -0,0 +1,47 @@ +requestService = $requestService; + } + + /** + * Submit a content release request. + * + * @param string $reason + * The reason for the request. + * + * @command va-gov-content-release:request:submit + * @aliases va-gov-content-release-request-submit + * va-gov-content-release-request-submit + */ + public function submitRequest(string $reason = 'Build requested via Drush.') { + $this->requestService->submitRequest($reason); + $this->io()->success('Content Release requested; check the queue for status.'); + } + +} diff --git a/docroot/modules/custom/va_gov_content_release/src/Controller/FrontendVersionAutocompleteController.php b/docroot/modules/custom/va_gov_content_release/src/Controller/FrontendVersionAutocompleteController.php new file mode 100644 index 0000000000..dee748c71c --- /dev/null +++ b/docroot/modules/custom/va_gov_content_release/src/Controller/FrontendVersionAutocompleteController.php @@ -0,0 +1,80 @@ +frontendVersionSearch = $frontendVersionSearch; + $this->logger = $logger->get('va_gov_content_release'); + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('va_gov_content_release.frontend_version_search'), + $container->get('logger.factory') + ); + } + + /** + * Handler for autocomplete request. + * + * @param \Symfony\Component\HttpFoundation\Request $request + * The current request. + * @param string $frontend + * The frontend type. + * @param int $count + * Number of results to return. + * + * @return \Symfony\Component\HttpFoundation\Response + * The json response object. + */ + public function handleAutocomplete(Request $request, string $frontend, int $count) : Response { + $results = []; + try { + $frontend = Frontend::from($frontend); + } + catch (\InvalidArgumentException $e) { + return JsonResponse::create(['error' => 'Invalid frontend type provided.']); + } + $input = $request->query->get('q') ?? 'main'; + $query = mb_strtolower($input); + $results = $this->frontendVersionSearch->getMatchingReferences($frontend, $query, $count); + return JsonResponse::create($results); + } + +} diff --git a/docroot/modules/custom/va_gov_build_trigger/src/Controller/ContentReleaseStatusBlockController.php b/docroot/modules/custom/va_gov_content_release/src/Controller/StatusBlockController.php similarity index 90% rename from docroot/modules/custom/va_gov_build_trigger/src/Controller/ContentReleaseStatusBlockController.php rename to docroot/modules/custom/va_gov_content_release/src/Controller/StatusBlockController.php index c3858b590f..bd36781c43 100644 --- a/docroot/modules/custom/va_gov_build_trigger/src/Controller/ContentReleaseStatusBlockController.php +++ b/docroot/modules/custom/va_gov_content_release/src/Controller/StatusBlockController.php @@ -1,6 +1,6 @@ '', ]; - $form['build_request']['selection'] = [ - '#title' => $this->t('Which version of the VA.gov front end would you like to use?'), + $form['build_request']['content_build_selection'] = [ + '#title' => $this->t('Which version of content-build would you like to use?'), + '#type' => 'radios', + '#options' => [ + 'default' => $this->t('Use default - the content-build version from the time this demo environment was created.'), + 'choose' => $this->t('Select a different content-build branch/pull request - for example, to see your content in a newer frontend design.'), + ], + '#default_value' => 'default', + ]; + + $form['build_request']['content_build_git_ref'] = [ + '#type' => 'textfield', + '#title' => $this->t('Select branch/pull request'), + '#description' => $this->t('Start typing to select a branch for the content-build version you want to use.'), + '#autocomplete_route_name' => 'va_gov_content_release.frontend_version_autocomplete', + '#autocomplete_route_parameters' => [ + 'frontend' => 'content_build', + 'count' => 10, + ], + '#size' => 72, + '#maxlength' => 1024, + '#hidden' => TRUE, + '#states' => [ + 'visible' => [':input[name="content_build_selection"]' => ['value' => 'choose']], + ], + ]; + + $form['build_request']['vets_website_selection'] = [ + '#title' => $this->t('Which version of vets-website would you like to use?'), '#type' => 'radios', '#options' => [ - 'default' => $this->t('Use default - the frontend version from the time this demo environment was created.'), - 'choose' => $this->t('Select a different frontend branch/pull request - for example, to see your content in a newer frontend design.'), + 'default' => $this->t('Use default - the vets-website version from the time this demo environment was created.'), + 'choose' => $this->t('Select a different vets-website branch/pull request - for example, to see your content in a newer frontend design.'), ], '#default_value' => 'default', ]; - $form['build_request']['git_ref'] = [ + $form['build_request']['vets_website_git_ref'] = [ '#type' => 'textfield', '#title' => $this->t('Select branch/pull request'), - '#description' => $this->t('Start typing to select a branch for the frontend version you want to use.'), - '#autocomplete_route_name' => 'va_gov_build_trigger.front_end_branches_autocomplete', + '#description' => $this->t('Start typing to select a branch for the vets-website version you want to use.'), + '#autocomplete_route_name' => 'va_gov_content_release.frontend_version_autocomplete', '#autocomplete_route_parameters' => [ + 'frontend' => 'vets_website', 'count' => 10, ], '#size' => 72, '#maxlength' => 1024, '#hidden' => TRUE, '#states' => [ - 'visible' => [':input[name="selection"]' => ['value' => 'choose']], + 'visible' => [':input[name="vets_website_selection"]' => ['value' => 'choose']], ], ]; @@ -152,70 +182,108 @@ protected function getContentReleaseStatusBlock() { * Object containing current form state. */ public function submitForm(array &$form, FormStateInterface $form_state) { - if ($form_state->getValue('selection') === 'default') { - $this->resetFrontendVersion($form_state); + $this->submitFormForFrontend(Frontend::ContentBuild, $form_state); + $this->submitFormForFrontend(Frontend::VetsWebsite, $form_state); + parent::submitForm($form, $form_state); + } + + /** + * Submit the form. + * + * @param \Drupal\va_gov_content_release\Frontend\FrontendInterface $frontend + * The frontend whose version we are managing. + * @param \Drupal\Core\Form\FormStateInterface $form_state + * Object containing current form state. + */ + protected function submitFormForFrontend(FrontendInterface $frontend, FormStateInterface $form_state) { + $selectionName = $frontend->getRawValue() . '_selection'; + if ($form_state->getValue($selectionName) === 'default') { + $this->resetFrontendVersion($frontend, $form_state); } else { - $this->setFrontendVersion($form_state); + $this->setFrontendVersion($frontend, $form_state); } - - parent::submitForm($form, $form_state); } /** * {@inheritdoc} */ public function validateForm(array &$form, FormStateInterface $form_state) { - if ($form_state->getValue('selection') === 'default') { - return; - } - if (empty($this->getGitRef($form_state))) { - $form_state->setErrorByName('git_ref', $this->t('Invalid selection.')); + $this->validateFormForFrontend(Frontend::ContentBuild, $form_state); + $this->validateFormForFrontend(Frontend::VetsWebsite, $form_state); + } + + /** + * Validate the form. + * + * @param \Drupal\va_gov_content_release\Frontend\FrontendInterface $frontend + * The frontend whose version we are managing. + * @param \Drupal\Core\Form\FormStateInterface $form_state + * Object containing current form state. + */ + protected function validateFormForFrontend(FrontendInterface $frontend, FormStateInterface $form_state) { + $selectionName = $frontend->getRawValue() . '_selection'; + $gitRefName = $frontend->getRawValue() . '_git_ref'; + if ($form_state->getValue($selectionName) !== 'default') { + if (empty($this->getGitRef($frontend, $form_state))) { + $form_state->setErrorByName($gitRefName, $this->t('Invalid selection.')); + } } } /** * Reset the frontend version. * + * @param \Drupal\va_gov_content_release\Frontend\FrontendInterface $frontend + * The frontend whose version we are resetting. * @param \Drupal\Core\Form\FormStateInterface $form_state * Object containing current form state. */ - public function resetFrontendVersion(FormStateInterface $form_state) { + public function resetFrontendVersion(FrontendInterface $frontend, FormStateInterface $form_state) { if (!$this->isUnderTest($form_state)) { - $this->frontendVersion->reset(); + $this->frontendVersion->resetVersion($frontend); } else { - $this->reporter->reportInfo($this->t('Reset frontend version skipped; form is under test.')); + $this->reporter->reportInfo($this->t('Reset :frontend version skipped; form is under test.', [ + ':frontend' => $frontend->getRawValue(), + ])); } } /** * Set the frontend version according to the form. * + * @param \Drupal\va_gov_content_release\Frontend\FrontendInterface $frontend + * The frontend whose version we are setting. * @param \Drupal\Core\Form\FormStateInterface $form_state * Object containing current form state. */ - public function setFrontendVersion(FormStateInterface $form_state) { + public function setFrontendVersion(FrontendInterface $frontend, FormStateInterface $form_state) { if (!$this->isUnderTest($form_state)) { - $this->frontendVersion->set($this->getGitRef($form_state)); + $this->frontendVersion->setVersion($frontend, $this->getGitRef($frontend, $form_state)); } else { - $this->reporter->reportInfo($this->t('Set frontend version skipped; form is under test.')); + $this->reporter->reportInfo($this->t('Set :frontend version skipped; form is under test.', [ + ':frontend' => $frontend->getRawValue(), + ])); } } /** * Parse a git ref out of the `git_ref` field value. * + * @param \Drupal\va_gov_content_release\Frontend\FrontendInterface $frontend + * The frontend whose version we are setting. * @param \Drupal\Core\Form\FormStateInterface $form_state * Object containing current form state. * * @return string * A standalone git ref, or an empty string. */ - public function getGitRef(FormStateInterface $form_state) : string { + public function getGitRef(FrontendInterface $frontend, FormStateInterface $form_state) : string { // If they selected a specific git ref, use that. - $formValue = $form_state->getValue('git_ref'); + $gitRefName = $frontend->getRawValue() . '_git_ref'; + $formValue = $form_state->getValue($gitRefName); $result = ''; if (preg_match("/.+\\s\\(([^\\)]+)\\)/", $formValue, $matches)) { $result = $matches[1]; diff --git a/docroot/modules/custom/va_gov_content_release/src/Frontend/Frontend.php b/docroot/modules/custom/va_gov_content_release/src/Frontend/Frontend.php new file mode 100644 index 0000000000..ce935f8188 --- /dev/null +++ b/docroot/modules/custom/va_gov_content_release/src/Frontend/Frontend.php @@ -0,0 +1,55 @@ +value; + } + + /** + * {@inheritDoc} + */ + public function isContentBuild() : bool { + return match ($this) { + self::ContentBuild => TRUE, + default => FALSE, + }; + } + + /** + * {@inheritDoc} + */ + public function isVetsWebsite() : bool { + return match ($this) { + self::VetsWebsite => TRUE, + default => FALSE, + }; + } + + /** + * {@inheritDoc} + */ + public function isNextBuild() : bool { + return match ($this) { + self::NextBuild => TRUE, + default => FALSE, + }; + } + +} diff --git a/docroot/modules/custom/va_gov_content_release/src/Frontend/FrontendInterface.php b/docroot/modules/custom/va_gov_content_release/src/Frontend/FrontendInterface.php new file mode 100644 index 0000000000..bc6a70e31f --- /dev/null +++ b/docroot/modules/custom/va_gov_content_release/src/Frontend/FrontendInterface.php @@ -0,0 +1,42 @@ +settings = $settings; + } + + /** + * Get the base URL for the frontend. + * + * @return string + * The base URL for the frontend. + */ + public function getBaseUrl() : string { + return $this->settings->get('va_gov_frontend_url') ?? 'https://www.va.gov'; + } + +} diff --git a/docroot/modules/custom/va_gov_content_release/src/FrontendUrl/FrontendUrlInterface.php b/docroot/modules/custom/va_gov_content_release/src/FrontendUrl/FrontendUrlInterface.php new file mode 100644 index 0000000000..fbb336a6be --- /dev/null +++ b/docroot/modules/custom/va_gov_content_release/src/FrontendUrl/FrontendUrlInterface.php @@ -0,0 +1,20 @@ +state->get(FrontendVersionInterface::FRONTEND_VERSION, FrontendVersionInterface::FRONTEND_VERSION_DEFAULT); + protected function getKey(FrontendInterface $frontend) : string { + return FrontendVersionInterface::FRONTEND_VERSION_PREFIX . $frontend->getRawValue(); } /** - * Set the current version of the frontend. - * - * @param string $version - * The version to set. + * {@inheritDoc} + */ + public function getVersion(FrontendInterface $frontend) : string { + $key = $this->getKey($frontend); + return $this->state->get($key, FrontendVersionInterface::FRONTEND_VERSION_DEFAULT); + } + + /** + * {@inheritDoc} */ - public function set(string $version) : void { - $this->state->set(FrontendVersionInterface::FRONTEND_VERSION, $version); + public function setVersion(FrontendInterface $frontend, string $version) : void { + $key = $this->getKey($frontend); + $this->state->set($key, $version); } /** - * Reset the current version of the frontend. + * {@inheritDoc} */ - public function reset() : void { - $this->state->delete(FrontendVersionInterface::FRONTEND_VERSION); + public function resetVersion(FrontendInterface $frontend) : void { + $key = $this->getKey($frontend); + $this->state->delete($key); } } diff --git a/docroot/modules/custom/va_gov_content_release/src/FrontendVersion/FrontendVersionInterface.php b/docroot/modules/custom/va_gov_content_release/src/FrontendVersion/FrontendVersionInterface.php index 1e8e014e9a..32867c4149 100644 --- a/docroot/modules/custom/va_gov_content_release/src/FrontendVersion/FrontendVersionInterface.php +++ b/docroot/modules/custom/va_gov_content_release/src/FrontendVersion/FrontendVersionInterface.php @@ -2,6 +2,8 @@ namespace Drupal\va_gov_content_release\FrontendVersion; +use Drupal\va_gov_content_release\Frontend\FrontendInterface; + /** * An interface for the FrontendVersion service. * @@ -10,28 +12,36 @@ */ interface FrontendVersionInterface { - const FRONTEND_VERSION = 'va_gov_content_release.frontend_version'; + const FRONTEND_VERSION_PREFIX = 'va_gov_content_release.frontend_version.'; const FRONTEND_VERSION_DEFAULT = '__default'; /** * Get the current version of the frontend. * + * @param \Drupal\va_gov_content_release\Frontend\FrontendInterface $frontend + * The frontend whose version we are requesting. + * * @return string * The current version of the frontend. */ - public function get() : string; + public function getVersion(FrontendInterface $frontend) : string; /** * Set the current version of the frontend. * + * @param \Drupal\va_gov_content_release\Frontend\FrontendInterface $frontend + * The frontend whose version we are setting. * @param string $version * The version to set. */ - public function set(string $version) : void; + public function setVersion(FrontendInterface $frontend, string $version) : void; /** * Reset the current version of the frontend. + * + * @param \Drupal\va_gov_content_release\Frontend\FrontendInterface $frontend + * The frontend whose version we are resetting. */ - public function reset() : void; + public function resetVersion(FrontendInterface $frontend) : void; } diff --git a/docroot/modules/custom/va_gov_content_release/src/FrontendVersionSearch/FrontendVersionSearch.php b/docroot/modules/custom/va_gov_content_release/src/FrontendVersionSearch/FrontendVersionSearch.php new file mode 100644 index 0000000000..d2d6145d39 --- /dev/null +++ b/docroot/modules/custom/va_gov_content_release/src/FrontendVersionSearch/FrontendVersionSearch.php @@ -0,0 +1,187 @@ +cbBranchSearch = $cbBranchSearch; + $this->cbApiClient = $cbApiClient; + $this->vwBranchSearch = $vwBranchSearch; + $this->vwApiClient = $vwApiClient; + $this->logger = $loggerFactory->get('va_gov_content_release'); + } + + /** + * Get the branch search service for the given frontend. + * + * @param \Drupal\va_gov_content_release\Frontend\FrontendInterface $frontend + * The frontend. + * + * @return \Drupal\va_gov_git\BranchSearch\BranchSearchInterface + * The branch search service. + */ + protected function getBranchSearch(FrontendInterface $frontend) : BranchSearchInterface { + switch (TRUE) { + case $frontend->isContentBuild(): + return $this->cbBranchSearch; + + case $frontend->isVetsWebsite(): + return $this->vwBranchSearch; + + default: + throw new \InvalidArgumentException('Invalid frontend: ' . $frontend->getRawValue()); + } + } + + /** + * Get the API client for the given frontend. + * + * @param \Drupal\va_gov_content_release\Frontend\FrontendInterface $frontend + * The frontend. + * + * @return \Drupal\va_gov_github\Api\Client\ApiClientInterface + * The API client. + */ + protected function getApiClient(FrontendInterface $frontend) : ApiClientInterface { + switch (TRUE) { + case $frontend->isContentBuild(): + return $this->cbApiClient; + + case $frontend->isVetsWebsite(): + return $this->vwApiClient; + + default: + throw new \InvalidArgumentException('Invalid frontend: ' . $frontend->getRawValue()); + } + } + + /** + * {@inheritDoc} + */ + public function getMatchingReferences(FrontendInterface $frontend, string $query, int $count) : array { + $results = []; + $branches = $this->getMatchingBranches($frontend, $query); + for ($i = 0; $i < $count; $i++) { + if (!empty($branches[$i])) { + $results[] = [ + 'label' => "BRANCH {$branches[$i]}", + 'value' => "BRANCH {$branches[$i]} ({$branches[$i]})", + ]; + } + } + + $pullRequests = $this->getMatchingPullRequests($frontend, $query); + for ($i = 0; $i < $count; $i++) { + if (!empty($pullRequests['items'][$i])) { + $item = $pullRequests['items'][$i]; + $results[] = [ + 'label' => "PR {$item['number']} ({$item['title']})", + 'value' => "PR {$item['number']} - {$item['title']} ({$item['number']})", + ]; + } + } + + return $results; + } + + /** + * {@inheritDoc} + */ + public function getMatchingBranches(FrontendInterface $frontend, string $query) : array { + try { + return $this->getBranchSearch($frontend)->getRemoteBranchNamesContaining($query); + } + catch (\Throwable $exception) { + $this->logger->error('Error searching for branches: @message', [ + '@message' => $exception->getMessage(), + ]); + return []; + } + } + + /** + * {@inheritDoc} + */ + public function getMatchingPullRequests(FrontendInterface $frontend, string $query) : array { + $results = []; + + try { + $results = $this->getApiClient($frontend)->searchPullRequests($query); + } + catch (\Throwable $exception) { + $this->logger->error('Error searching for pull requests: @message', [ + '@message' => $exception->getMessage(), + ]); + } + + return $results; + } + +} diff --git a/docroot/modules/custom/va_gov_content_release/src/FrontendVersionSearch/FrontendVersionSearchInterface.php b/docroot/modules/custom/va_gov_content_release/src/FrontendVersionSearch/FrontendVersionSearchInterface.php new file mode 100644 index 0000000000..6e9861d673 --- /dev/null +++ b/docroot/modules/custom/va_gov_content_release/src/FrontendVersionSearch/FrontendVersionSearchInterface.php @@ -0,0 +1,56 @@ +configuration = $configuration; + $this->pluginId = $plugin_id; + $this->pluginDefinition = $plugin_definition; + $this->status = $status; + $this->frontendUrl = $frontendUrl; + $this->backendBaseUrl = $requestStack->getCurrentRequest()->getSchemeAndHttpHost(); + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $container->get('va_gov_content_release.status'), + $container->get('va_gov_content_release.frontend_url'), + $container->get('request_stack') + ); + } + + /** + * {@inheritdoc} + */ + public function build() { + $build = $this->buildStatusBlock(); + $this->attachStatusBlockLibrary($build); + return $build; + } + + /** + * Build the status block. + * + * @return array + * The status block. + */ + public function buildStatusBlock(): array { + $build = []; + $build['content_release_status_block'] = [ + '#theme' => 'status_report_grouped', + '#grouped_requirements' => [ + [ + 'title' => $this->t('Content release status'), + 'type' => 'content-release-status', + 'items' => $this->getItems(), + ], + ], + ]; + return $build; + } + + /** + * Get the status items. + * + * @return array + * The status items. + */ + public function getItems(): array { + $items = []; + $items['frontend_link'] = $this->buildFrontendLinkItem(); + $items['release_state'] = $this->getReleaseStateItem(); + $items['last_release'] = $this->getLastReleaseItem(); + $items['content_build_version'] = $this->getContentBuildVersionItem(); + if ($this->status->hasAdditionalBuildDetails()) { + $items = array_merge($items, $this->getAdditionalBuildDetailsItems()); + } + return $items; + } + + /** + * Build and insert the frontend link. + * + * @return array + * The frontend link item. + */ + public function buildFrontendLinkItem(): array { + if (!$this->hasEverCompletedRelease()) { + return $this->getDefaultFrontendLinkItem(); + } + $targetUrl = $this->frontendUrl->getBaseUrl(); + $targetUrl = Url::fromUri($targetUrl, ['attributes' => ['target' => '_blank']]); + return [ + 'title' => $this->t('Front end link'), + 'description' => $this->t('See how your content will appear to site visitors on the front end.'), + 'value' => Link::fromTextAndUrl($this->t('View front end'), $targetUrl), + ]; + } + + /** + * Has a release completed? Like, ever? + * + * @return bool + * TRUE if a release has ever completed, FALSE otherwise. + */ + public function hasEverCompletedRelease() : bool { + return $this->status->getLastReleaseCompleteTimestamp() !== 0; + } + + /** + * Get the default frontend link item. + * + * This is used if we've never completed a frontend build and the frontend + * is not available. + * + * @return array + * The default frontend link item. + */ + public function getDefaultFrontendLinkItem() : array { + return [ + 'title' => $this->t('Front end link'), + 'description' => $this->t('Once a release is completed successfully, this section will update with a link to the newly built VA.gov front end.'), + 'value' => $this->t('Front end has not been built yet.'), + ]; + } + + /** + * Get the release state item. + * + * @return array + * The release state item. + */ + public function getReleaseStateItem(): array { + return [ + 'title' => $this->t('Release state'), + 'value' => $this->status->getHumanReadableCurrentReleaseState(), + ]; + } + + /** + * Get the last release item. + * + * @return array + * The last release item. + */ + public function getLastReleaseItem(): array { + return [ + 'title' => $this->t('Last release'), + 'value' => $this->status->getLastReleaseCompleteDate(), + ]; + } + + /** + * Get additional build details items. + * + * @return array + * The additional build details items. + */ + public function getAdditionalBuildDetailsItems(): array { + $items = []; + $items['content_build_version'] = $this->getContentBuildVersionItem(); + $items['vets_website_version'] = $this->getVetsWebsiteVersionItem(); + $items['build_log'] = $this->getBuildLogItem(); + return $items; + } + + /** + * Get the content build version item. + * + * @return array + * The content build version item. + */ + public function getContentBuildVersionItem(): array { + return [ + 'title' => $this->t('content-build version'), + 'value' => $this->status->getContentBuildVersion(), + ]; + } + + /** + * Get the vets-website version item. + * + * @return array + * The vets-website version item. + */ + public function getVetsWebsiteVersionItem(): array { + return [ + 'title' => $this->t('vets-website version'), + 'value' => $this->status->getVetsWebsiteVersion(), + ]; + } + + /** + * Get the build log item. + * + * @return array + * The build log item. + */ + public function getBuildLogItem(): array { + return [ + 'title' => $this->t('Build log'), + 'value' => $this->getBuildLogLink(), + ]; + } + + /** + * Get the build log link. + * + * @return \Drupal\Core\GeneratedLink + * The build log link. + */ + public function getBuildLogLink() { + $buildLogPath = $this->status->getBuildLogPath(); + $buildLogUri = $this->backendBaseUrl . $buildLogPath; + $buildLogUrl = Url::fromUri($buildLogUri, ['attributes' => ['target' => '_blank']]); + return Link::fromTextAndUrl($this->t('View build log'), $buildLogUrl); + } + + /** + * Attach the status block library. + * + * @param array $build + * The render array. + */ + public function attachStatusBlockLibrary(array &$build) { + $build['#attached']['library'][] = 'va_gov_content_release/status_block'; + $build['#attached']['drupalSettings']['contentRelease']['statusBlock'] = [ + 'blockRefreshPath' => Url::fromRoute(static::BLOCK_REFRESH_ROUTE)->toString(), + ]; + } + +} diff --git a/docroot/modules/custom/va_gov_content_release/src/Plugin/Strategy/GitHubRepositoryDispatch.php b/docroot/modules/custom/va_gov_content_release/src/Plugin/Strategy/GitHubRepositoryDispatch.php index 5ad7cd732e..d0c3416cfb 100644 --- a/docroot/modules/custom/va_gov_content_release/src/Plugin/Strategy/GitHubRepositoryDispatch.php +++ b/docroot/modules/custom/va_gov_content_release/src/Plugin/Strategy/GitHubRepositoryDispatch.php @@ -2,12 +2,12 @@ namespace Drupal\va_gov_content_release\Plugin\Strategy; +use Drupal\Core\StringTranslation\TranslationInterface; use Drupal\va_gov_content_release\Exception\ContentReleaseInProgressException; use Drupal\va_gov_content_release\Exception\StrategyErrorException; -use Drupal\va_gov_content_release\Strategy\Plugin\StrategyPluginBase; -use Drupal\Core\StringTranslation\TranslationInterface; use Drupal\va_gov_content_release\GitHub\GitHubRepositoryDispatchInterface; use Drupal\va_gov_content_release\Reporter\ReporterInterface; +use Drupal\va_gov_content_release\Strategy\Plugin\StrategyPluginBase; use Symfony\Component\DependencyInjection\ContainerInterface; /** diff --git a/docroot/modules/custom/va_gov_content_release/src/Plugin/Strategy/LocalFilesystemBuildFile.php b/docroot/modules/custom/va_gov_content_release/src/Plugin/Strategy/LocalFilesystemBuildFile.php index 9e9386175c..f9982e9d30 100644 --- a/docroot/modules/custom/va_gov_content_release/src/Plugin/Strategy/LocalFilesystemBuildFile.php +++ b/docroot/modules/custom/va_gov_content_release/src/Plugin/Strategy/LocalFilesystemBuildFile.php @@ -2,11 +2,11 @@ namespace Drupal\va_gov_content_release\Plugin\Strategy; +use Drupal\Core\StringTranslation\TranslationInterface; use Drupal\va_gov_content_release\Exception\StrategyErrorException; use Drupal\va_gov_content_release\LocalFilesystem\LocalFilesystemBuildFileInterface; -use Drupal\va_gov_content_release\Strategy\Plugin\StrategyPluginBase; -use Drupal\Core\StringTranslation\TranslationInterface; use Drupal\va_gov_content_release\Reporter\ReporterInterface; +use Drupal\va_gov_content_release\Strategy\Plugin\StrategyPluginBase; use Symfony\Component\DependencyInjection\ContainerInterface; /** diff --git a/docroot/modules/custom/va_gov_content_release/src/Status/Status.php b/docroot/modules/custom/va_gov_content_release/src/Status/Status.php new file mode 100644 index 0000000000..0a065e8dff --- /dev/null +++ b/docroot/modules/custom/va_gov_content_release/src/Status/Status.php @@ -0,0 +1,149 @@ +stringTranslation = $stringTranslation; + $this->dateFormatter = $dateFormatter; + $this->releaseStateManager = $releaseStateManager; + $this->strategyResolver = $strategyResolver; + $this->frontendVersion = $frontendVersion; + } + + /** + * {@inheritDoc} + */ + public function getCurrentReleaseState() : string { + return $this->releaseStateManager->getState(); + } + + /** + * {@inheritDoc} + */ + public function getHumanReadableCurrentReleaseState() : string { + return match ($this->getCurrentReleaseState()) { + // An enum will make this more beautiful. + // @see https://github.com/department-of-veterans-affairs/va.gov-cms/issues/15556 + ReleaseStateManager::STATE_READY => $this->t('Ready'), + ReleaseStateManager::STATE_REQUESTED => $this->t('Requested'), + ReleaseStateManager::STATE_DISPATCHED => $this->t('Dispatched'), + ReleaseStateManager::STATE_STARTING => $this->t('Starting'), + ReleaseStateManager::STATE_INPROGRESS => $this->t('In Progress'), + ReleaseStateManager::STATE_COMPLETE => $this->t('Complete'), + default => $this->t('Unknown'), + }; + } + + /** + * {@inheritDoc} + */ + public function getLastReleaseCompleteTimestamp() : int { + return $this->releaseStateManager->getLastReleaseCompleteTimestamp(); + } + + /** + * {@inheritDoc} + */ + public function getLastReleaseCompleteDate() : string { + $timestamp = $this->getLastReleaseCompleteTimestamp(); + if ($timestamp === 0) { + return $this->t('Never'); + } + return $this->dateFormatter->format($timestamp, 'standard'); + } + + /** + * {@inheritDoc} + */ + public function hasAdditionalBuildDetails() : bool { + return in_array($this->strategyResolver->getStrategyId(), StatusInterface::ADDITIONAL_BUILD_DETAILS_STRATEGY_IDS); + } + + /** + * {@inheritDoc} + */ + public function getContentBuildVersion() : string { + return $this->frontendVersion->getVersion(Frontend::ContentBuild); + } + + /** + * {@inheritDoc} + */ + public function getVetsWebsiteVersion() : string { + return $this->frontendVersion->getVersion(Frontend::VetsWebsite); + } + + /** + * {@inheritDoc} + */ + public function getBuildLogPath() : string { + return '/sites/default/files/build.txt'; + } + +} diff --git a/docroot/modules/custom/va_gov_content_release/src/Status/StatusInterface.php b/docroot/modules/custom/va_gov_content_release/src/Status/StatusInterface.php new file mode 100644 index 0000000000..5f7476c544 --- /dev/null +++ b/docroot/modules/custom/va_gov_content_release/src/Status/StatusInterface.php @@ -0,0 +1,91 @@ +repositoryFactory->getContentBuild(), $this->loggerFactory); } + /** + * {@inheritDoc} + */ + public function getVetsWebsite(): BranchSearchInterface { + return new BranchSearch($this->repositoryFactory->getVetsWebsite(), $this->loggerFactory); + } + } diff --git a/docroot/modules/custom/va_gov_git/src/BranchSearch/Factory/BranchSearchFactoryInterface.php b/docroot/modules/custom/va_gov_git/src/BranchSearch/Factory/BranchSearchFactoryInterface.php index e2787533f5..8d67cb0b1f 100644 --- a/docroot/modules/custom/va_gov_git/src/BranchSearch/Factory/BranchSearchFactoryInterface.php +++ b/docroot/modules/custom/va_gov_git/src/BranchSearch/Factory/BranchSearchFactoryInterface.php @@ -10,9 +10,10 @@ * This service provides a way to create branch search services corresponding * to specific Git repositories. * - * At this time, we're primarily interested in two repositories: + * At this time, we're primarily interested in three repositories: * - The `va.gov-cms` repository. * - The `content-build` repository. + * - The `vets-website` repository. */ interface BranchSearchFactoryInterface { @@ -46,4 +47,12 @@ public function getCms(): BranchSearchInterface; */ public function getContentBuild(): BranchSearchInterface; + /** + * Get the vets-website branch search service. + * + * @return \Drupal\va_gov_git\BranchSearch\BranchSearchInterface + * The vets-website branch search object. + */ + public function getVetsWebsite(): BranchSearchInterface; + } diff --git a/docroot/modules/custom/va_gov_git/src/Repository/Factory/RepositoryFactory.php b/docroot/modules/custom/va_gov_git/src/Repository/Factory/RepositoryFactory.php index 60da7fb8fc..fe70477b26 100644 --- a/docroot/modules/custom/va_gov_git/src/Repository/Factory/RepositoryFactory.php +++ b/docroot/modules/custom/va_gov_git/src/Repository/Factory/RepositoryFactory.php @@ -2,9 +2,9 @@ namespace Drupal\va_gov_git\Repository\Factory; -use Drupal\va_gov_git\Repository\Settings\RepositorySettingsInterface; use Drupal\va_gov_git\Repository\Repository; use Drupal\va_gov_git\Repository\RepositoryInterface; +use Drupal\va_gov_git\Repository\Settings\RepositorySettingsInterface; /** * The Repository Factory service. @@ -12,9 +12,10 @@ * This service provides a way to create services corresponding to specific Git * repositories. * - * At this time, we're primarily interested in two repositories: + * At this time, we're primarily interested in three repositories: * - The `va.gov-cms` repository. * - The `content-build` repository. + * - The `vets-website` repository. */ class RepositoryFactory implements RepositoryFactoryInterface { @@ -57,4 +58,11 @@ public function getContentBuild(): RepositoryInterface { return $this->get(RepositorySettingsInterface::CONTENT_BUILD); } + /** + * {@inheritDoc} + */ + public function getVetsWebsite(): RepositoryInterface { + return $this->get(RepositorySettingsInterface::VETS_WEBSITE); + } + } diff --git a/docroot/modules/custom/va_gov_git/src/Repository/Factory/RepositoryFactoryInterface.php b/docroot/modules/custom/va_gov_git/src/Repository/Factory/RepositoryFactoryInterface.php index 13002d5944..3e0a3350f2 100644 --- a/docroot/modules/custom/va_gov_git/src/Repository/Factory/RepositoryFactoryInterface.php +++ b/docroot/modules/custom/va_gov_git/src/Repository/Factory/RepositoryFactoryInterface.php @@ -10,9 +10,10 @@ * This service provides a way to create services corresponding to specific Git * repositories. * - * At this time, we're primarily interested in two repositories: + * At this time, we're primarily interested in three repositories: * - The `va.gov-cms` repository. * - The `content-build` repository. + * - The `vets-website` repository. */ interface RepositoryFactoryInterface { @@ -46,4 +47,12 @@ public function getCms(): RepositoryInterface; */ public function getContentBuild(): RepositoryInterface; + /** + * Get the vets-website repository. + * + * @return \Drupal\va_gov_git\Repository\RepositoryInterface + * The vets-website repository. + */ + public function getVetsWebsite(): RepositoryInterface; + } diff --git a/docroot/modules/custom/va_gov_git/src/Repository/Settings/RepositorySettingsInterface.php b/docroot/modules/custom/va_gov_git/src/Repository/Settings/RepositorySettingsInterface.php index 8ec7d63d7c..15615705cc 100644 --- a/docroot/modules/custom/va_gov_git/src/Repository/Settings/RepositorySettingsInterface.php +++ b/docroot/modules/custom/va_gov_git/src/Repository/Settings/RepositorySettingsInterface.php @@ -13,9 +13,11 @@ interface RepositorySettingsInterface { // Repository names. const VA_GOV_CMS = 'va.gov-cms'; const CONTENT_BUILD = 'content-build'; + const VETS_WEBSITE = 'vets-website'; const REPOSITORY_NAMES = [ self::VA_GOV_CMS, self::CONTENT_BUILD, + self::VETS_WEBSITE, ]; // Settings keys for the repositories' filesystem paths. @@ -23,9 +25,11 @@ interface RepositorySettingsInterface { // should point to values matching those paths. const VA_GOV_CMS_PATH_KEY = 'va_gov_app_root'; const CONTENT_BUILD_PATH_KEY = 'va_gov_web_root'; + const VETS_WEBSITE_PATH_KEY = 'va_gov_vets_website_root'; const PATH_KEYS = [ self::VA_GOV_CMS => self::VA_GOV_CMS_PATH_KEY, self::CONTENT_BUILD => self::CONTENT_BUILD_PATH_KEY, + self::VETS_WEBSITE => self::VETS_WEBSITE_PATH_KEY, ]; /** diff --git a/docroot/modules/custom/va_gov_git/va_gov_git.services.yml b/docroot/modules/custom/va_gov_git/va_gov_git.services.yml index e1b3415429..bd4757fffe 100644 --- a/docroot/modules/custom/va_gov_git/va_gov_git.services.yml +++ b/docroot/modules/custom/va_gov_git/va_gov_git.services.yml @@ -13,6 +13,10 @@ services: class: Drupal\va_gov_git\Repository\Repository factory: ['@va_gov_git.repository_factory', 'getContentBuild'] arguments: [] + va_gov_git.repository.vets_website: + class: Drupal\va_gov_git\Repository\Repository + factory: ['@va_gov_git.repository_factory', 'getVetsWebsite'] + arguments: [] va_gov_git.branch_search_factory: class: Drupal\va_gov_git\BranchSearch\Factory\BranchSearchFactory arguments: ['@va_gov_git.repository_factory', '@logger.factory'] @@ -24,3 +28,8 @@ services: class: Drupal\va_gov_git\BranchSearch\BranchSearch factory: ['@va_gov_git.branch_search_factory', 'getContentBuild'] arguments: [] + va_gov_git.branch_search.vets_website: + class: Drupal\va_gov_git\BranchSearch\BranchSearch + factory: ['@va_gov_git.branch_search_factory', 'getVetsWebsite'] + arguments: [] + diff --git a/docroot/modules/custom/va_gov_github/src/Api/Client/Factory/ApiClientFactory.php b/docroot/modules/custom/va_gov_github/src/Api/Client/Factory/ApiClientFactory.php index aafb89f94c..f4f59cc7ed 100644 --- a/docroot/modules/custom/va_gov_github/src/Api/Client/Factory/ApiClientFactory.php +++ b/docroot/modules/custom/va_gov_github/src/Api/Client/Factory/ApiClientFactory.php @@ -17,6 +17,7 @@ class ApiClientFactory implements ApiClientFactoryInterface { const OWNER = 'department-of-veterans-affairs'; const VA_GOV_CMS = 'va.gov-cms'; const CONTENT_BUILD = 'content-build'; + const VETS_WEBSITE = 'vets-website'; /** * The settings service. @@ -56,4 +57,11 @@ public function getContentBuild(): ApiClientInterface { return $this->get(static::OWNER, static::CONTENT_BUILD, $this->settings->getApiToken()); } + /** + * {@inheritDoc} + */ + public function getVetsWebsite(): ApiClientInterface { + return $this->get(static::OWNER, static::VETS_WEBSITE, $this->settings->getApiToken()); + } + } diff --git a/docroot/modules/custom/va_gov_github/src/Api/Client/Factory/ApiClientFactoryInterface.php b/docroot/modules/custom/va_gov_github/src/Api/Client/Factory/ApiClientFactoryInterface.php index 73a82214ff..4dbd126985 100644 --- a/docroot/modules/custom/va_gov_github/src/Api/Client/Factory/ApiClientFactoryInterface.php +++ b/docroot/modules/custom/va_gov_github/src/Api/Client/Factory/ApiClientFactoryInterface.php @@ -56,4 +56,15 @@ public function getCms(): ApiClientInterface; */ public function getContentBuild(): ApiClientInterface; + /** + * Retrieve an API client for the Vets-Website repository. + * + * @return \Drupal\va_gov_github\Api\Client\ApiClientInterface + * The GitHub Api Client instance. + * + * @throws \Drupal\va_gov_github\Exception\InvalidApiTokenException + * If the GitHub API token is provided, but is invalid. + */ + public function getVetsWebsite(): ApiClientInterface; + } diff --git a/docroot/modules/custom/va_gov_github/va_gov_github.services.yml b/docroot/modules/custom/va_gov_github/va_gov_github.services.yml index 69566856a3..60aa99976c 100644 --- a/docroot/modules/custom/va_gov_github/va_gov_github.services.yml +++ b/docroot/modules/custom/va_gov_github/va_gov_github.services.yml @@ -13,3 +13,7 @@ services: class: Drupal\va_gov_github\Api\Client\ApiClientInterface factory: ['@va_gov_github.api_client_factory', 'getContentBuild'] arguments: [] + va_gov_github.api_client.vets_website: + class: Drupal\va_gov_github\Api\Client\ApiClientInterface + factory: ['@va_gov_github.api_client_factory', 'getVetsWebsite'] + arguments: [] diff --git a/docroot/sites/default/settings.php b/docroot/sites/default/settings.php index 36756336ce..6151af1bc1 100755 --- a/docroot/sites/default/settings.php +++ b/docroot/sites/default/settings.php @@ -113,9 +113,10 @@ // Environment settings $settings['va_gov_composer_home'] = getenv('COMPOSER_HOME'); $settings['va_gov_path_to_composer'] = '/usr/local/bin/composer'; -// The default BRD locations. These settings are currently only used on tugboat/local +// The default project root locations. These settings are currently only used on Tugboat and local environments. $settings['va_gov_web_root'] = '/var/www/cms/web'; $settings['va_gov_app_root'] = '/var/www/cms'; +$settings['va_gov_vets_website_root'] = '/var/www/cms/docroot/vendor/va-gov/vets-website'; // Defaults (should only be local that doesn't set these), default to dev for config_split $config['config_split.config_split.dev']['status'] = TRUE; diff --git a/docroot/sites/default/settings/settings.local.php b/docroot/sites/default/settings/settings.local.php index d17153fd2b..29610f0852 100644 --- a/docroot/sites/default/settings/settings.local.php +++ b/docroot/sites/default/settings/settings.local.php @@ -5,7 +5,7 @@ // This should be set to something different, e.g. 'lando', if not in DDEV. // // We should shift to using the string 'ddev' rather than 'local' in the future -// to avoid confusion (especially given that we can have local overrides on +// to avoid confusion (especially given that we can have local overrides on // _any_ environment). $settings['va_gov_environment']['environment'] = 'ddev'; @@ -46,6 +46,7 @@ $settings['va_gov_frontend_url'] = $webhost_on_cli . '/static'; $settings['va_gov_app_root'] = getenv('DDEV_APPROOT'); $settings['va_gov_web_root'] = getenv('DDEV_APPROOT') . '/web'; +$settings['va_gov_vets_website_root'] = getenv('DDEV_APPROOT') . '/docroot/vendor/va-gov/vets-website'; $settings['memcache']['servers'] = [ 'memcached:11211' => 'default', diff --git a/docroot/sites/default/settings/settings.tugboat.php b/docroot/sites/default/settings/settings.tugboat.php index c1d2e1de44..5bcd14b1e3 100644 --- a/docroot/sites/default/settings/settings.tugboat.php +++ b/docroot/sites/default/settings/settings.tugboat.php @@ -37,6 +37,10 @@ $config['environment_indicator.indicator']['fg_color'] = '#212121'; $config['environment_indicator.indicator']['name'] = 'Tugboat'; +// Update next-build site endpoint to the appropriate tugboat alias +$config['next.next_site.next_build_preview_server']['base_url'] = 'https://next-' . getenv('TUGBOAT_SERVICE_TOKEN') . '.' . getenv('TUGBOAT_SERVICE_CONFIG_DOMAIN'); +$config['next.next_site.next_build_preview_server']['preview_url'] = 'https://next-' . getenv('TUGBOAT_SERVICE_TOKEN') . '.' . getenv('TUGBOAT_SERVICE_CONFIG_DOMAIN') . '/api/preview'; + $settings['trusted_host_patterns'] = [ '^localhost$', '^.*' . getenv('TUGBOAT_SERVICE_TOKEN') . '.' . getenv('TUGBOAT_SERVICE_CONFIG_DOMAIN') . '$', @@ -59,6 +63,7 @@ $settings['va_gov_frontend_build_type'] = 'tugboat'; $settings['va_gov_app_root'] = getenv('TUGBOAT_ROOT'); $settings['va_gov_web_root'] = getenv('TUGBOAT_ROOT') . '/web'; +$settings['va_gov_vets_website_root'] = getenv('TUGBOAT_ROOT') . '/docroot/vendor/va-gov/vets-website'; $settings['memcache']['servers'] = [ 'memcache:11211' => 'default', @@ -71,7 +76,7 @@ // PIV login does not currently work on Tugboat. // -// To avoid confusing editors, we want to disable PIV login completely on +// To avoid confusing editors, we want to disable PIV login completely on // Tugboat demo environments. // // However, we want to _preserve_ the PIV login interface on Tugboat PR diff --git a/scripts/build-frontend.sh b/scripts/build-frontend.sh index 300285e339..e23e6b1d23 100755 --- a/scripts/build-frontend.sh +++ b/scripts/build-frontend.sh @@ -39,12 +39,21 @@ trap "rm -f ${reporoot}/.buildlock" INT TERM EXIT # Just because the path is really long: logfile="${reporoot}/docroot/sites/default/files/build.txt" +# The currently selected version of content-build (may be "__default", a PR#, or a git ref) +content_build_version=$(drush va-gov-content-release:frontend-version:get content_build | tail -1) + +# The currently selected version of vets-website (may be "__default", a PR#, or a git ref) +vets_website_version=$(drush va-gov-content-release:frontend-version:get vets_website | tail -1) + # Create a fresh log file. [ -f "${logfile}" ] && rm ${logfile} touch ${logfile} date >> ${logfile} +echo "content-build version: ${content_build_version}" >> ${logfile} +echo "vets-website version: ${vets_website_version}" >> ${logfile} + # Tell the frontend (and the user) that we're starting. drush va-gov:content-release:advance-state starting echo "==> Starting a frontend build. This file will be updated as the build progresses." >> ${logfile} @@ -54,26 +63,44 @@ echo "==> Resetting VA repos to default versions" >> ${logfile} rm -rf ${reporoot}/docroot/vendor/va-gov composer install --no-scripts &>> ${logfile} -# Get the requested frontend version -feversion=$(drush va-gov:content-release:get-frontend-version | tail -1) -if [ "${feversion}" != "__default" ]; then +# Get the requested content-build version +if [ "${content_build_version}" != "__default" ]; then echo "==> Checking out the requested frontend version" >> ${logfile} pushd ${reporoot}/docroot/vendor/va-gov/content-build - if echo "$feversion" | grep -qE '^[0-9]+$' > /dev/null; then - echo "==> Checking out PR #${feversion}" - git fetch origin pull/${feversion}/head &>> ${logfile} - else - echo "==> Checking out git ref ${feversion}" - git fetch origin ${feversion} &>> ${logfile} - fi - git checkout FETCH_HEAD &>> ${logfile} + if echo "${content_build_version}" | grep -qE '^[0-9]+$' > /dev/null; then + echo "==> Checking out PR #${content_build_version}" + git fetch origin pull/${content_build_version}/head &>> ${logfile} + else + echo "==> Checking out git ref ${content_build_version}" + git fetch origin ${content_build_version} &>> ${logfile} + fi + git checkout FETCH_HEAD &>> ${logfile} popd +else + echo "==> Using default content-build version" >> ${logfile} fi # Install 3rd party deps. echo "==> Installing yarn dependencies" >> ${logfile} composer va:web:install &>> ${logfile} +# Get the requested vets-website version +if [ "${vets_website_version}" != "__default" ]; then + echo "==> Checking out the requested vets-website version" >> ${logfile} + pushd ${reporoot}/docroot/vendor/va-gov/vets-website + if echo "$vets_website_version" | grep -qE '^[0-9]+$' > /dev/null; then + echo "==> Checking out PR #${vets_website_version}" + git fetch origin pull/${vets_website_version}/head &>> ${logfile} + else + echo "==> Checking out git ref ${vets_website_version}" + git fetch origin ${vets_website_version} &>> ${logfile} + fi + git checkout FETCH_HEAD &>> ${logfile} + popd +else + echo "==> Using default vets-website version" >> ${logfile} +fi + # Run the build. echo "==> Starting build" >> ${logfile} drush va-gov:content-release:advance-state inprogress diff --git a/tests/cypress/integration/features/platform/content_release.feature b/tests/cypress/integration/features/platform/content_release.feature index ba1e082cbe..da163e93ff 100644 --- a/tests/cypress/integration/features/platform/content_release.feature +++ b/tests/cypress/integration/features/platform/content_release.feature @@ -7,12 +7,16 @@ Feature: Content Release Scenario: The user should be able to deploy a content release from the Simple form Given I am logged in as a user with the "content_admin" role And I reset the content release state from the command line + + # Require user confirmation. When I am at "/admin/content/deploy/simple" And I stub form submission for the current page And I click the "Release content" button And I wait for form submission Then I should see "1 error has been found" And I should see "You must confirm that you understand this implication." + + # Confirm and release. When I check the checkbox with selector "#edit-confirm" And I click the "Release content" button And I wait for form submission @@ -23,133 +27,105 @@ Feature: Content Release Scenario: The user should be able to deploy a content release from the Git form Given I am logged in as a user with the "content_admin" role And I reset the content release state from the command line + + # Default content release. When I am at "/admin/content/deploy/git" And I stub form submission for the current page And I click the "Release content" button And I wait for form submission Then I should see "Content release requested successfully" And I should see "Build request skipped; form is under test." - And I should see "Reset frontend version skipped; form is under test." + And I should see "Reset content_build version skipped; form is under test." + And I should see "Reset vets_website version skipped; form is under test." @new_content_release - Scenario: The user should be able to deploy a content release from the Git form with a branch selected. + Scenario: The user should be able to deploy a content release from the Git form with a content-build branch selected. Given I am logged in as a user with the "content_admin" role And I reset the content release state from the command line + + # Require that we select a content-build branch. When I am at "/admin/content/deploy/git" And I stub form submission for the current page - And I select the "Select a different frontend branch/pull request" radio button + And I select the "Select a different content-build branch/pull request" radio button And I click the "Release content" button And I wait for form submission Then I should see "Invalid selection." - When I fill in autocomplete field with selector "#edit-git-ref" with value "main" + + # Select content-build branch. + When I fill in autocomplete field with selector "#edit-content-build-git-ref" with value "main" Then I should see "BRANCH main" - When I fill in autocomplete field with selector "#edit-git-ref" with value "BRANCH main (main)" + When I fill in autocomplete field with selector "#edit-content-build-git-ref" with value "BRANCH main (main)" And I click the "Release content" button And I wait for form submission Then I should see "Content release requested successfully" And I should see "Build request skipped; form is under test." - And I should see "Set frontend version skipped; form is under test." + And I should see "Set content_build version skipped; form is under test." + And I should see "Reset vets_website version skipped; form is under test." @new_content_release - Scenario: The Simple content release form should not display the content release status block. + Scenario: The user should be able to deploy a content release from the Git form with a vets-website branch selected. Given I am logged in as a user with the "content_admin" role And I reset the content release state from the command line - When I am at "/admin/content/deploy/simple" - And I reload the page - And I scroll to position "bottom" - Then "Content release status" should not exist + + # Require that we select a vets-website branch. + When I am at "/admin/content/deploy/git" + And I stub form submission for the current page + And I select the "Select a different vets-website branch/pull request" radio button + And I click the "Release content" button + And I wait for form submission + Then I should see "Invalid selection." + + # Select vets-website branch. + When I fill in autocomplete field with selector "#edit-vets-website-git-ref" with value "main" + Then I should see "BRANCH main" + When I fill in autocomplete field with selector "#edit-vets-website-git-ref" with value "BRANCH main (main)" + And I click the "Release content" button + And I wait for form submission + Then I should see "Content release requested successfully" + And I should see "Build request skipped; form is under test." + And I should see "Reset content_build version skipped; form is under test." + And I should see "Set vets_website version skipped; form is under test." @new_content_release - Scenario: The Git content release form should normally display no in-process releases by default. + Scenario: The user should be able to deploy a content release from the Git form with a content-build and vets-website branch selected. Given I am logged in as a user with the "content_admin" role And I reset the content release state from the command line + + # Basic form setup. When I am at "/admin/content/deploy/git" - And I reload the page - And I scroll to position "bottom" - Then "Ready" should exist - # This is only on local/Tugboat ATM. I should add it back later. - # And I should see "View the full output of the last completed build process (including a broken link report)." + And I stub form submission for the current page - @skip_on_brd @old_content_release - # When we shift to the new content release system, this will be obsoleted by - # the new content release tests above. - Scenario: The content release page should normally display no in-process releases - Given I am logged in as a user with the "content_admin" role - And I reset the content release state from the command line - When I am at "/admin/content/deploy" - And I reload the page - And I scroll to position "bottom" - Then "Ready" should exist + # Select a content-build branch. + And I select the "Select a different content-build branch/pull request" radio button + And I fill in autocomplete field with selector "#edit-content-build-git-ref" with value "BRANCH main (main)" - @skip_on_brd @old_content_release - # When we shift to the new content release system, this will be obsoleted by - # the new content release tests above. - Scenario: The content release page should show a pending default release initiated within the browser - Given I am logged in as a user with the "content_admin" role - And I reset the content release state from the command line - When I am at "/admin/content/deploy" - And I click the "Release content" button - And I process the content release queue - And I reload the page - And I scroll to position "bottom" - Then "Preparing" should exist - And I reset the content release state from the command line - And I reload the page - And I scroll to position "bottom" - Then "Ready" should exist + # Select a vets-website branch. + And I select the "Select a different vets-website branch/pull request" radio button + And I fill in autocomplete field with selector "#edit-vets-website-git-ref" with value "BRANCH main (main)" - @skip_on_brd @old_content_release - # When we shift to the new content release system, this will be obsoleted by - # the new content release tests above. - # This test concerns functionality that is currently broken or not available - # in all environments, specifically interactions with the frontend git repo. - Scenario: The content release page should show a pending chosen release initiated within the browser - Given I am logged in as a user with the "content_admin" role - And I reset the content release state from the command line - When I initiate a content release with the branch "main" - And I process the content release queue - And I am at "/admin/content/deploy" - And I scroll to position "bottom" - Then "Preparing" should exist - And I reset the content release state from the command line - And I reload the page - And I scroll to position "bottom" - Then "Ready" should exist + When I click the "Release content" button + And I wait for form submission + Then I should see "Content release requested successfully" + And I should see "Build request skipped; form is under test." + And I should see "Set content_build version skipped; form is under test." + And I should see "Set vets_website version skipped; form is under test." - @skip_on_brd @old_content_release - # When we shift to the new content release system, this will be obsoleted by - # the new content release tests above. - Scenario: The content release page should show a pending default release initiated from the command line + @new_content_release + Scenario: The Simple content release form should not display the content release status block. Given I am logged in as a user with the "content_admin" role And I reset the content release state from the command line - And I initiate a content release from the command line - And I process the content release queue - And I am at "/admin/content/deploy" - And I scroll to position "bottom" - Then "Preparing" should exist - And I reset the content release state from the command line + When I am at "/admin/content/deploy/simple" And I reload the page And I scroll to position "bottom" - Then "Ready" should exist + Then "Content release status" should not exist - @skip_on_brd @ignore @old_content_release - # When we shift to the new content release system, this will be obsoleted by - # the new content release tests above. - # This test concerns functionality that is currently not available, - # specifically initiating releases from the command line with a specific - # branch. - # If this unavailable functionality is permanently removed, this test should - # be as well. - Scenario: The content release page should show a pending chosen release initiated from the command line + @new_content_release + Scenario: The Git content release form should normally display no in-process releases by default. Given I am logged in as a user with the "content_admin" role And I reset the content release state from the command line - And I initiate a content release from the command line with the branch "main" - And I process the content release queue - And I reload the page - And I scroll to position "bottom" - Then "Branch: " should exist - And "Preparing" should exist - And I reset the content release state from the command line + When I am at "/admin/content/deploy/git" And I reload the page And I scroll to position "bottom" Then "Ready" should exist + # This is only on local/Tugboat ATM. I should add it back later. + # And I should see "View the full output of the last completed build process (including a broken link report)." diff --git a/tests/phpunit/FrontendBuild/BuildRequesterTest.php b/tests/phpunit/FrontendBuild/BuildRequesterTest.php index 9d4afd0e34..2d90788db0 100644 --- a/tests/phpunit/FrontendBuild/BuildRequesterTest.php +++ b/tests/phpunit/FrontendBuild/BuildRequesterTest.php @@ -8,7 +8,7 @@ use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\KeyValueStore\KeyValueMemoryFactory; use Drupal\Core\State\State; -use Drupal\va_gov_build_trigger\Service\BuildRequester; +use Drupal\va_gov_content_release\Request\Request as BuildRequester; use Tests\Support\Classes\VaGovUnitTestBase; /** @@ -38,7 +38,7 @@ public function setUp() : void { /** * Test that we're getting state values back from getState(). */ - public function testRequestFrontendBuild() { + public function testSubmitRequest() { // Mock the queue and assert that we're getting the right things in the job // that is created and enqueued. $queue = $this->getMockBuilder(QueueInterface::class) @@ -67,26 +67,8 @@ public function testRequestFrontendBuild() { // Finally, create a build requester and request a build (which should // trigger the assertions above). - $buildRequester = new BuildRequester($entityTypeManager, $this->state); - $buildRequester->requestFrontendBuild('TEST REASON'); - } - - /** - * Test that setting and unsetting the frontend version works. - */ - public function testFrontendVersionSelection() { - $queue = $this->getMockBuilder(QueueInterface::class) - ->disableOriginalConstructor() - ->getMock(); - $entityTypeManager = $this->getEntityTypeManagerWithStorageAndQueue($queue); - - $buildRequester = new BuildRequester($entityTypeManager, $this->state); - - $buildRequester->switchFrontendVersion('foobar'); - $this->assertEquals('foobar', $this->state->get(BuildRequester::VA_GOV_FRONTEND_VERSION)); - - $buildRequester->resetFrontendVersion(); - $this->assertEquals('NOT PRESENT', $this->state->get(BuildRequester::VA_GOV_FRONTEND_VERSION, 'NOT PRESENT')); + $buildRequester = new BuildRequester($entityTypeManager); + $buildRequester->submitRequest('TEST REASON'); } /** diff --git a/tests/phpunit/FrontendBuild/BuildSchedulerTest.php b/tests/phpunit/FrontendBuild/BuildSchedulerTest.php index 76dc4bea03..c728f82f85 100644 --- a/tests/phpunit/FrontendBuild/BuildSchedulerTest.php +++ b/tests/phpunit/FrontendBuild/BuildSchedulerTest.php @@ -8,11 +8,11 @@ use Drupal\Core\KeyValueStore\KeyValueMemoryFactory; use Drupal\Core\Language\LanguageManagerInterface; use Drupal\Core\State\State; -use Drupal\va_gov_build_trigger\Service\BuildRequester; use Drupal\va_gov_build_trigger\Service\BuildScheduler; +use Drupal\va_gov_content_release\Request\RequestInterface; use Symfony\Component\DependencyInjection\Container; -use Tests\Support\Mock\SpecifiedTime; use Tests\Support\Classes\VaGovUnitTestBase; +use Tests\Support\Mock\SpecifiedTime; /** * Unit test for the build scheduler. @@ -25,7 +25,7 @@ class BuildSchedulerTest extends VaGovUnitTestBase { /** * The build requester service. * - * @var \Drupal\va_gov_build_trigger\Service\BuildRequesterInterface + * @var \Drupal\va_gov_content_release\Request\RequestInterface */ protected $buildRequester; @@ -207,22 +207,22 @@ public function testCheckScheduledBuild($time, $last_scheduled_build_request, $s * @param bool $shouldExpectBuildRequest * Whether or not the build requester should get a request. * - * @return \Drupal\va_gov_build_trigger\Service\BuildRequesterInterface + * @return \Drupal\va_gov_content_release\Request\RequestInterface * (mocked) */ protected function getBuildRequester($shouldExpectBuildRequest = FALSE) { - $build_requester = $this->getMockBuilder(BuildRequester::class) + $build_requester = $this->getMockBuilder(RequestInterface::class) ->disableOriginalConstructor() ->getMock(); if ($shouldExpectBuildRequest) { $build_requester->expects($this->once()) - ->method('requestFrontendBuild') + ->method('submitRequest') ->with('Scheduled hourly build'); } else { $build_requester->expects($this->never()) - ->method('requestFrontendBuild'); + ->method('submitRequest'); } return $build_requester; diff --git a/tests/phpunit/FrontendBuild/BuildStateEventSubscriberTest.php b/tests/phpunit/FrontendBuild/BuildStateEventSubscriberTest.php index d3b4f7ecac..f0b191ecc9 100644 --- a/tests/phpunit/FrontendBuild/BuildStateEventSubscriberTest.php +++ b/tests/phpunit/FrontendBuild/BuildStateEventSubscriberTest.php @@ -2,7 +2,10 @@ namespace tests\phpunit\FrontendBuild; +use Drupal\Core\Datetime\DateFormatter; +use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\KeyValueStore\KeyValueMemoryFactory; +use Drupal\Core\Language\LanguageManagerInterface; use Drupal\Core\State\State; use Drupal\prometheus_exporter\MetricsCollectorManager; use Drupal\va_gov_build_trigger\Event\ReleaseStateTransitionEvent; @@ -11,15 +14,12 @@ use Drupal\va_gov_build_trigger\EventSubscriber\ContentReleaseMetricsRecalculationSubscriber; use Drupal\va_gov_build_trigger\EventSubscriber\ContinuousReleaseSubscriber; use Drupal\va_gov_build_trigger\Plugin\MetricsCollector\ContentReleaseInterval; -use Drupal\va_gov_build_trigger\Service\BuildRequester; use Drupal\va_gov_build_trigger\Service\ReleaseStateManager; -use Symfony\Component\HttpFoundation\RequestStack; -use Tests\Support\Mock\SpecifiedTime; -use Drupal\Core\Datetime\DateFormatter; -use Drupal\Core\Entity\EntityTypeManagerInterface; -use Drupal\Core\Language\LanguageManagerInterface; +use Drupal\va_gov_content_release\Request\RequestInterface; use Symfony\Component\DependencyInjection\Container; +use Symfony\Component\HttpFoundation\RequestStack; use Tests\Support\Classes\VaGovUnitTestBase; +use Tests\Support\Mock\SpecifiedTime; /** * Unit test for build state event subscribers. @@ -77,12 +77,12 @@ public function setUp() : void { * Tests the ContentReleaseErrorSubscriber class. */ public function testContentReleaseErrorSubscriber() { - $buildRequester = $this->getMockBuilder(BuildRequester::class) + $buildRequester = $this->getMockBuilder(RequestInterface::class) ->disableOriginalConstructor() ->getMock(); $buildRequester->expects($this->never()) - ->method('requestFrontendBuild'); + ->method('submitRequest'); $no_states = [ 'ready', @@ -99,12 +99,12 @@ public function testContentReleaseErrorSubscriber() { $subscriber->handleError($event); } - $buildRequester = $this->getMockBuilder(BuildRequester::class) + $buildRequester = $this->getMockBuilder(RequestInterface::class) ->disableOriginalConstructor() ->getMock(); $buildRequester->expects($this->once()) - ->method('requestFrontendBuild') + ->method('submitRequest') ->with($this->callback(function ($reason) { $contains_str = str_contains($reason, 'Retrying build'); $this->assertTrue($contains_str); @@ -223,17 +223,17 @@ public function testContinuousRelease($continuous_release_enabled, $event, $time $state = new State(new KeyValueMemoryFactory()); $state->set(ContinuousReleaseSubscriber::CONTINUOUS_RELEASE_ENABLED, $continuous_release_enabled); - $buildRequester = $this->getMockBuilder(BuildRequester::class) + $buildRequester = $this->getMockBuilder(RequestInterface::class) ->disableOriginalConstructor() ->getMock(); if ($expected) { $buildRequester->expects($this->once()) - ->method('requestFrontendBuild'); + ->method('submitRequest'); } else { $buildRequester->expects($this->never()) - ->method('requestFrontendBuild'); + ->method('submitRequest'); } $continuous_release_subscriber = new ContinuousReleaseSubscriber($state, $time, $buildRequester, $this->dateFormatter); diff --git a/tests/phpunit/va_gov_content_release/functional/EntityEvent/Strategy/Plugin/StrategyPluginManagerTest.php b/tests/phpunit/va_gov_content_release/functional/EntityEvent/Strategy/Plugin/StrategyPluginManagerTest.php index c068ace78c..bf08265c74 100644 --- a/tests/phpunit/va_gov_content_release/functional/EntityEvent/Strategy/Plugin/StrategyPluginManagerTest.php +++ b/tests/phpunit/va_gov_content_release/functional/EntityEvent/Strategy/Plugin/StrategyPluginManagerTest.php @@ -2,8 +2,8 @@ namespace tests\phpunit\va_gov_content_release\functional\EntityEvent\Strategy\Plugin; -use Drupal\va_gov_content_release\Exception\StrategyErrorException; use Drupal\va_gov_content_release\EntityEvent\Strategy\Plugin\StrategyPluginInterface; +use Drupal\va_gov_content_release\Exception\StrategyErrorException; use Drupal\va_gov_content_types\Entity\VaNodeInterface; use Tests\Support\Classes\VaGovExistingSiteBase; diff --git a/tests/phpunit/va_gov_content_release/functional/FrontendUrl/FrontendUrlTest.php b/tests/phpunit/va_gov_content_release/functional/FrontendUrl/FrontendUrlTest.php new file mode 100644 index 0000000000..fa5f730fdb --- /dev/null +++ b/tests/phpunit/va_gov_content_release/functional/FrontendUrl/FrontendUrlTest.php @@ -0,0 +1,29 @@ +assertInstanceOf(FrontendUrl::class, $frontendUrl); + $this->assertNotEmpty($frontendUrl->getBaseUrl()); + } + +} diff --git a/tests/phpunit/va_gov_content_release/functional/Status/StatusTest.php b/tests/phpunit/va_gov_content_release/functional/Status/StatusTest.php new file mode 100644 index 0000000000..502bce9d19 --- /dev/null +++ b/tests/phpunit/va_gov_content_release/functional/Status/StatusTest.php @@ -0,0 +1,28 @@ +assertInstanceOf(Status::class, $status); + } + +} diff --git a/tests/phpunit/va_gov_content_release/unit/FrontendVersion/FrontendVersionTest.php b/tests/phpunit/va_gov_content_release/unit/FrontendVersion/FrontendVersionTest.php index 6dc559b946..b5370645ee 100644 --- a/tests/phpunit/va_gov_content_release/unit/FrontendVersion/FrontendVersionTest.php +++ b/tests/phpunit/va_gov_content_release/unit/FrontendVersion/FrontendVersionTest.php @@ -2,8 +2,9 @@ namespace tests\phpunit\va_gov_content_release\unit\FrontendVersion; -use Drupal\Core\State\State; use Drupal\Core\KeyValueStore\KeyValueMemoryFactory; +use Drupal\Core\State\State; +use Drupal\va_gov_content_release\Frontend\Frontend; use Drupal\va_gov_content_release\FrontendVersion\FrontendVersion; use Drupal\va_gov_content_release\FrontendVersion\FrontendVersionInterface; use Tests\Support\Classes\VaGovUnitTestBase; @@ -22,18 +23,19 @@ class FrontendVersionTest extends VaGovUnitTestBase { * Test that the service works as expected. * * @covers ::__construct - * @covers ::get - * @covers ::set - * @covers ::reset + * @covers ::getVersion + * @covers ::setVersion + * @covers ::resetVersion */ public function testGetSetReset() : void { $state = new State(new KeyValueMemoryFactory()); + $frontend = Frontend::ContentBuild; $frontendVersion = new FrontendVersion($state); - $this->assertEquals(FrontendVersionInterface::FRONTEND_VERSION_DEFAULT, $frontendVersion->get()); - $frontendVersion->set('1.2.3'); - $this->assertEquals('1.2.3', $frontendVersion->get()); - $frontendVersion->reset(); - $this->assertEquals(FrontendVersionInterface::FRONTEND_VERSION_DEFAULT, $frontendVersion->get()); + $this->assertEquals(FrontendVersionInterface::FRONTEND_VERSION_DEFAULT, $frontendVersion->getVersion($frontend)); + $frontendVersion->setVersion($frontend, '1.2.3'); + $this->assertEquals('1.2.3', $frontendVersion->getVersion($frontend)); + $frontendVersion->resetVersion($frontend); + $this->assertEquals(FrontendVersionInterface::FRONTEND_VERSION_DEFAULT, $frontendVersion->getVersion($frontend)); } } diff --git a/tests/phpunit/va_gov_git/functional/BranchSearch/BranchSearchTest.php b/tests/phpunit/va_gov_git/functional/BranchSearch/BranchSearchTest.php index 18218f2465..d10b8ecdf3 100644 --- a/tests/phpunit/va_gov_git/functional/BranchSearch/BranchSearchTest.php +++ b/tests/phpunit/va_gov_git/functional/BranchSearch/BranchSearchTest.php @@ -35,6 +35,7 @@ public function getDataProvider() { return [ ['va_gov_git.branch_search.va_gov_cms'], ['va_gov_git.branch_search.content_build'], + ['va_gov_git.branch_search.vets_website'], ]; } @@ -65,6 +66,7 @@ public function getRemoteBranchNamesContainingDataProvider() { return [ ['va_gov_git.branch_search.va_gov_cms', 'main'], ['va_gov_git.branch_search.content_build', 'main'], + ['va_gov_git.branch_search.vets_website', 'main'], ]; } diff --git a/tests/phpunit/va_gov_git/functional/BranchSearch/Factory/BranchSearchFactoryTest.php b/tests/phpunit/va_gov_git/functional/BranchSearch/Factory/BranchSearchFactoryTest.php index 3519c5b4f9..61818c0f6c 100644 --- a/tests/phpunit/va_gov_git/functional/BranchSearch/Factory/BranchSearchFactoryTest.php +++ b/tests/phpunit/va_gov_git/functional/BranchSearch/Factory/BranchSearchFactoryTest.php @@ -2,8 +2,8 @@ namespace tests\phpunit\va_gov_git\functional\BranchSearch\Factory; -use Drupal\va_gov_git\BranchSearch\Factory\BranchSearchFactory; use Drupal\va_gov_git\BranchSearch\BranchSearchInterface; +use Drupal\va_gov_git\BranchSearch\Factory\BranchSearchFactory; use Drupal\va_gov_git\Repository\Settings\RepositorySettingsInterface; use Tests\Support\Classes\VaGovExistingSiteBase; @@ -69,4 +69,12 @@ public function testGetContentBuild() { $this->assertInstanceOf(BranchSearchInterface::class, $branchSearch); } + /** + * Test the getVetsWebsite() method. + */ + public function testGetVetsWebsite() { + $branchSearch = \Drupal::service('va_gov_git.branch_search_factory')->getVetsWebsite(); + $this->assertInstanceOf(BranchSearchInterface::class, $branchSearch); + } + } diff --git a/tests/phpunit/va_gov_git/functional/Repository/Factory/RepositoryFactoryTest.php b/tests/phpunit/va_gov_git/functional/Repository/Factory/RepositoryFactoryTest.php index 0ba76c1a51..635f9095c9 100644 --- a/tests/phpunit/va_gov_git/functional/Repository/Factory/RepositoryFactoryTest.php +++ b/tests/phpunit/va_gov_git/functional/Repository/Factory/RepositoryFactoryTest.php @@ -3,8 +3,8 @@ namespace tests\phpunit\va_gov_git\functional\Repository\Factory; use Drupal\va_gov_git\Repository\Factory\RepositoryFactory; -use Drupal\va_gov_git\Repository\Settings\RepositorySettingsInterface; use Drupal\va_gov_git\Repository\RepositoryInterface; +use Drupal\va_gov_git\Repository\Settings\RepositorySettingsInterface; use Tests\Support\Classes\VaGovExistingSiteBase; /** @@ -69,4 +69,12 @@ public function testGetContentBuild() { $this->assertInstanceOf(RepositoryInterface::class, $repository); } + /** + * Test the getVetsWebsite() method. + */ + public function testGetVetsWebsite() { + $repository = \Drupal::service('va_gov_git.repository_factory')->getVetsWebsite(); + $this->assertInstanceOf(RepositoryInterface::class, $repository); + } + } diff --git a/tests/phpunit/va_gov_git/functional/Repository/RepositoryTest.php b/tests/phpunit/va_gov_git/functional/Repository/RepositoryTest.php index 5e8c3a1e85..d87c9429d5 100644 --- a/tests/phpunit/va_gov_git/functional/Repository/RepositoryTest.php +++ b/tests/phpunit/va_gov_git/functional/Repository/RepositoryTest.php @@ -35,6 +35,16 @@ public function testConstructContentBuild() { $this->assertInstanceOf(RepositoryInterface::class, $repository); } + /** + * Test that we can instantiate the Vets-Website repository. + */ + public function testConstructVetsWebsite() { + $repository = \Drupal::service('va_gov_git.repository_factory')->getContentBuild(); + $this->assertInstanceOf(RepositoryInterface::class, $repository); + $repository = \Drupal::service('va_gov_git.repository.vets_website'); + $this->assertInstanceOf(RepositoryInterface::class, $repository); + } + /** * Test that each repository has remote branches. * @@ -87,6 +97,16 @@ public function getRemoteBranchNamesDataProvider() { 'refs/remotes/origin/this-branch-does-not-exist', FALSE, ], + [ + 'vets-website', + 'refs/remotes/origin/main', + TRUE, + ], + [ + 'vets-website', + 'refs/remotes/origin/this-branch-does-not-exist', + FALSE, + ], ]; } diff --git a/tests/phpunit/va_gov_git/functional/Repository/Settings/RepositorySettingsTest.php b/tests/phpunit/va_gov_git/functional/Repository/Settings/RepositorySettingsTest.php index 2a5c0c00a8..b50b2de832 100644 --- a/tests/phpunit/va_gov_git/functional/Repository/Settings/RepositorySettingsTest.php +++ b/tests/phpunit/va_gov_git/functional/Repository/Settings/RepositorySettingsTest.php @@ -46,6 +46,7 @@ public function testGetPathKey() { $repositorySettings = \Drupal::service('va_gov_git.repository_settings'); $this->assertEquals(RepositorySettingsInterface::PATH_KEYS['va.gov-cms'], $repositorySettings->getPathKey('va.gov-cms')); $this->assertEquals(RepositorySettingsInterface::PATH_KEYS['content-build'], $repositorySettings->getPathKey('content-build')); + $this->assertEquals(RepositorySettingsInterface::PATH_KEYS['vets-website'], $repositorySettings->getPathKey('vets-website')); } /** @@ -64,6 +65,10 @@ public function testList() { 'name' => RepositorySettingsInterface::CONTENT_BUILD, 'path' => Settings::get('va_gov_web_root'), ], + [ + 'name' => RepositorySettingsInterface::VETS_WEBSITE, + 'path' => Settings::get('va_gov_vets_website_root'), + ], ], $repositorySettings->list()); } diff --git a/tests/phpunit/va_gov_git/unit/Repository/Settings/RepositorySettingsTest.php b/tests/phpunit/va_gov_git/unit/Repository/Settings/RepositorySettingsTest.php index d6d26e4e3a..20b5d104d3 100644 --- a/tests/phpunit/va_gov_git/unit/Repository/Settings/RepositorySettingsTest.php +++ b/tests/phpunit/va_gov_git/unit/Repository/Settings/RepositorySettingsTest.php @@ -29,6 +29,7 @@ public function getRepositorySettings() { $settings = new Settings([ 'va_gov_app_root' => '/srv/cms', 'va_gov_web_root' => '/srv/web', + 'va_gov_vets_website_root' => '/srv/vets-website', ]); return new RepositorySettings($settings); } @@ -66,6 +67,7 @@ public function getPathKeyDataProvider() { return [ ['va.gov-cms', RepositorySettings::VA_GOV_CMS_PATH_KEY], ['content-build', RepositorySettings::CONTENT_BUILD_PATH_KEY], + ['vets-website', RepositorySettings::VETS_WEBSITE_PATH_KEY], ]; } @@ -94,6 +96,7 @@ public function getPathDataProvider() { return [ ['va.gov-cms', '/srv/cms'], ['content-build', '/srv/web'], + ['vets-website', '/srv/vets-website'], ]; } @@ -139,6 +142,10 @@ public function testList() { 'name' => RepositorySettingsInterface::CONTENT_BUILD, 'path' => '/srv/web', ], + [ + 'name' => RepositorySettingsInterface::VETS_WEBSITE, + 'path' => '/srv/vets-website', + ], ], $repositorySettings->list()); } diff --git a/tugboat.yml b/tugboat.yml index 9e85728187..0af8f93bac 100644 --- a/tugboat.yml +++ b/tugboat.yml @@ -11,7 +11,7 @@ tasks: build-frontend: desc: Request a frontend build cmds: - - drush va-gov:content-release:request-frontend-build + - drush va-gov-content-release:request:submit build-next: desc: build next.js preview server