diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 000000000..aaa528e21 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,255 @@ +name: Build Check +on: + push: + paths-ignore: + - 'docs/**' + - '**.md' + - .gitignore + branches: + - master +env: + GO_VERSION: 1.13 + GOPATH: ${{ github.workspace }}/go + WORKING_DIR: ${{ github.workspace }}/go/src/github.com/ethereum/go-ethereum +jobs: + build: + name: 'Run tests and build on ${{ matrix.os }}' + strategy: + fail-fast: false + matrix: + # Not enable for macos as there's a consistent failure: + # --- FAIL: TestUPNP_DDWRT (2.20s) + # ###[error] natupnp_test.go:165: not discovered + # must be sommething with Github Actions VM networking setup. + # Event Ubuntu requires a workaround + os: ["ubuntu-latest"] + env: + QUORUM_IGNORE_TEST_PACKAGES: github.com/ethereum/go-ethereum/les,github.com/ethereum/go-ethereum/les/flowcontrol,github.com/ethereum/go-ethereum/mobile + runs-on: ${{ matrix.os }} + steps: + - name: 'Setup Go ${{ env.GO_VERSION }}' + uses: actions/setup-go@v1 + with: + go-version: ${{ env.GO_VERSION }} + - name: 'Check out project files' + uses: actions/checkout@574281d + with: + submodules: recursive + path: ${{ env.WORKING_DIR }} + - name: 'Apply workaround to fix networking in Linux' + if: runner.os == 'Linux' + run: | + # https://github.com/actions/virtual-environments/issues/798 + sudo ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf + - name: 'Prepare environment' + run: | + echo "::add-path::$(go env GOPATH)/bin" + - name: 'Run tests and build all' + working-directory: ${{ env.WORKING_DIR }} + run: | + make test all + notify: + if: always() + name: Notify + needs: + - build + runs-on: ubuntu-latest + steps: + - name: 'Setup metadata' + id: setup + run: | + gitref_path="${{ github.ref }}" + gitref_path=${gitref_path/refs\/heads/tree} # for refs/heads/my-branch + gitref_path=${gitref_path/refs\/tags/tree} # for refs/tags/v1.0.0 + gitref_path=${gitref_path#refs\/} # for refs/pull/123/merge + gitref_path=${gitref_path%/merge} # for refs/pull/123/merge + echo "::set-output name=gitref-path::$gitref_path" + - name: 'Prepare Slack message with full info' + id: status + uses: actions/github-script@0.8.0 + with: + script: | + var gitref_path = "${{ steps.setup.outputs.gitref-path }}" + //////////////////////////////////// + // retrieve workflow run data + //////////////////////////////////// + console.log("get workflow run") + const wf_run = await github.actions.getWorkflowRun({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: ${{ github.run_id }} + }) + console.log(wf_run.data) + console.log("get jobs for workflow run:", wf_run.data.jobs_url) + const jobs_response = await github.request(wf_run.data.jobs_url) + //////////////////////////////////// + // build slack notification message + //////////////////////////////////// + // some utility functions + var date_diff_func = function(start, end) { + var duration = end - start + // format the duration + var delta = duration / 1000 + var days = Math.floor(delta / 86400) + delta -= days * 86400 + var hours = Math.floor(delta / 3600) % 24 + delta -= hours * 3600 + var minutes = Math.floor(delta / 60) % 60 + delta -= minutes * 60 + var seconds = Math.floor(delta % 60) + var format_func = function(v, text, check) { + if (v <= 0 && check) { + return "" + } else { + return v + text + } + } + return format_func(days, "d", true) + format_func(hours, "h", true) + format_func(minutes, "m", true) + format_func(seconds, "s", false) + } + var status_icon_func = function(s) { + switch (s) { + case "w_success": + return ":white_check_mark:" + case "w_failure": + return ":no_entry:" + case "w_cancelled": + return ":warning:" + case "success": + return "\u2713" + case "failure": + return "\u2717" + default: + return "\u20e0" + } + } + // build the message + var job_blocks = [] + var is_wf_success = true + var is_wf_failure = false + for (j of jobs_response.data.jobs) { + console.log(j.name, ":", j.status, j.conclusion, j.started_at, j.completed_at) + // ignore the current job running this script + if (j.status != "completed") { + continue + } + if (j.conclusion != "success") { + is_wf_success = false + } + if (j.conclusion == "failure") { + is_wf_failure = true + } + job_blocks.push({ + type: "section", + text: { + type: "mrkdwn", + text: `${status_icon_func(j.conclusion)} <${j.html_url}|${j.name}> took ${date_diff_func(new Date(j.started_at), new Date(j.completed_at))}` + } + }) + } + var workflow_status = "w_cancelled" + if (is_wf_success) { + workflow_status = "w_success" + } else if (is_wf_failure) { + workflow_status = "w_failure" + } + var context_elements = [ + { + "type": "mrkdwn", + "text": "*Repo:* " + }, + { + "type": "mrkdwn", + "text": `*Branch:* ` + }, + { + "type": "mrkdwn", + "text": `*Event:* ${wf_run.data.event}` + }, + { + "type": "mrkdwn", + "text": `*Commit:* ` + }, + { + "type": "mrkdwn", + "text": `*Author:* ${wf_run.data.head_commit.author.name}` + } + ] + var header_blocks = [ + { + type: "section", + text: { + type: "mrkdwn", + text: `${status_icon_func(workflow_status)} *${{ github.workflow }}* <${wf_run.data.html_url}|#${{ github.run_number }}> took ${date_diff_func(new Date(wf_run.data.created_at), new Date(wf_run.data.updated_at))}` + } + }, + { + type: "context", + elements: context_elements, + }, + { + type: "divider" + } + ] + var slack_msg = { + blocks: [].concat(header_blocks, job_blocks) + } + return slack_msg + - name: 'Prepare Slack message with partial info' + id: short_status + if: failure() + uses: actions/github-script@0.8.0 + with: + script: | + //////////////////////////////////// + // retrieve workflow run data + //////////////////////////////////// + const wf_run = await github.actions.getWorkflowRun({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: ${{ github.run_id }} + }) + var date_diff_func = function(start, end) { + var duration = end - start + // format the duration + var delta = duration / 1000 + var days = Math.floor(delta / 86400) + delta -= days * 86400 + var hours = Math.floor(delta / 3600) % 24 + delta -= hours * 3600 + var minutes = Math.floor(delta / 60) % 60 + delta -= minutes * 60 + var seconds = Math.floor(delta % 60) + var format_func = function(v, text, check) { + if (v <= 0 && check) { + return "" + } else { + return v + text + } + } + return format_func(days, "d", true) + format_func(hours, "h", true) + format_func(minutes, "m", true) + format_func(seconds, "s", false) + } + var slack_msg = { + blocks: [ + { + type: "section", + text: { + type: "mrkdwn", + text: `:skull_and_crossbones: *${{ github.workflow }}* <${wf_run.data.html_url}|#${{ github.run_number }}> (took ${date_diff_func(new Date(wf_run.data.created_at), new Date(wf_run.data.updated_at))})` + } + } + ] + } + return slack_msg + - name: 'Send to Slack' + if: always() + run: | + cat < long_message.json + ${{ steps.status.outputs.result }} + JSON + cat < short_message.json + ${{ steps.short_status.outputs.result }} + JSON + _post() { + curl -X POST ${{ secrets.SLACK_WEBHOOK_URL }} -H "Content-type: application/json" --data "@${1}" + } + _post "long_message.json" || _post "short_message.json" \ No newline at end of file diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml new file mode 100644 index 000000000..2b942e63a --- /dev/null +++ b/.github/workflows/pr.yml @@ -0,0 +1,102 @@ +name: Pull Request Check +on: + pull_request: + paths-ignore: + - 'docs/**' + - '**.md' + - .gitignore +env: + GO_VERSION: 1.13 + GOPATH: ${{ github.workspace }}/go + WORKING_DIR: ${{ github.workspace }}/go/src/github.com/ethereum/go-ethereum +jobs: + unit-tests: + name: 'Unit tests in ${{ matrix.os }}' + strategy: + fail-fast: false + matrix: + os: ["ubuntu-latest"] + env: + QUORUM_IGNORE_TEST_PACKAGES: github.com/ethereum/go-ethereum/les,github.com/ethereum/go-ethereum/les/flowcontrol,github.com/ethereum/go-ethereum/mobile + runs-on: ${{ matrix.os }} + steps: + - name: 'Setup Go ${{ env.GO_VERSION }}' + uses: actions/setup-go@v1 + with: + go-version: ${{ env.GO_VERSION }} + - name: 'Check out project files' + uses: actions/checkout@574281d + with: + submodules: recursive + path: ${{ env.WORKING_DIR }} + - name: 'Prepare environment' + run: | + # https://github.com/actions/virtual-environments/issues/798 + sudo ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf + + echo "::add-path::$(go env GOPATH)/bin" + - name: 'Run unit tests' + working-directory: ${{ env.WORKING_DIR }} + run: | + make test + docker-build: + name: 'Build Docker image' + runs-on: ubuntu-latest + steps: + - name: 'Check out project files' + uses: actions/checkout@v2 + - name: 'Build docker image' + id: build + run: | + output_dir=${{ runner.temp }}/docker + mkdir -p $output_dir + docker build -t quorumengineering/quorum:pr . + docker save quorumengineering/quorum:pr > quorum-pr.tar + tar cfvz $output_dir/quorum-pr.tar.gz quorum-pr.tar + echo "::set-output name=output_dir::$output_dir" + - name: 'Upload workflow artifact - Docker image' + uses: actions/upload-artifact@v1 + with: + name: docker-image + path: ${{ steps.build.outputs.output_dir }} + acceptance-tests: + name: Acceptance tests (${{ matrix.tag }}) + needs: + - docker-build + if: success() + strategy: + fail-fast: false + matrix: + # list of tag expression being executed in parallel + # for PR, only selective tests are run. + # More comprehensive suites are scheduled to run in master + tag: + - 'basic || basic-raft || (advanced && raft) || networks/typical::raft' + - 'basic || basic-istanbul || (advanced && istanbul && !block-heights) || networks/typical::istanbul' + runs-on: ubuntu-latest + steps: + - name: 'Download workflow artifact - Docker image' + uses: actions/download-artifact@v1 + with: + name: docker-image + - name: 'Load Docker image' + id: setup + run: | + tar xfvz docker-image/quorum-pr.tar.gz + docker load --input quorum-pr.tar + echo "::set-output name=outputDir::${{ runner.temp }}" + - name: 'Run acceptance tests' + run: | + docker run --rm \ + --network host \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -v ${{ steps.setup.outputs.outputDir }}:${{ steps.setup.outputs.outputDir }} \ + -e TF_VAR_quorum_docker_image='{ name = "quorumengineering/quorum:pr", local = true }' \ + quorumengineering/acctests:latest test \ + -Pauto \ + -Dauto.outputDir=${{ steps.setup.outputs.outputDir }} \ + -Dtags="${{ matrix.tag }}" + - name: 'Debug' + run: | + docker images + docker ps -a \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 96e80e3ac..7e0bc09ad 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,5 @@ # simplified version of the upstream travis configuration with additional features # 1. Distribute binaries to bintray from Tag -# 2. Run quorum-acceptance-tests for Pull Requests language: go go_import_path: github.com/ethereum/go-ethereum @@ -19,65 +18,6 @@ env: matrix: include: - #raft consensus - - if: tag IS blank AND type = pull_request - name: acceptance-tests-raft - os: linux - dist: xenial - git: - submodules: false - cache: - directories: - - $HOME/.m2 - env: - - TF_VAR_consensus_mechanism=raft - install: - - $TRAVIS_BUILD_DIR/build/travis-install-linux.sh - script: - - $TRAVIS_BUILD_DIR/build/travis-run-acceptance-tests-linux.sh - - #istanbul consensus - - if: tag IS blank AND type = pull_request - name: acceptance-tests-istanbul - os: linux - dist: xenial - git: - submodules: false - cache: - directories: - - $HOME/.m2 - env: - - TF_VAR_consensus_mechanism=istanbul - install: - - $TRAVIS_BUILD_DIR/build/travis-install-linux.sh - script: - - $TRAVIS_BUILD_DIR/build/travis-run-acceptance-tests-linux.sh - - #clique consensus - - if: tag IS blank AND type = pull_request - name: acceptance-tests-clique - os: linux - dist: xenial - git: - submodules: false - cache: - directories: - - $HOME/.m2 - env: - - TF_VAR_consensus_mechanism=clique - install: - - $TRAVIS_BUILD_DIR/build/travis-install-linux.sh - script: - - $TRAVIS_BUILD_DIR/build/travis-run-acceptance-tests-linux.sh - - - if: tag IS blank - os: linux - dist: xenial - script: - - | - go run build/ci.go install - QUORUM_IGNORE_TEST_PACKAGES=github.com/ethereum/go-ethereum/les,github.com/ethereum/go-ethereum/les/flowcontrol go run build/ci.go test -coverage $TEST_PACKAGES - - if: tag IS present os: linux dist: xenial