diff --git a/.github/actions/build-and-deploy-to-bucket/action.yml b/.github/actions/build-and-deploy-to-bucket/action.yml new file mode 100644 index 000000000..47203d727 --- /dev/null +++ b/.github/actions/build-and-deploy-to-bucket/action.yml @@ -0,0 +1,142 @@ +name: Deploy to a GCP Bucket +description: "Builds and deploys to a Google Cloud Storage Bucket" +inputs: + # Currently the action only supports `environment` = `goerli`. + environment: + description: > + The environment on which the action should be used. For example `goerli`. + Will be used to deterine environment variables and decide which legacy + packages should be used for building. + required: true + ethUrlHttp: + description: The HTTP ETH API URL. + required: true + ethUrlWS: + description: The WebSocket ETH API URL. + required: true + useUpstreamBuilds: + description: True if the upstream builds should be used. + required: true + default: "false" + upstreamBuilds: + description: Upstream builds (required if `useUpstreamBuilds==true`). + required: false + dependentPackagesTag: + description: > + Tag which should be used to pull latest non-legacy `threshold-network` and + `keep-network` packages with contracts (required if + `useUpstreamBuilds==false`). For example `dapp-dev-goerli`. + required: false + gcpServiceKey: + description: JSON key for Google Cloud Platform service account. + required: true + gcpBucketName: + description: The name of the bucket where code wil be deployed. + required: true + preview: + description: True if the code should be pushed to the preview bucket. + required: true + default: "false" + +runs: + using: "composite" + steps: + - uses: actions/setup-node@v3 + with: + node-version: "14" + cache: "yarn" + + # We need this step because the `@keep-network/tbtc` which we update in + # next step has a dependency to `@summa-tx/relay-sol@2.0.2` package, which + # downloads one of its sub-dependencies via unathenticated `git://` + # protocol. That protocol is no longer supported. Thanks to this step + # `https://` is used instead of `git://`. + - name: Configure git to don't use unauthenticated protocol + shell: bash + run: git config --global url."https://".insteadOf git:// + + - name: Install dependencies + shell: bash + run: yarn install --frozen-lockfile + + - name: Get upstream packages versions + if: inputs.upstreamBuilds == 'true' + uses: keep-network/ci/actions/upstream-builds-query@v2 + id: upstream-builds-query + with: + upstream-builds: ${{ inputs.upstreamBuilds }} + query: | + threshold-contracts-version = github.com/threshold-network/solidity-contracts#version + + - name: Set packages versions + shell: bash + id: set-packages-versions + run: | + if [ ${{ inputs.useUpstreamBuilds }} = 'false' ]; then + echo "::set-output name=threshold-contracts-version::${{ inputs.dependentPackagesTag }}" + else + echo "::set-output name=threshold-contracts-version::${{ steps.upstream-builds-query.outputs.threshold-contracts-version }}" + fi + + # Currently we only support `environment` = `goerli`. We provide explicit + # version of the `keep-core` package, because using `goerli` tag results in + # `expected manifest` error - probably caused by bug in Yarn: + # https://github.com/yarnpkg/yarn/issues/4731. + + # TODO: Add upgrade of @keep-network/random-beacon, @keep-network/ecdsa, + # @keep-network/tbtc-v2 once they'll be added as dashboard's dependencies. + - name: Resolve contracts + shell: bash + run: | + yarn upgrade \ + @threshold-network/solidity-contracts@${{ steps.set-packages-versions.outputs.threshold-contracts-version }} \ + @keep-network/keep-core@1.8.1-goerli.0 \ + @keep-network/keep-ecdsa@${{ inputs.environment }} \ + @keep-network/tbtc@${{ inputs.environment }} \ + @keep-network/coverage-pools@${{ inputs.environment }} + + - name: Run postinstall script + shell: bash + # `yarn upgrade` doesn't trigger the `postinstall` script. + run: yarn run postinstall + + - name: Load environment variables + uses: keep-network/ci/actions/load-env-variables@v2 + with: + environment: ${{ inputs.environment }} + + - name: Build + shell: bash + run: yarn build + env: + # `head_ref` variable property is only available when the event that + # triggers a workflow run is either pull_request or pull_request_target. + # For `workflow_dispatch` and `push`, the `PUBLIC_URL` will resolve to `/`.` + PUBLIC_URL: /${{ github.head_ref }} + CHAIN_ID: ${{ env.NETWORK_ID }} + ETH_HOSTNAME_HTTP: ${{ inputs.ethUrlHttp }} + ETH_HOSTNAME_WS: ${{ inputs.ethUrlWS }} + + - name: Deploy to GCP + uses: thesis/gcp-storage-bucket-action@v3.1.0 + with: + service-key: ${{ inputs.gcpServiceKey }} + project: ${{ env.GOOGLE_PROJECT_ID }} + bucket-name: ${{ inputs.gcpBucketName }} + bucket-path: ${{ github.head_ref }} + build-folder: build + set-website: ${{ inputs.preview == 'false' }} + home-page-path: index.html + error-page-path: index.html + + - name: Post preview URL to PR + if: inputs.preview == 'true' + uses: actions/github-script@v5 + with: + script: | + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: 'Preview uploaded to https://${{ inputs.gcpBucketName }}/${{ github.head_ref }}/index.html.' + }) diff --git a/.github/workflows/dashboard-ci.yml b/.github/workflows/dashboard-ci.yml index 7f0b0cabc..b0bff63e1 100644 --- a/.github/workflows/dashboard-ci.yml +++ b/.github/workflows/dashboard-ci.yml @@ -8,6 +8,17 @@ on: - main pull_request: workflow_dispatch: + inputs: + environment: + description: "Environment (network) for workflow execution, e.g. `goerli`" + required: false + upstream_builds: + description: "Upstream builds" + required: false + upstream_ref: + description: "Git reference to checkout (e.g. branch name)" + required: false + default: "main" jobs: format: @@ -80,86 +91,77 @@ jobs: # - name: Test # run: yarn test - build-and-deploy-testnet: - name: Deploy to testnet + # The code will be published to https://preview.dashboard.test.threshold.network/${{ github.head_ref }}/index.html. + build-and-deploy-testnet-preview: + name: Deploy preview to testnet needs: build-and-test + if: github.event_name == 'pull_request' runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - - uses: actions/setup-node@v2 + - uses: ./.github/actions/build-and-deploy-to-bucket with: - node-version: "16" - cache: "yarn" - - # We need this step because the `@keep-network/tbtc` which we update in - # next step has a dependency to `@summa-tx/relay-sol@2.0.2` package, which - # downloads one of its sub-dependencies via unathenticated `git://` - # protocol. That protocol is no longer supported. Thanks to this step - # `https://` is used instead of `git://`. - - name: Configure git to don't use unauthenticated protocol - run: git config --global url."https://".insteadOf git:// - - # We provide explicit version of the `keep-core` package, because using - # `goerli` tag results in `expected manifest` error - probably caused by - # bug in Yarn: https://github.com/yarnpkg/yarn/issues/4731. - - name: Resolve latest goerli contracts - run: | - yarn upgrade \ - @threshold-network/solidity-contracts@goerli \ - @keep-network/keep-core@1.8.1-goerli.0 \ - @keep-network/keep-ecdsa@goerli \ - @keep-network/tbtc@goerli \ - @keep-network/coverage-pools@goerli - - - name: Run postinstall script - # `yarn upgrade` doesn't trigger the `postinstall` script. - run: yarn run postinstall - - - name: Build - run: yarn build - env: - PUBLIC_URL: /${{ github.head_ref }} - CHAIN_ID: 5 - ETH_HOSTNAME_HTTP: ${{ secrets.GOERLI_ETH_HOSTNAME_HTTP }} - ETH_HOSTNAME_WS: ${{ secrets.GOERLI_ETH_HOSTNAME_WS }} + environment: goerli + ethUrlHttp: ${{ secrets.GOERLI_ETH_HOSTNAME_HTTP }} + ethUrlWS: ${{ secrets.GOERLI_ETH_HOSTNAME_WS }} + useUpstreamBuilds: false + dependentPackagesTag: goerli + gcpServiceKey: ${{ secrets.KEEP_TEST_CI_UPLOAD_DAPP_JSON_KEY_BASE64 }} + gcpBucketName: preview.dashboard.test.threshold.network + preview: true + + # This job will be triggered via the `workflow_dispatch` event, as part of the + # CI flow, which gets triggered manually after changes in the contracts, + # client code, etc. As after such changes the manual rotation of the client + # pods is needed, we configure the job to use the protected `testnet` + # environment. Thanks to this, the job won't start until somebody approves it + # in GH Actions. + # The code will be published to https://dashboard.test.threshold.network/index.html. + build-and-deploy-testnet-on-dispatch: + name: Deploy to testnet + needs: build-and-test + if: | + github.event_name == 'workflow_dispatch' + && github.ref == 'refs/heads/main' + runs-on: ubuntu-latest + # testnet environment is protected, it requires an approval before execution. + environment: + name: testnet + steps: + - uses: actions/checkout@v3 - # A pull_request event is a PR; deploy to preview testnet bucket. - - name: Deploy PR preview to GCP - if: github.event_name == 'pull_request' - uses: thesis/gcp-storage-bucket-action@v3.1.0 + - uses: ./.github/actions/build-and-deploy-to-bucket with: - service-key: ${{ secrets.KEEP_TEST_CI_UPLOAD_DAPP_JSON_KEY_BASE64 }} - project: ${{ secrets.KEEP_TEST_GOOGLE_PROJECT_ID }} - bucket-name: preview.dashboard.test.threshold.network - bucket-path: ${{ github.head_ref }} - build-folder: build - - - name: Post preview URL to PR - if: github.event_name == 'pull_request' - uses: actions/github-script@v5 - with: - script: | - github.rest.issues.createComment({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - body: 'Preview uploaded to https://preview.dashboard.test.threshold.network/${{ github.head_ref }}/index.html.' - }) - - # A push event is triggered on main branch merge; deploy to testnet - # bucket. Also triggered by manual dispatch from `main` branch. - - name: Deploy to GCP bucket - if: | - github.event_name == 'push' - || (github.event_name == 'workflow_dispatch' - && github.ref == 'refs/heads/main') - uses: thesis/gcp-storage-bucket-action@v3.1.0 + environment: goerli + ethUrlHttp: ${{ secrets.GOERLI_ETH_HOSTNAME_HTTP }} + ethUrlWS: ${{ secrets.GOERLI_ETH_HOSTNAME_WS }} + useUpstreamBuilds: true + upstreamBuilds: ${{ github.event.inputs.upstream_builds }} + gcpServiceKey: ${{ secrets.KEEP_TEST_CI_UPLOAD_DAPP_JSON_KEY_BASE64 }} + gcpBucketName: dashboard.test.threshold.network + preview: false + + # This job will be triggered after merges of PRs to the `main` branch. As the + # triggering is not related to the changes in the contracts / client code, we + # don't need to rotate the pods and hence don't need to wait with the + # execution of workflow for the manual approval. + # The code will be published to https://dashboard.test.threshold.network/index.html. + build-and-deploy-testnet-on-push: + name: Deploy to testnet + needs: build-and-test + if: github.event_name == 'push' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - uses: ./.github/actions/build-and-deploy-to-bucket with: - service-key: ${{ secrets.KEEP_TEST_CI_UPLOAD_DAPP_JSON_KEY_BASE64 }} - project: ${{ secrets.KEEP_TEST_GOOGLE_PROJECT_ID }} - bucket-name: dashboard.test.threshold.network - build-folder: build - set-website: true - home-page-path: index.html - error-page-path: index.html + environment: goerli + ethUrlHttp: ${{ secrets.GOERLI_ETH_HOSTNAME_HTTP }} + ethUrlWS: ${{ secrets.GOERLI_ETH_HOSTNAME_WS }} + useUpstreamBuilds: false + dependentPackagesTag: goerli + gcpServiceKey: ${{ secrets.KEEP_TEST_CI_UPLOAD_DAPP_JSON_KEY_BASE64 }} + gcpBucketName: dashboard.test.threshold.network + preview: false