diff --git a/.circleci/aws_config b/.circleci/aws_config deleted file mode 100644 index 2565f2151..000000000 --- a/.circleci/aws_config +++ /dev/null @@ -1,2 +0,0 @@ -[default] -output = json diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index e8be2a253..000000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,362 +0,0 @@ -# Yext Answers CircleCI configuration -version: 2.1 -orbs: - aws-s3: circleci/aws-s3@1.0.9 -commands: - setup-workspace: - description: "Checks out the repo and installs node_modules with the cache" - steps: - - checkout - # Download and cache dependencies - - restore_cache: - keys: - - v3-node-14-{{ checksum "package-lock.json" }} - # fallback to use the latest cache from the same node version if no exact match is found - - v3-node-14- - - run: npm install - - save_cache: - paths: - - node_modules - key: v3-node-14-{{ checksum "package-lock.json" }} - deploy-to-aws: - description: "Deploys the dist directory to a given subdirectory of the answers bucket" - parameters: - subdirectory: - type: string - cache-control: - type: string - default: "no-cache" - deploy-bucket: - type: string - default: answers - steps: - - attach_workspace: - at: ~/answers - - run: - name: Configure AWS - command: | - mkdir -p ~/.aws - cp .circleci/aws_config ~/.aws/config - echo -e $AWS_PROD_PROFILE >> ~/.aws/config - - aws-s3/copy: - from: dist - to: 's3://assets.sitescdn.net/<< parameters.deploy-bucket >><< parameters.subdirectory >>' - arguments: | - --acl public-read \ - --cache-control << parameters.cache-control >> \ - --recursive \ - --profile production \ -jobs: - # generate bundles - build: - docker: - - image: circleci/node:14.5 - working_directory: ~/answers - steps: - - setup-workspace - - run: npm run build - - persist_to_workspace: - root: . - paths: - - dist - - .circleci - # generate bundles for all languages and locales - build_i18n: - docker: - - image: circleci/node:14.5 - working_directory: ~/answers - steps: - - setup-workspace - - run: npm run build-locales - - persist_to_workspace: - root: . - paths: - - dist - - .circleci - build_search_bar: - docker: - - image: circleci/node:14.5 - working_directory: ~/answers - steps: - - setup-workspace - - run: npm run build-search-bar-only - - persist_to_workspace: - root: . - paths: - - dist - - .circleci - # run the jest unit tests - unit_test: - docker: - - image: circleci/node:14.5 - resource_class: xlarge - working_directory: ~/answers - steps: - - setup-workspace - - attach_workspace: - at: ~/answers - - run: npm run test - # run acceptance tests directly in the container - headless_acceptance_test: - docker: - - image: circleci/node:14.5-browsers - working_directory: ~/answers - steps: - - setup-workspace - - attach_workspace: - at: ~/answers - - run: ./.circleci/run_headless_acceptance.sh - headless_acceptance_test_search_bar: - docker: - - image: circleci/node:14.5-browsers - working_directory: ~/answers - steps: - - setup-workspace - - attach_workspace: - at: ~/answers - - run: - name: Search Bar Acceptance Tests - command: npx testcafe -c 3 "chrome:headless,firefox:headless" --config-file ./.circleci/testcafe_search_bar.json -q - # run the browserstack testcafe acceptance tests - browserstack_acceptance_test: - docker: - - image: circleci/node:14.5 - working_directory: ~/answers - steps: - - setup-workspace - - attach_workspace: - at: ~/answers - - run: ./.circleci/run_browserstack_acceptance.sh - # verify all translations are present - translation_test: - docker: - - image: circleci/node:14.5 - working_directory: ~/answers - steps: - - setup-workspace - - attach_workspace: - at: ~/answers - - run: - name: Verify translation files - command: | - sudo apt-get install -qq gettext - ./.circleci/run_translation_verification.sh - # deploys assets to an uncached folder in the S3 bucket named by branch - deploy_branch: - docker: - - image: circleci/python:2.7 - working_directory: ~/answers - steps: - - run: - name: "Setup branch formatting, replace / with -" - command: echo 'export FORMATTED_CIRCLE_BRANCH=$(echo ${CIRCLE_BRANCH} | sed "s/\//-/g")' >> $BASH_ENV - - deploy-to-aws: - subdirectory: '/dev/${FORMATTED_CIRCLE_BRANCH}' - # deploys assets to a long-lived-cache folder in the S3 bucket named by hash - deploy_canary: - docker: - - image: circleci/python:2.7 - working_directory: ~/answers - steps: - - deploy-to-aws: - subdirectory: '/canary/${CIRCLE_SHA1}' - cache-control: 'max-age=31536000' - - deploy-to-aws: - subdirectory: '/canary/latest' - # deploys assets to a long-lived-cache folder in the S3 bucket named by release tag - deploy_version: - docker: - - image: circleci/python:2.7 - working_directory: ~/answers - steps: - - deploy-to-aws: - subdirectory: '/${CIRCLE_TAG}' - cache-control: 'max-age=31536000' - - run: - name: "Get major and minor version substrings" - command: | - echo "export MINOR_VERSION="$(echo "${CIRCLE_TAG}" | cut -d '.' -f 1,2)"" >> $BASH_ENV - echo "export MAJOR_VERSION="$(echo "${CIRCLE_TAG}" | cut -d '.' -f 1)"" >> $BASH_ENV - - deploy-to-aws: - subdirectory: '/${MINOR_VERSION}' - cache-control: 'max-age=43200' - - deploy-to-aws: - subdirectory: '/${MAJOR_VERSION}' - cache-control: 'max-age=43200' - # deploys assets to a long-lived-cache folder in the S3 bucket named by release tag - deploy_search_bar_version: - docker: - - image: circleci/python:2.7 - working_directory: ~/answers - steps: - - deploy-to-aws: - deploy-bucket: 'answers-search-bar' - subdirectory: '/${CIRCLE_TAG##search-bar-}' - cache-control: 'max-age=31536000' - - run: - name: "Get major and minor version substrings" - command: | - echo "export MINOR_VERSION="$(echo "${CIRCLE_TAG##search-bar-}" | cut -d '.' -f 1,2)"" >> $BASH_ENV - echo "export MAJOR_VERSION="$(echo "${CIRCLE_TAG##search-bar-}" | cut -d '.' -f 1)"" >> $BASH_ENV - - deploy-to-aws: - deploy-bucket: 'answers-search-bar' - subdirectory: '/${MINOR_VERSION}' - cache-control: 'max-age=43200' - - deploy-to-aws: - deploy-bucket: 'answers-search-bar' - subdirectory: '/${MAJOR_VERSION}' - cache-control: 'max-age=43200' -workflows: - version: 2 - build_and_deploy: - jobs: - - build: - filters: - branches: - ignore: - - develop - - master - - /^support\/.*/ - - /^hotfix\/.*/ - - /^feature\/.*-i18n/ - - /^release\/.*/ - - unit_test: - requires: - - build - - headless_acceptance_test: - requires: - - build - - browserstack_acceptance_test: - requires: - - build - - translation_test: - requires: - - build - - deploy_branch: - requires: - - unit_test - - browserstack_acceptance_test - - headless_acceptance_test - build_and_deploy_i18n: - jobs: - - build_i18n: - filters: - branches: - only: - - develop - - /^support\/.*/ - - /^hotfix\/.*/ - - /^feature\/.*-i18n/ - - /^release\/.*/ - - unit_test: - requires: - - build_i18n - - headless_acceptance_test: - requires: - - build_i18n - - browserstack_acceptance_test: - requires: - - build_i18n - - translation_test: - requires: - - build_i18n - - deploy_branch: - filters: - branches: - ignore: - - develop - requires: - - unit_test - - browserstack_acceptance_test - - headless_acceptance_test - - translation_test - - deploy_canary: - filters: - branches: - only: develop - requires: - - unit_test - - headless_acceptance_test - - browserstack_acceptance_test - build_and_deploy_hold: - jobs: - - build_i18n: - filters: - tags: - only: /^v.*/ - branches: - ignore: /.*/ - - unit_test: - filters: - tags: - only: /^v.*/ - requires: - - build_i18n - - headless_acceptance_test: - filters: - tags: - only: /^v.*/ - requires: - - build_i18n - - browserstack_acceptance_test: - filters: - tags: - only: /^v.*/ - requires: - - build_i18n - - translation_test: - filters: - tags: - only: /^v.*/ - requires: - - build_i18n - - hold: - type: approval - filters: - tags: - only: /^v.*/ - requires: - - unit_test - - browserstack_acceptance_test - - headless_acceptance_test - - translation_test - - deploy_version: - filters: - tags: - only: /^v.*/ - requires: - - hold - build_and_deploy_search_bar: - jobs: - - build_search_bar: - filters: - tags: - only: /^search-bar-v.*/ - branches: - ignore: /.*/ - - headless_acceptance_test_search_bar: - filters: - tags: - only: /^search-bar-v.*/ - requires: - - build_search_bar - - translation_test: - filters: - tags: - only: /^search-bar-v.*/ - requires: - - build_search_bar - - hold: - type: approval - filters: - tags: - only: /^search-bar-v.*/ - requires: - - headless_acceptance_test_search_bar - - translation_test - - deploy_search_bar_version: - filters: - tags: - only: /^search-bar-v.*/ - requires: - - hold diff --git a/.circleci/run_browserstack_acceptance.sh b/.circleci/run_browserstack_acceptance.sh deleted file mode 100755 index 57f36952a..000000000 --- a/.circleci/run_browserstack_acceptance.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash -export BROWSERSTACK_USE_AUTOMATE="1" -export BROWSERSTACK_PROJECT_NAME="Answers SDK" -export BROWSERSTACK_BUILD_ID="${CIRCLE_BRANCH} - ${CIRCLE_BUILD_NUM}" -COMMIT_MSG_TITLE=$(git log -n 1 --pretty=format:%s) -export BROWSERSTACK_TEST_RUN_NAME=$COMMIT_MSG_TITLE - -if [[ $CIRCLE_BRANCH == release/* - || $CIRCLE_BRANCH == hotfix/* - || $CIRCLE_BRANCH == master - || $CIRCLE_BRANCH == support/* ]] -then - npx testcafe "browserstack:ie@11.0,browserstack:safari" --config-file ./.circleci/testcafe.json -q -else - npx testcafe -c 2 "browserstack:ie@11.0" --config-file ./.circleci/testcafe.json -q -fi diff --git a/.circleci/run_headless_acceptance.sh b/.circleci/run_headless_acceptance.sh deleted file mode 100755 index a7facb38e..000000000 --- a/.circleci/run_headless_acceptance.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash - -if [[ $CIRCLE_BRANCH == release/* - || $CIRCLE_BRANCH == hotfix/* - || $CIRCLE_BRANCH == master - || $CIRCLE_BRANCH == support/* ]] -then - npx testcafe -c 3 "chrome:headless,firefox:headless" --config-file ./.circleci/testcafe.json -q -else - npx testcafe -c 3 "chrome:headless" --config-file ./.circleci/testcafe.json -q -fi diff --git a/.github/run_browserstack_acceptance.sh b/.github/run_browserstack_acceptance.sh new file mode 100755 index 000000000..ab418324f --- /dev/null +++ b/.github/run_browserstack_acceptance.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +export BROWSERSTACK_USE_AUTOMATE="1" +export BROWSERSTACK_PROJECT_NAME="Answers SDK" +export BROWSERSTACK_BUILD_ID="${GITHUB_REF_NAME} - ${GITHUB_RUN_ID}" +COMMIT_MSG_TITLE=$(git log -n 1 --pretty=format:%s) +export BROWSERSTACK_TEST_RUN_NAME=$COMMIT_MSG_TITLE + +if [[ $GITHUB_REF_NAME == release/* + || $GITHUB_REF_NAME == hotfix/* + || $GITHUB_REF_NAME == master + || $GITHUB_REF_NAME == support/* ]] +then + npx testcafe "browserstack:ie@11.0,browserstack:safari" --config-file ./.github/testcafe.json -q +else + npx testcafe -c 2 "browserstack:ie@11.0" --config-file ./.github/testcafe.json -q +fi diff --git a/.github/run_headless_acceptance.sh b/.github/run_headless_acceptance.sh new file mode 100755 index 000000000..c79243666 --- /dev/null +++ b/.github/run_headless_acceptance.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +if [[ $GITHUB_REF_NAME == release/* + || $GITHUB_REF_NAME == hotfix/* + || $GITHUB_REF_NAME == master + || $GITHUB_REF_NAME == support/* ]] +then + npx testcafe -c 3 "chrome:headless,firefox:headless" --config-file ./.github/testcafe.json -q +else + npx testcafe -c 3 "chrome:headless" --config-file ./.github/testcafe.json -q +fi diff --git a/.circleci/run_translation_verification.sh b/.github/run_translation_verification.sh similarity index 77% rename from .circleci/run_translation_verification.sh rename to .github/run_translation_verification.sh index aeea97903..48ab8b5cb 100755 --- a/.circleci/run_translation_verification.sh +++ b/.github/run_translation_verification.sh @@ -16,14 +16,19 @@ fi # Verify that translations are present for all languages cd conf/i18n/translations -if [[ $CIRCLE_BRANCH == release/* - || $CIRCLE_BRANCH == hotfix/* - || $CIRCLE_BRANCH == master - || $CIRCLE_BRANCH == support/* ]] + +exit_code=0 +if [[ $GITHUB_REF_NAME == release/* + || $GITHUB_REF_NAME == hotfix/* + || $GITHUB_REF_NAME == master + || $GITHUB_REF_NAME == support/* ]] then for po_file in *.po - do msgcmp $po_file messages.pot + do + msgcmp $po_file messages.pot || exit_code=1 done else echo "Skipping the verification that all translations are present" -fi \ No newline at end of file +fi + +exit $exit_code diff --git a/.circleci/testcafe.json b/.github/testcafe.json similarity index 100% rename from .circleci/testcafe.json rename to .github/testcafe.json diff --git a/.circleci/testcafe_search_bar.json b/.github/testcafe_search_bar.json similarity index 100% rename from .circleci/testcafe_search_bar.json rename to .github/testcafe_search_bar.json diff --git a/.github/workflows/acceptance.yml b/.github/workflows/acceptance.yml new file mode 100644 index 000000000..6ca903caf --- /dev/null +++ b/.github/workflows/acceptance.yml @@ -0,0 +1,49 @@ +name: Run acceptance tests + +on: + workflow_call: + secrets: + BROWSERSTACK_USERNAME: + required: true + BROWSERSTACK_ACCESS_KEY: + required: true + +jobs: + headless_acceptance: + name: Headless Acceptance + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Use Node.js 14 + uses: actions/setup-node@v2 + with: + node-version: 14 + cache: 'npm' + - run: npm ci + - name: Download build-output artifact + uses: actions/download-artifact@v2 + with: + name: build-output + path: dist/ + - run: ./.github/run_headless_acceptance.sh + + browserstack_acceptance: + name: Browserstack Acceptance + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Use Node.js 14 + uses: actions/setup-node@v2 + with: + node-version: 14 + cache: 'npm' + - run: npm ci + - name: Download build-output artifact + uses: actions/download-artifact@v2 + with: + name: build-output + path: dist/ + - run: ./.github/run_browserstack_acceptance.sh + env: + BROWSERSTACK_USERNAME: ${{ secrets.BROWSERSTACK_USERNAME }} + BROWSERSTACK_ACCESS_KEY: ${{ secrets.BROWSERSTACK_ACCESS_KEY }} diff --git a/.github/workflows/acceptance_search_bar.yml b/.github/workflows/acceptance_search_bar.yml new file mode 100644 index 000000000..f4ca7d8b0 --- /dev/null +++ b/.github/workflows/acceptance_search_bar.yml @@ -0,0 +1,28 @@ +name: Run acceptance tests + +on: + workflow_call: + secrets: + BROWSERSTACK_USERNAME: + required: true + BROWSERSTACK_ACCESS_KEY: + required: true + +jobs: + headless_acceptance: + name: Headless Acceptance + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Use Node.js 14 + uses: actions/setup-node@v2 + with: + node-version: 14 + cache: 'npm' + - run: npm ci + - name: Download build-output artifact + uses: actions/download-artifact@v2 + with: + name: build-output + path: dist/ + - run: npx testcafe -c 3 "chrome:headless,firefox:headless" --config-file ./.github/testcafe_search_bar.json -q diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 000000000..164ae5588 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,28 @@ +name: Build Answers assets + +on: + workflow_call: + inputs: + build_script: + required: false + default: build + type: string + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Use Node.js 14 + uses: actions/setup-node@v2 + with: + node-version: 14 + cache: 'npm' + - run: npm ci + - run: npm run ${{ inputs.build_script }} + - name: Create build-output artifact + uses: actions/upload-artifact@v2 + with: + name: build-output + path: dist/ \ No newline at end of file diff --git a/.github/workflows/build_and_deploy.yml b/.github/workflows/build_and_deploy.yml new file mode 100644 index 000000000..d3edbf90f --- /dev/null +++ b/.github/workflows/build_and_deploy.yml @@ -0,0 +1,49 @@ +name: Build and deploy + +on: + push: + branches-ignore: + - develop + - master + - support/** + - hotfix/** + - feature/**-i18n + - release/** + +jobs: + call_build: + uses: ./.github/workflows/build.yml + + call_unit_test: + uses: ./.github/workflows/unit_test.yml + needs: call_build + + call_misc_tests: + uses: ./.github/workflows/miscellaneous_tests.yml + + call_format_branch_name: + uses: ./.github/workflows/format_branch_name.yml + + call_acceptance: + uses: ./.github/workflows/acceptance.yml + needs: call_build + secrets: + BROWSERSTACK_USERNAME: ${{ secrets.BROWSERSTACK_USERNAME }} + BROWSERSTACK_ACCESS_KEY: ${{ secrets.BROWSERSTACK_ACCESS_KEY }} + + call_deploy: + needs: + - call_unit_test + - call_format_branch_name + - call_acceptance + - call_misc_tests + uses: ./.github/workflows/deploy.yml + with: + directory: dev/${{ needs.call_format_branch_name.outputs.formatted_branch }} + secrets: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + +concurrency: + group: ci-build-and-deploy-${{ github.ref }}-1 + cancel-in-progress: true diff --git a/.github/workflows/build_and_deploy_hold.yml b/.github/workflows/build_and_deploy_hold.yml new file mode 100644 index 000000000..83b8991cf --- /dev/null +++ b/.github/workflows/build_and_deploy_hold.yml @@ -0,0 +1,80 @@ +name: Build and deploy with a hold state + +on: + push: + tags: + - 'v*' + +jobs: + call_build: + uses: ./.github/workflows/build.yml + with: + build_script: build-locales + + call_unit_test: + uses: ./.github/workflows/unit_test.yml + needs: call_build + + call_misc_tests: + uses: ./.github/workflows/miscellaneous_tests.yml + + call_acceptance: + uses: ./.github/workflows/acceptance.yml + needs: call_build + secrets: + BROWSERSTACK_USERNAME: ${{ secrets.BROWSERSTACK_USERNAME }} + BROWSERSTACK_ACCESS_KEY: ${{ secrets.BROWSERSTACK_ACCESS_KEY }} + + call_extract_versions: + uses: ./.github/workflows/extract_versions.yml + + call_should_deploy_major_version: + uses: ./.github/workflows/should_deploy_major_version.yml + + call_deploy_full_version: + needs: + - call_unit_test + - call_acceptance + - call_extract_versions + - call_misc_tests + uses: ./.github/workflows/deploy_hold.yml + with: + directory: ${{ github.ref_name }} + cache-control: 'max-age=31536000' + secrets: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + + call_deploy_major_version: + needs: + - call_unit_test + - call_acceptance + - call_extract_versions + - call_misc_tests + - call_should_deploy_major_version + if: ${{ needs.call_should_deploy_major_version.outputs.should_deploy_major_version }} + uses: ./.github/workflows/deploy_hold.yml + with: + directory: ${{ needs.call_extract_versions.outputs.major_version }} + cache-control: 'max-age=43200' + secrets: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + + call_deploy_minor_version: + needs: + - call_unit_test + - call_acceptance + - call_extract_versions + - call_misc_tests + uses: ./.github/workflows/deploy_hold.yml + with: + directory: ${{ needs.call_extract_versions.outputs.minor_version }} + cache-control: 'max-age=43200' + secrets: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + +concurrency: + group: ci-build-and-deploy-hold-${{ github.ref }}-1 + cancel-in-progress: true \ No newline at end of file diff --git a/.github/workflows/build_and_deploy_i18n.yml b/.github/workflows/build_and_deploy_i18n.yml new file mode 100644 index 000000000..63e9d5b16 --- /dev/null +++ b/.github/workflows/build_and_deploy_i18n.yml @@ -0,0 +1,80 @@ +name: Build and deploy i18n + +on: + push: + branches: + - develop + - support/** + - hotfix/** + - feature/**-i18n + - release/** + +jobs: + call_build: + uses: ./.github/workflows/build.yml + with: + build_script: build-locales + + call_unit_test: + uses: ./.github/workflows/unit_test.yml + needs: call_build + + call_misc_tests: + uses: ./.github/workflows/miscellaneous_tests.yml + + call_format_branch_name: + uses: ./.github/workflows/format_branch_name.yml + + call_acceptance: + uses: ./.github/workflows/acceptance.yml + needs: call_build + secrets: + BROWSERSTACK_USERNAME: ${{ secrets.BROWSERSTACK_USERNAME }} + BROWSERSTACK_ACCESS_KEY: ${{ secrets.BROWSERSTACK_ACCESS_KEY }} + + call_deploy: + if: github.ref_name != 'develop' + needs: + - call_unit_test + - call_format_branch_name + - call_acceptance + - call_misc_tests + uses: ./.github/workflows/deploy.yml + with: + directory: dev/${{ needs.call_format_branch_name.outputs.formatted_branch }} + secrets: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + + call_deploy_canary: + if: github.ref_name == 'develop' + needs: + - call_unit_test + - call_format_branch_name + - call_acceptance + - call_misc_tests + uses: ./.github/workflows/deploy.yml + with: + directory: canary/latest + secrets: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + + call_deploy_canary_sha: + if: github.ref_name == 'develop' + needs: + - call_unit_test + - call_format_branch_name + - call_acceptance + - call_misc_tests + uses: ./.github/workflows/deploy.yml + with: + directory: canary/${{ github.sha }} + cache-control: 'max-age=31536000' + secrets: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + +concurrency: + group: ci-build-and-deploy-i18n-${{ github.ref }}-1 + cancel-in-progress: true \ No newline at end of file diff --git a/.github/workflows/build_and_deploy_search_bar.yml b/.github/workflows/build_and_deploy_search_bar.yml new file mode 100644 index 000000000..c97c6883a --- /dev/null +++ b/.github/workflows/build_and_deploy_search_bar.yml @@ -0,0 +1,80 @@ +name: Build and deploy search bar + +on: + push: + tags: + - 'search-bar-v*' + +jobs: + call_build: + uses: ./.github/workflows/build.yml + with: + build_script: build-search-bar-only + + call_misc_tests: + uses: ./.github/workflows/miscellaneous_tests.yml + + call_acceptance_search_bar: + uses: ./.github/workflows/acceptance_search_bar.yml + needs: call_build + secrets: + BROWSERSTACK_USERNAME: ${{ secrets.BROWSERSTACK_USERNAME }} + BROWSERSTACK_ACCESS_KEY: ${{ secrets.BROWSERSTACK_ACCESS_KEY }} + + call_extract_versions: + uses: ./.github/workflows/extract_versions.yml + with: + ignore_prefix: search-bar- + + call_should_deploy_major_version: + uses: ./.github/workflows/should_deploy_major_version.yml + with: + ignore_prefix: search-bar- + + call_deploy_full_version: + needs: + - call_acceptance_search_bar + - call_extract_versions + - call_misc_tests + uses: ./.github/workflows/deploy_hold.yml + with: + bucket: answers-search-bar + directory: ${{ needs.call_extract_versions.outputs.full_version }} + cache-control: 'max-age=31536000' + secrets: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + + call_deploy_major_version: + needs: + - call_acceptance_search_bar + - call_extract_versions + - call_misc_tests + - call_should_deploy_major_version + if: ${{ needs.call_should_deploy_major_version.outputs.should_deploy_major_version }} + uses: ./.github/workflows/deploy_hold.yml + with: + bucket: answers-search-bar + directory: ${{ needs.call_extract_versions.outputs.major_version }} + cache-control: 'max-age=43200' + secrets: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + + call_deploy_minor_version: + needs: + - call_acceptance_search_bar + - call_extract_versions + - call_misc_tests + uses: ./.github/workflows/deploy_hold.yml + with: + bucket: answers-search-bar + directory: ${{ needs.call_extract_versions.outputs.minor_version }} + cache-control: 'max-age=43200' + secrets: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + +concurrency: + group: ci-build-and-deploy-search-bars-${{ github.ref }}-1 + cancel-in-progress: true \ No newline at end of file diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 000000000..692c468a0 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,45 @@ +name: Deploy assets to AWS S3 + +on: + workflow_call: + inputs: + bucket: + required: false + type: string + default: answers + directory: + required: true + type: string + cache-control: + required: false + type: string + default: no-cache + secrets: + AWS_ACCESS_KEY_ID: + required: true + AWS_SECRET_ACCESS_KEY: + required: true + +jobs: + deploy: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Download build-output artifact + uses: actions/download-artifact@v2 + with: + name: build-output + path: dist/ + - name: Configure AWS Credentials + uses: aws-actions/configure-aws-credentials@v1 + with: + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + aws-region: us-east-1 + - name: Deploy to S3 + run: | + aws s3 cp ./dist/ s3://assets.sitescdn.net/${{ inputs.bucket }}/${{ inputs.directory }} \ + --acl public-read \ + --recursive \ + --cache-control ${{ inputs.cache-control }} \ No newline at end of file diff --git a/.github/workflows/deploy_hold.yml b/.github/workflows/deploy_hold.yml new file mode 100644 index 000000000..842c23212 --- /dev/null +++ b/.github/workflows/deploy_hold.yml @@ -0,0 +1,45 @@ +name: Deploy assets to AWS S3 with hold state setup in github's production environment + +on: + workflow_call: + inputs: + bucket: + required: false + type: string + default: answers + directory: + required: true + type: string + cache-control: + required: false + type: string + default: no-cache + secrets: + AWS_ACCESS_KEY_ID: + required: true + AWS_SECRET_ACCESS_KEY: + required: true + +jobs: + deploy: + runs-on: ubuntu-latest + environment: production # sets in github repo with reiewer requirement protection rule + steps: + - uses: actions/checkout@v2 + - name: Download build-output artifact + uses: actions/download-artifact@v2 + with: + name: build-output + path: dist/ + - name: Configure AWS Credentials + uses: aws-actions/configure-aws-credentials@v1 + with: + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + aws-region: us-east-1 + - name: Deploy to S3 + run: | + aws s3 cp ./dist/ s3://assets.sitescdn.net/${{ inputs.bucket }}/${{ inputs.directory }} \ + --acl public-read \ + --recursive \ + --cache-control ${{ inputs.cache-control }} \ No newline at end of file diff --git a/.github/workflows/extract_versions.yml b/.github/workflows/extract_versions.yml new file mode 100644 index 000000000..216d4b032 --- /dev/null +++ b/.github/workflows/extract_versions.yml @@ -0,0 +1,37 @@ +name: Extract versions + +on: + workflow_call: + inputs: + ignore_prefix: + required: false + default: '' + type: string + outputs: + major_version: + value: ${{ jobs.extract_versions.outputs.major_version }} + minor_version: + value: ${{ jobs.extract_versions.outputs.minor_version }} + full_version: + value: ${{ jobs.extract_versions.outputs.full_version }} + +jobs: + extract_versions: + runs-on: ubuntu-latest + outputs: + minor_version: ${{ steps.vars.outputs.minor_version }} + major_version: ${{ steps.vars.outputs.major_version }} + full_version: ${{ steps.vars.outputs.full_version }} + steps: + - name: extract major and minor version substrings + id: vars + run: | + MAJOR_VERSION="$(echo "${GITHUB_REF_NAME##${{ inputs.ignore_prefix }}}" | cut -d '.' -f 1)" + echo "Major version: $MAJOR_VERSION" + echo ::set-output name=major_version::${MAJOR_VERSION} + MINOR_VERSION="$(echo "${GITHUB_REF_NAME##${{ inputs.ignore_prefix }}}" | cut -d '.' -f 1,2)" + echo "Minor version: $MINOR_VERSION" + echo ::set-output name=minor_version::${MINOR_VERSION} + FULL_VERSION="${GITHUB_REF_NAME##${{ inputs.ignore_prefix }}}" + echo "Full version: $FULL_VERSION" + echo ::set-output name=full_version::${FULL_VERSION} \ No newline at end of file diff --git a/.github/workflows/format_branch_name.yml b/.github/workflows/format_branch_name.yml new file mode 100644 index 000000000..b45991286 --- /dev/null +++ b/.github/workflows/format_branch_name.yml @@ -0,0 +1,21 @@ +name: Format branch name to use as part of s3 directory path + +on: + workflow_call: + outputs: + formatted_branch: + description: "formatted branch name" + value: ${{ jobs.format_branch_name.outputs.formatted_branch }} + +jobs: + format_branch_name: + runs-on: ubuntu-latest + outputs: + formatted_branch: ${{ steps.vars.outputs.formatted_branch }} + steps: + - name: Format branch name # replace '/' with '-' + id: vars + run: | + FORMATTED_BRANCH="$(echo ${GITHUB_REF_NAME} | sed "s/\//-/g")" + echo $FORMATTED_BRANCH + echo ::set-output name=formatted_branch::${FORMATTED_BRANCH} \ No newline at end of file diff --git a/.github/workflows/miscellaneous_tests.yml b/.github/workflows/miscellaneous_tests.yml new file mode 100644 index 000000000..2cd346a6c --- /dev/null +++ b/.github/workflows/miscellaneous_tests.yml @@ -0,0 +1,19 @@ +name: Run miscellaneous tests + +on: + workflow_call: + +jobs: + translation_test: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Use Node.js 14 + uses: actions/setup-node@v2 + with: + node-version: 14 + cache: 'npm' + - run: npm ci + - run: sudo apt-get install -qq gettext + - run: ./.github/run_translation_verification.sh \ No newline at end of file diff --git a/.github/workflows/should_deploy_major_version.yml b/.github/workflows/should_deploy_major_version.yml new file mode 100644 index 000000000..4f46a0235 --- /dev/null +++ b/.github/workflows/should_deploy_major_version.yml @@ -0,0 +1,36 @@ +name: Should deploy major version + +on: + workflow_call: + inputs: + ignore_prefix: + required: false + default: '' + type: string + outputs: + should_deploy_major_version: + value: ${{ jobs.should_deploy_major_version.outputs.should_deploy_major_version }} + +jobs: + should_deploy_major_version: + runs-on: ubuntu-latest + outputs: + should_deploy_major_version: ${{ steps.vars.outputs.should_deploy_major_version }} + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: allow for major version deployment if the next minor version from current tag does not exist + id: vars + run: | + MINOR_VERSION=$(echo "${GITHUB_REF_NAME##${{ inputs.ignore_prefix }}}" | cut -d '.' -f 2) + MAJOR_VERSION=$(echo "${GITHUB_REF_NAME##${{ inputs.ignore_prefix }}}" | cut -d '.' -f 1) + NEXT_MINOR_VERSION=$(( $MINOR_VERSION + 1 )) + OUTPUT=$(git tag --list "$MAJOR_VERSION.$NEXT_MINOR_VERSION.*") + if [ -z $OUTPUT ] + then + echo 'Major version should be deployed.' + echo ::set-output name=should_deploy_major_version::true + else + echo 'Major version should not be deployed.' + fi \ No newline at end of file diff --git a/.github/workflows/unit_test.yml b/.github/workflows/unit_test.yml new file mode 100644 index 000000000..b20af84d5 --- /dev/null +++ b/.github/workflows/unit_test.yml @@ -0,0 +1,23 @@ +name: Run unit tests + +on: + workflow_call: + +jobs: + unit_tests: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Use Node.js 14 + uses: actions/setup-node@v2 + with: + node-version: 14 + cache: 'npm' + - run: npm ci + - name: Download build-output artifact + uses: actions/download-artifact@v2 + with: + name: build-output + path: dist/ + - run: npm run test \ No newline at end of file diff --git a/package.json b/package.json index e004fdb8f..703ce1c43 100644 --- a/package.json +++ b/package.json @@ -120,7 +120,7 @@ "docs": "jsdoc -R README.md -d docs/ -r src/", "lint": "eslint .", "test": "eslint . && stylelint src/**/*.scss && cross-env NODE_ICU_DATA=node_modules/full-icu jest", - "acceptance": "testcafe safari,chrome --config-file ./.circleci/testcafe.json", + "acceptance": "testcafe safari,chrome --config-file ./.github/testcafe.json", "wcag": "./tests/acceptance/wcag/index.js", "size": "size-limit", "fix": "eslint . --fix", diff --git a/tests/acceptance/acceptancesuites/facetsonload.js b/tests/acceptance/acceptancesuites/facetsonload.js index 4c8bbee0c..db4a6fe07 100644 --- a/tests/acceptance/acceptancesuites/facetsonload.js +++ b/tests/acceptance/acceptancesuites/facetsonload.js @@ -41,6 +41,7 @@ test('Facets work with back/forward navigation and page refresh', async t => { const state1 = { c_puppyPreference: [], c_employeeDepartment: [{ c_employeeDepartment: { $eq: 'Client Delivery [SO]' } }], + c_popularity: [], languages: [], specialities: [] }; @@ -68,6 +69,7 @@ test('Facets work with back/forward navigation and page refresh', async t => { { c_employeeDepartment: { $eq: 'Client Delivery [SO]' } }, { c_employeeDepartment: { $eq: 'Technology' } } ], + c_popularity: [], languages: [], specialities: [] }; diff --git a/tests/acceptance/blocks/filtersearchcomponent.js b/tests/acceptance/blocks/filtersearchcomponent.js index 373283b77..bb90c799e 100644 --- a/tests/acceptance/blocks/filtersearchcomponent.js +++ b/tests/acceptance/blocks/filtersearchcomponent.js @@ -23,6 +23,6 @@ export default class FilterSearchComponentBlock { .typeText(this._input, displayValue) .pressKey('space') .wait(500) - .click(this._selector.find('.js-yext-autocomplete-option').withText(displayValue)); + .click(this._selector.find('.js-yext-autocomplete-option').withExactText(displayValue)); } } diff --git a/tests/acceptance/fixtures/html/facets.html b/tests/acceptance/fixtures/html/facets.html index 9a4858dc4..824f4ac90 100644 --- a/tests/acceptance/fixtures/html/facets.html +++ b/tests/acceptance/fixtures/html/facets.html @@ -46,6 +46,8 @@ verticalKey: 'people', }, onReady: function () { + this.setGeolocation(38.8955, -77.0699); + this.addComponent('SearchBar', { container: '.search-bar-container', clearButton: true, diff --git a/tests/acceptance/fixtures/html/facetsonload.html b/tests/acceptance/fixtures/html/facetsonload.html index 453aa0859..fd6c936e6 100644 --- a/tests/acceptance/fixtures/html/facetsonload.html +++ b/tests/acceptance/fixtures/html/facetsonload.html @@ -46,6 +46,8 @@ verticalKey: 'people', }, onReady: function () { + this.setGeolocation(38.8955, -77.0699); + this.addComponent('SearchBar', { container: '.search-bar-container', clearButton: true, diff --git a/tests/acceptance/fixtures/html/filterbox.html b/tests/acceptance/fixtures/html/filterbox.html index cfe61b93b..f41ba85f8 100644 --- a/tests/acceptance/fixtures/html/filterbox.html +++ b/tests/acceptance/fixtures/html/filterbox.html @@ -49,6 +49,8 @@ defaultInitialSearch: '' }, onReady: function () { + this.setGeolocation(38.8955, -77.0699); + this.addComponent('SearchBar', { container: '.search-bar-container', clearButton: true, diff --git a/tests/acceptance/fixtures/html/no-unsafe-eval.html b/tests/acceptance/fixtures/html/no-unsafe-eval.html index 7dacc5ebe..839bb768f 100644 --- a/tests/acceptance/fixtures/html/no-unsafe-eval.html +++ b/tests/acceptance/fixtures/html/no-unsafe-eval.html @@ -27,6 +27,8 @@ defaultInitialSearch: 'virginia' }, onReady: function () { + this.setGeolocation(38.8955, -77.0699); + this.addComponent('SearchBar', { container: '.search-bar-container', verticalKey: 'people' diff --git a/tests/acceptance/fixtures/html/searchbaronly.html b/tests/acceptance/fixtures/html/searchbaronly.html index 70f448944..18d9862cf 100644 --- a/tests/acceptance/fixtures/html/searchbaronly.html +++ b/tests/acceptance/fixtures/html/searchbaronly.html @@ -19,6 +19,8 @@ experienceVersion: 'PRODUCTION', templateBundle: TemplateBundle.default, onReady: function() { + this.setGeolocation(38.8955, -77.0699); + this.addComponent('SearchBar', { container: '.search-bar-container', clearButton: true, diff --git a/tests/acceptance/fixtures/html/universal.html b/tests/acceptance/fixtures/html/universal.html index 59cc8bcad..808d3f59a 100644 --- a/tests/acceptance/fixtures/html/universal.html +++ b/tests/acceptance/fixtures/html/universal.html @@ -21,6 +21,8 @@ experienceVersion: 'PRODUCTION', templateBundle: TemplateBundle.default, onReady: function() { + this.setGeolocation(38.8955, -77.0699); + this.addComponent('SearchBar', { container: '.search-bar-container', clearButton: true, diff --git a/tests/acceptance/fixtures/html/universalinitialsearch.html b/tests/acceptance/fixtures/html/universalinitialsearch.html index 91536021e..bcd47f8a6 100644 --- a/tests/acceptance/fixtures/html/universalinitialsearch.html +++ b/tests/acceptance/fixtures/html/universalinitialsearch.html @@ -25,6 +25,8 @@ defaultInitialSearch: '' }, onReady: function () { + this.setGeolocation(38.8955, -77.0699); + this.addComponent('SearchBar', { container: '.search-bar-container', clearButton: true, diff --git a/tests/acceptance/fixtures/html/vertical.html b/tests/acceptance/fixtures/html/vertical.html index b615dd40d..ceca68c3a 100644 --- a/tests/acceptance/fixtures/html/vertical.html +++ b/tests/acceptance/fixtures/html/vertical.html @@ -31,6 +31,8 @@ displayAllResults: true }, onReady: function() { + this.setGeolocation(38.8955, -77.0699); + this.addComponent('SearchBar', { container: '.search-bar-container', verticalKey:'KM',