diff --git a/.circleci/config.yml b/.circleci/config.yml index 1659eed75e..c4b465540a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -3,6 +3,58 @@ orbs: k8s: circleci/kubernetes@0.7.0 slack: circleci/slack@3.4.2 commands: + generate_app_id: + description: "Capture Vercel preview URL" + steps: + - name: Capture Vercel preview URL + id: vercel_preview_url + uses: binary-com/vercel-preview-url-action@v1.0.5 + with: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + preview_url_regexp: \[Visit Preview\]\((.*?.sx)\) + - name: Generate Binary Bot ID for deployment Preview URL + id: generate_app_id + uses: binary-com/binary-bot-id-action@v1 + with: + DERIV_API_TOKEN: ${{ secrets.DERIV_API_TOKEN }} + DERIV_APP_ID: ${{ secrets.DERIV_APP_ID }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + max_retries: 5 + vercel_preview_url: ${{ steps.vercel_preview_url.outputs.vercel_preview_url }} + - name: Comment on pull request with App ID and URLs + id: sticky_comment_on_pr + if: steps.generate_app_id.outputs.should_post_comment + uses: marocchino/sticky-pull-request-comment@v1 + with: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + header: binary-bot-id-action + number: ${{github.event.issue.number}} + message: | + A production App ID was automatically generated for this PR. ([log](https://github.com/${{github.repository}}/actions/runs/${{github.run_id}}) + - **PR**: [${{ steps.generate_app_id.outputs.pr_url }}](${{ steps.generate_app_id.outputs.pr_url }}) + - **URLs**: + - **w/ App ID + Server**: ${{ steps.vercel_preview_url.outputs.vercel_preview_url }}?qa_server=frontend.binaryws.com&app_id=${{ steps.generate_app_id.outputs.app_id }} + - **Original**: ${{ steps.vercel_preview_url.outputs.vercel_preview_url }} + - **App ID**: `${{ steps.generate_app_id.outputs.app_id }} +
+ Click here to copy & paste above information. + - name: Store generated URL in artifact + run: echo "HOME_URL=${{ steps.vercel_preview_url.outputs.vercel_preview_url }}?qa_server=frontend.binaryws.com&app_id=${{ steps.generate_app_id.outputs.app_id }}" >> ${{ github.workspace }}/url.txt + - name: Upload artifact + uses: actions/upload-artifact@master + with: + name: generated_url + path: ${{ github.workspace }}/url.txt + retention-days: 1 + git_checkout_from_cache: description: "Git checkout and save cache" steps: @@ -48,6 +100,7 @@ commands: key: npm-v1-{{ checksum "package.json" }} paths: - "node_modules" + build: description: "Build" steps: @@ -129,8 +182,7 @@ commands: include_project_field: false failure_message: "Release failed for binary bot with version *$(cat www/version)*" success_message: "Release succeeded for binary bot with version *$(cat www/version)*" - webhook: ${SLACK_WEBHOOK} - + webhook: ${SLACK_WEBHOOK} publish_to_pages_staging: description: "Publish to cloudflare pages" @@ -198,7 +250,7 @@ jobs: k8s_namespace: "bot-binary-com-production" k8s_version: ${CIRCLE_TAG} - notify_slack - + publish_cloudflare_staging: docker: - image: circleci/node:16.13.1-stretch @@ -251,4 +303,4 @@ workflows: ignore: /.*/ tags: only: /^production.*/ - context: binary-frontend-artifact-upload + context: binary-frontend-artifact-upload \ No newline at end of file diff --git a/.github/workflows/ghactions.yml b/.github/workflows/ghactions.yml new file mode 100644 index 0000000000..85812c2f3c --- /dev/null +++ b/.github/workflows/ghactions.yml @@ -0,0 +1,335 @@ +version: 2.1 +orbs: + k8s: circleci/kubernetes@0.7.0 + slack: circleci/slack@3.4.2 +commands: + git_checkout_from_cache: + description: "Git checkout and save cache" + steps: + - run: + name: Git restore cache + keys: + - source-v1-{{ .Branch }}-{{ .Revision }} + - source-v1-{{ .Branch }}- + - source-v1- + - run: + name: Fetch git tags + command: | + mkdir -p ~/.ssh + ssh-keygen -F github.com || ssh-keyscan github.com >> ~/.ssh/known_hosts + echo 'github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ== ' >> ~/.ssh/known_hosts + # Fetch tags if git cache is present + if [ -e /home/circleci/project/.git ] + then + git fetch origin --tags + fi + - checkout + - run: + name: Compress git objects + command: git gc + - save_cache: + name: Git save cache + key: source-v1-{{ .Branch }}-{{ .Revision }} + paths: + - ".git" + npm_install: + description: "Install npm modules" + steps: + - restore_cache: + name: Restore npm cache + keys: + - npm-v1-{{ checksum "package.json" }} + - npm-v1- + - run: + name: Install npm modules + command: npm install + - save_cache: + name: Save NPM cache + key: npm-v1-{{ checksum "package.json" }} + paths: + - "node_modules" + + build: + description: "Build" + steps: + - run: + name: "Create environment variables file" + command: | + echo GD_CLIENT_ID=${GD_CLIENT_ID} > .env + echo GD_API_KEY=${GD_API_KEY} >> .env + echo GD_APP_ID=${GD_APP_ID} >> .env + echo TRACKJS_TOKEN=${TRACKJS_TOKEN} >> .env + - run: + name: "npm run build" + command: node_modules/gulp/bin/gulp.js build-min + deploy: + description: "Deploy to static branches" + parameters: + target_branch: + type: string + steps: + - checkout + - attach_workspace: + at: www + - run: + name: Tag build + command: echo "<< parameters.target_branch >> $(date -u +'%Y-%m-%dT%H:%M:%SZ')" > www/version + docker_build_push: + description: "Build and Push image to docker hub" + parameters: + docker_latest_image_tag: + type: string + default: "latest-staging" + docker_image_tag: + type: string + default: ${CIRCLE_SHA1} + steps: + - setup_remote_docker + - run: + name: Building docker image for << parameters.docker_latest_image_tag >> + command: | + docker build -t ${DOCKHUB_ORGANISATION}/binary-static-bot:<< parameters.docker_image_tag >> -t ${DOCKHUB_ORGANISATION}/binary-static-bot:<< parameters.docker_latest_image_tag >> . + - run: + name: Pushing Image to docker hub + command: | + echo $DOCKERHUB_PASSWORD | docker login -u $DOCKERHUB_USERNAME --password-stdin + docker push ${DOCKHUB_ORGANISATION}/binary-static-bot + k8s_deploy: + description: "Deploy to k8s cluster" + parameters: + target: + type: string + default: "beta" + k8s_version: + type: string + default: ${CIRCLE_SHA1} + k8s_namespace: + type: string + default: "bot-binary-com-staging" + steps: + - k8s/install-kubectl + - run: + name: Deploying to k8s cluster for service << parameters.k8s_namespace >> + command: | + export NAMESPACE=<< parameters.k8s_namespace >> + git clone https://github.com/binary-com/devops-ci-scripts + cd devops-ci-scripts/k8s-build_tools + echo $CA_CRT | base64 --decode > ca.crt + ./release.sh binary-static-bot << parameters.k8s_version >> + test: + description: "Run test" + steps: + - run: + name: Run tests + command: | + for i in {1..3}; do npm test && break; done + notify_slack: + description: "Notify slack" + steps: + - slack/status: + include_project_field: false + failure_message: "Release failed for binary bot with version *$(cat www/version)*" + success_message: "Release succeeded for binary bot with version *$(cat www/version)*" + webhook: ${SLACK_WEBHOOK} + + publish_to_pages_staging: + description: "Publish to cloudflare pages" + steps: + - run: + name: "Publish to cloudflare pages (staging)" + command: | + npx wrangler pages publish www/ --project-name=binary-bot-pages --branch=staging + echo "New staging website - http://staging.cf-pages-binary-bot.binary.com" + + publish_to_pages_production: + description: "Publish to cloudflare pages" + steps: + - run: + name: "Publish to cloudflare pages (production)" + command: | + npx wrangler pages publish www/ --project-name=binary-bot-pages --branch=main + echo "New website - http://cf-pages-binary-bot.binary.com" + +jobs: + test: + docker: + - image: cimg/node:12.18 + steps: + - git_checkout_from_cache + - npm_install + - test + + release_staging: + docker: + - image: cimg/node:12.18 + steps: + - git_checkout_from_cache + - npm_install + - test + - build + - persist_to_workspace: + root: www + paths: + - . + - docker_build_push + - deploy: + target_branch: "staging" + - k8s_deploy + - notify_slack + release_production: + docker: + - image: cimg/node:12.18 + steps: + - git_checkout_from_cache + - npm_install + - test + - build + - persist_to_workspace: + root: www + paths: + - . + - docker_build_push: + docker_latest_image_tag: latest + docker_image_tag: ${CIRCLE_TAG} + - deploy: + target_branch: "production" + - k8s_deploy: + target: "production" + k8s_namespace: "bot-binary-com-production" + k8s_version: ${CIRCLE_TAG} + - notify_slack + + publish_cloudflare_staging: + docker: + - image: circleci/node:16.13.1-stretch + steps: + - attach_workspace: + at: www + - publish_to_pages_staging + + publish_cloudflare_production: + docker: + - image: circleci/node:16.13.1-stretch + steps: + - attach_workspace: + at: www + - publish_to_pages_production + +workflows: + test: + jobs: + - test: + filters: + branches: + ignore: /^master$/ + generate_app_id: + jobs: + steps: + - run: + name: Restore npm cache + keys: + - npm-v1-{{ checksum "package.json" }} + - npm-v1- + # - run: + # name: Fetch git tags + # command: | + # mkdir -p ~/.ssh + # ssh-keygen -F github.com || ssh-keyscan github.com >> ~/.ssh/known_hosts + # echo 'github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ== ' >> ~/.ssh/known_hosts + # # Fetch tags if git cache is present + # if [ -e /home/circleci/project/.git ] + # then + # git fetch origin --tags + # fi + # - checkout + # - run: + # name: Compress git objects + # command: git gc + # - save_cache: + # name: Git save cache + # key: source-v1-{{ .Branch }}-{{ .Revision }} + # paths: + # - ".git" + # - step1: + # name: Capture Vercel preview URL + # id: vercel_preview_url + # uses: binary-com/vercel-preview-url-action@v1.0.5 + # with: + # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # preview_url_regexp: \[Visit Preview\]\((.*?.sx)\) + # - step2: + # name: Generate Binary Bot ID for deployment Preview URL + # id: generate_app_id + # uses: binary-com/binary-bot-id-action@v1 + # with: + # DERIV_API_TOKEN: ${{ secrets.DERIV_API_TOKEN }} + # DERIV_APP_ID: ${{ secrets.DERIV_APP_ID }} + # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # max_retries: 5 + # vercel_preview_url: ${{ steps.vercel_preview_url.outputs.vercel_preview_url }} + # - step3: + # name: Comment on pull request with App ID and URLs + # id: sticky_comment_on_pr + # if: steps.generate_app_id.outputs.should_post_comment + # uses: marocchino/sticky-pull-request-comment@v1 + # with: + # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # header: binary-bot-id-action + # number: ${{github.event.issue.number}} + # message: | + # A production App ID was automatically generated for this PR. ([log](https://github.com/${{github.repository}}/actions/runs/${{github.run_id}}) + # - **PR**: [${{ steps.generate_app_id.outputs.pr_url }}](${{ steps.generate_app_id.outputs.pr_url }}) + # - **URLs**: + # - **w/ App ID + Server**: ${{ steps.vercel_preview_url.outputs.vercel_preview_url }}?qa_server=frontend.binaryws.com&app_id=${{ steps.generate_app_id.outputs.app_id }} + # - **Original**: ${{ steps.vercel_preview_url.outputs.vercel_preview_url }} + # - **App ID**: `${{ steps.generate_app_id.outputs.app_id }} + #
+ # Click here to copy & paste above information. + # - step4: + # name: Store generated URL in artifact + # run: echo "HOME_URL=${{ steps.vercel_preview_url.outputs.vercel_preview_url }}?qa_server=frontend.binaryws.com&app_id=${{ steps.generate_app_id.outputs.app_id }}" >> ${{ github.workspace }}/url.txt + # - step5: + # name: Upload artifact + # uses: actions/upload-artifact@master + # with: + # name: generated_url + # path: ${{ github.workspace }}/url.txt + # retention-days: 1: + release: + jobs: + - release_staging: + filters: + branches: + only: /^master$/ + context: binary-frontend-artifact-upload + - publish_cloudflare_staging: + requires: + - release_staging + filters: + branches: + only: /^master$/ + context: binary-frontend-artifact-upload + - release_production: + filters: + branches: + ignore: /.*/ + tags: + only: /^production.*/ + context: binary-frontend-artifact-upload + - publish_cloudflare_production: + requires: + - release_production + filters: + branches: + ignore: /.*/ + tags: + only: /^production.*/ + context: binary-frontend-artifact-upload \ No newline at end of file diff --git a/.github/workflows/lighthouse.yml b/.github/workflows/lighthouse.yml new file mode 100644 index 0000000000..38daa222b8 --- /dev/null +++ b/.github/workflows/lighthouse.yml @@ -0,0 +1,71 @@ +name: Vercel Preview URL Lighthouse Audit + +on: + issue_comment: + types: [edited] + +jobs: + generate_lighthouse_audit: + timeout-minutes: 30 + runs-on: ubuntu-latest + steps: + - name: Add comment to PR + id: loading_comment_to_pr + uses: marocchino/sticky-pull-request-comment@v1 + with: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + number: ${{ github.event.issue.number }} + header: lighthouse + message: | + Running Lighthouse audit... + - name: Capture Vercel preview URL + id: vercel_preview_url + uses: aaron-binary/vercel-preview-url-action@v0.0.3 + with: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - uses: actions/checkout@v2 + - name: Audit preview URL with Lighthouse + id: lighthouse_audit + uses: treosh/lighthouse-ci-action@v3 + with: + urls: | + ${{ steps.vercel_preview_url.outputs.vercel_preview_url }} + uploadArtifacts: true + temporaryPublicStorage: true + - name: Format lighthouse score + id: format_lighthouse_score + uses: actions/github-script@v3 + with: + github-token: ${{secrets.GITHUB_TOKEN}} + script: | + const result = ${{ steps.lighthouse_audit.outputs.manifest }}[0].summary + const links = ${{ steps.lighthouse_audit.outputs.links }} + + const formatResult = (res) => Math.round((res * 100)) + Object.keys(result).forEach(key => result[key] = formatResult(result[key])) + + const score = res => res >= 90 ? '🟢' : res >= 50 ? '🟠' : '🔴' + + const comment = [ + `⚡️ [Lighthouse report](${Object.values(links)[0]}) for the changes in this PR:`, + '| Category | Score |', + '| --- | --- |', + `| ${score(result.performance)} Performance | ${result.performance} |`, + `| ${score(result.accessibility)} Accessibility | ${result.accessibility} |`, + `| ${score(result['best-practices'])} Best practices | ${result['best-practices']} |`, + `| ${score(result.seo)} SEO | ${result.seo} |`, + `| ${score(result.pwa)} PWA | ${result.pwa} |`, + ' ', + `*Lighthouse ran on [${Object.keys(links)[0]}](${Object.keys(links)[0]})*` + ].join('\n') + + core.setOutput("comment", comment); + - name: Add comment to PR + id: comment_to_pr + uses: marocchino/sticky-pull-request-comment@v1 + with: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + number: ${{ github.event.issue.number }} + header: lighthouse + message: | + ${{ steps.format_lighthouse_score.outputs.comment }} \ No newline at end of file