diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..51ae3e64 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,155 @@ +name: Build +on: [push, pull_request] +jobs: + build: + name: Build on ${{ matrix.vm }} + strategy: + fail-fast: false + matrix: + vm: ["ubuntu-latest", "macos-latest"] + runs-on: ${{ matrix.vm }} + steps: + - name: Setup Go 1.13 + uses: actions/setup-go@v1 + with: + go-version: 1.13 + - name: Extract version metadata + id: meta + run: | + echo "::set-output name=os-arch::$(go env GOOS)_$(go env GOARCH)" + echo "::set-output name=version::${GITHUB_REF##*/}" + - name: Check out project files + uses: actions/checkout@v2 + - name: Build + id: build + run: | + make dist + notify: + name: Notify Slack + needs: + - build + if: always() + runs-on: ubuntu-latest + steps: + - name: Prepare Slack message + id: status + uses: actions/github-script@0.8.0 + with: + script: | + //////////////////////////////////// + // 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" + } + } + const commit = "${{ github.sha }}".substr(0, 6) + var pr = "" + for (p of wf_run.data.pull_requests) { + pr += ",<"+ p.url + "|#" + p.number + ">" + } + if (pr != "") { + pr = "for " + pr.substr(1) + } + // build the message + var fields = [] + 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 + } + fields.push({ + type: "mrkdwn", + text: status_icon_func(j.conclusion) + " <" + j.html_url + "|" + j.name + ">\n \u21b3 completed in " + 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 slack_msg = { + blocks: [ + { + type: "section", + text: { + type: "mrkdwn", + text: "\nfrom *${{ github.ref }}@" + commit + "*" + } + }, + { + type: "section", + text: { + type: "mrkdwn", + text: status_icon_func(workflow_status) + " *${{ github.workflow }}* " + pr + "\nWorkflow run <" + wf_run.data.html_url + "|#${{ github.run_number }}> completed in " + date_diff_func(new Date(wf_run.data.created_at), new Date(wf_run.data.updated_at)) + } + }, + { + type: "divider" + }, + { + type: "section", + fields: fields + } + ] + } + return slack_msg + - name: Send to Slack + if: success() + run: | + curl -X POST ${{ secrets.SLACK_WEBHOOK }} -H "Content-type: application/json" --data '${{ steps.status.outputs.result }}' \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 66ee912f..ad5d33a2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -3,6 +3,8 @@ on: push: tags: - 'v*' +env: + BINTRAY_PACKAGE: istanbul jobs: build: name: Build on ${{ matrix.vm }} @@ -32,27 +34,17 @@ jobs: with: name: artifacts-${{ steps.meta.outputs.os-arch }} path: build - deploy: - name: Deploy ${{ matrix.os-arch }} dist to Bintray + predeploy: + name: Prepare Bintray runs-on: ubuntu-latest - needs: - - build - strategy: - matrix: - os-arch: ["linux_amd64", "darwin_amd64"] steps: - name: Setup jfrog CLI uses: jfrog/setup-jfrog-cli@v1 - - name: Download artifacts - uses: actions/download-artifact@v1 - with: - name: artifacts-${{ matrix.os-arch }} - name: Extract metadata id: meta run: | echo "::set-output name=version::${GITHUB_REF##*/}" - echo "::set-output name=package::istanbul" - echo "::set-output name=upload-path::istanbul-tools" + echo "::set-output name=package::${{ env.BINTRAY_PACKAGE }}" - name: Prepare ${{ steps.meta.outputs.package }}@${{ steps.meta.outputs.version }} in Bintray run: | CHECK_PACKAGE="${{ secrets.BINTRAY_ORGANIZATION }}/${{ secrets.BINTRAY_REPOSITORY }}/${{ steps.meta.outputs.package }}" @@ -68,12 +60,32 @@ jobs: --vcs-tag ${{ steps.meta.outputs.version }} --released $(date -u +"%Y-%m-%dT%H:%M:%SZ") \ $CHECK_VERSION fi + deploy: + name: Deploy ${{ matrix.os-arch }} dist to Bintray + runs-on: ubuntu-latest + needs: + - build + - predeploy + strategy: + matrix: + os-arch: ["linux_amd64", "darwin_amd64"] + steps: + - name: Setup jfrog CLI + uses: jfrog/setup-jfrog-cli@v1 + - name: Download artifacts + uses: actions/download-artifact@v1 + with: + name: artifacts-${{ matrix.os-arch }} + - name: Extract metadata + id: meta + run: | + echo "::set-output name=version::${GITHUB_REF##*/}" + echo "::set-output name=package::${{ env.BINTRAY_PACKAGE }}" - name: Upload to Bintray run: | jfrog bt upload --key ${{ secrets.BINTRAY_API_KEY }} --user ${{ secrets.BINTRAY_USER }} --publish --override \ "artifacts-${{ matrix.os-arch }}/*.*" \ - ${{ secrets.BINTRAY_ORGANIZATION }}/${{ secrets.BINTRAY_REPOSITORY }}/${{ steps.meta.outputs.package }}/${{ steps.meta.outputs.version }} \ - ${{ steps.meta.outputs.upload-path }}/ + ${{ secrets.BINTRAY_ORGANIZATION }}/${{ secrets.BINTRAY_REPOSITORY }}/${{ steps.meta.outputs.package }}/${{ steps.meta.outputs.version }} notify: name: Notify Slack needs: @@ -203,4 +215,4 @@ jobs: - name: Send to Slack if: success() run: | - curl -X POST ${{ secrets.SLACK_WEBHOOK_URL}} -H "Content-type: application/json" --data '${{ steps.status.outputs.result }}' \ No newline at end of file + curl -X POST ${{ secrets.SLACK_WEBHOOK }} -H "Content-type: application/json" --data '${{ steps.status.outputs.result }}' \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index e768331b..00000000 --- a/.travis.yml +++ /dev/null @@ -1,46 +0,0 @@ -language: go -sudo: required -go: - - 1.11.5 - - 1.12.4 -env: - - TEST=unit - - TEST=istanbul - - TEST=quorum - -services: - - docker - -install: - - go get github.com/onsi/ginkgo/ginkgo - - unset GOPATH - -script: - - 'if [ ${TEST} = "unit" ]; then - travis_wait 30 go test -v ./... --timeout 30m; - elif [ ${TEST} = "istanbul" ]; then - cd ${TRAVIS_BUILD_DIR}/tests/functional && travis_wait 120 ginkgo -r --progress; - elif [ ${TEST} = "quorum" ]; then - cd ${TRAVIS_BUILD_DIR}/tests/quorum && travis_wait 120 ginkgo -r --progress; - else - echo "Invalid env" - exit 2; - fi' -branches: - only: - - master - -jobs: - include: - - stage: release - go: 1.11 - if: tag =~ ^v - env: - - TEST=none - - REV="$TRAVIS_TAG" - deploy: - provider: releases - api_key: "$GITHUB_OAUTH_TOKEN" - skip_cleanup: true - on: - tags: true diff --git a/cmd/istanbul/address/cmd.go b/cmd/istanbul/address/cmd.go index b01380d9..2802be05 100644 --- a/cmd/istanbul/address/cmd.go +++ b/cmd/istanbul/address/cmd.go @@ -1,9 +1,12 @@ package address import ( + "crypto/ecdsa" "encoding/hex" "fmt" + "github.com/ethereum/go-ethereum/p2p/enode" + "github.com/ethereum/go-ethereum/crypto" "github.com/urfave/cli" ) @@ -15,20 +18,32 @@ var ( Usage: "Extract validator address", Flags: []cli.Flag{ nodeKeyHexFlag, + nodeIdHexFlag, }, Description: `Extract validator address`, } ) func address(ctx *cli.Context) error { - if !ctx.IsSet(nodeKeyHexFlag.Name) { - return cli.NewExitError("Must supply nodekey hex", 10) + if (!ctx.IsSet(nodeKeyHexFlag.Name) && !ctx.IsSet(nodeIdHexFlag.Name)) || (ctx.IsSet(nodeKeyHexFlag.Name) && ctx.IsSet(nodeIdHexFlag.Name)) { + return cli.NewExitError("Must supply nodekey or nodeid hex", 10) } - nodeKeyHex := ctx.String(nodeKeyHexFlag.Name) - privKey, err := crypto.HexToECDSA(nodeKeyHex) - if err != nil { - return err + var publicKey ecdsa.PublicKey + if ctx.IsSet(nodeKeyHexFlag.Name) { + nodeKeyHex := ctx.String(nodeKeyHexFlag.Name) + privKey, err := crypto.HexToECDSA(nodeKeyHex) + if err != nil { + return err + } + publicKey = privKey.PublicKey } - fmt.Printf("0x%s\n", hex.EncodeToString(crypto.PubkeyToAddress(privKey.PublicKey).Bytes())) + if ctx.IsSet(nodeIdHexFlag.Name) { + pubKey, err := enode.HexPubkey(ctx.String(nodeIdHexFlag.Name)) + if err != nil { + return err + } + publicKey = *pubKey + } + fmt.Printf("0x%s\n", hex.EncodeToString(crypto.PubkeyToAddress(publicKey).Bytes())) return nil } diff --git a/cmd/istanbul/address/flags.go b/cmd/istanbul/address/flags.go index cf65bab4..3081bd47 100644 --- a/cmd/istanbul/address/flags.go +++ b/cmd/istanbul/address/flags.go @@ -9,4 +9,8 @@ var ( Name: "nodekeyhex", Usage: "Node key as hex", } + nodeIdHexFlag = cli.StringFlag{ + Name: "nodeidhex", + Usage: "Public key as hex, usually used as enode address", + } )