Skip to content

Release

Release #52

Workflow file for this run

name: Release
on:
workflow_dispatch:
tags:
- 'v*'
push:
tags:
- 'v*'
env:
GO_VERSION: 1.21.3
GOPATH: ${{ github.workspace }}/go
WORKING_DIR: ${{ github.workspace }}/go/src/github.com/ethereum/go-ethereum
jobs:
publish-docker:
name: Publish Docker Images
runs-on: ubuntu-20.04
steps:
- name: 'Check out project files'
uses: actions/checkout@v3
# https://github.com/docker/setup-qemu-action
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
# https://github.com/docker/setup-buildx-action
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: 'Extract Docker Image Tag'
id: extract
run: |
REF=${{ github.ref }}
echo ::set-output name=image_tag::$(echo $REF | sed 's/refs\/tags\/v//g')
echo ::set-output name=image_tag_minor_latest::$(echo $REF | sed -e 's/refs\/tags\/v//g' -e 's/^\([[:digit:]]*\.[[:digit:]]*\).*/\1/')
- name: 'Build ARM image to Docker Hub'
id: build
run: |
echo "skipping..."
# output_dir=${{ runner.temp }}/docker
# mkdir -p $output_dir
# docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_ACCESS_TOKEN }}
# docker buildx build --push --platform linux/amd64,linux/arm64 -t ${{ secrets.DOCKER_REPO }}:latest -t ${{ secrets.DOCKER_REPO }}:${{ steps.extract.outputs.image_tag }} -t ${{ secrets.DOCKER_REPO }}:${{ steps.extract.outputs.image_tag_minor_latest }} .
build-binary:
name: 'Build binary for ${{ matrix.os }}'
strategy:
fail-fast: false
matrix:
# os: [ "ubuntu-20.04", "macos-latest" ]
os: [ "macos-latest" ]
runs-on: ${{ matrix.os }}
steps:
- name: 'Setup Go ${{ env.GO_VERSION }}'
uses: actions/setup-go@v1
with:
go-version: ${{ env.GO_VERSION }}
- name: 'Prepare environment'
id: env
run: |
echo "$(go env GOPATH)/bin" >> $GITHUB_PATH
echo "::set-output name=key::$(go env GOOS)_$(go env GOARCH)"
echo "::set-output name=version::${GITHUB_REF##*/}"
- name: 'Check out project files'
uses: actions/checkout@v2
with:
path: ${{ env.WORKING_DIR }}
- name: 'Build geth'
# For MacOS, We use gtar and run purge command to workaround issue
# https://github.com/actions/virtual-environments/issues/2619
id: build
working-directory: ${{ env.WORKING_DIR }}
run: |-
make geth
mkdir -p build/artifact
tar_file=build/artifact/geth_${{ steps.env.outputs.version }}_${{ steps.env.outputs.key }}.tar.gz
if [ "${{ matrix.os }}" == "macos-latest" ]; then
sudo /usr/sbin/purge
gtar cfvz ${tar_file} -C build/bin geth
else
tar cfvz ${tar_file} -C build/bin geth
fi
echo "::set-output name=tar_file::${tar_file}"
echo "::set-output name=checksum::$(shasum -a 256 build/bin/geth | awk '{print $1}')"
- name: 'Verify tarball'
working-directory: ${{ env.WORKING_DIR }}
run: |-
cp ${{ steps.build.outputs.tar_file }} ${{ runner.temp }}
pushd ${{ runner.temp}}
tar xfvz *.tar.gz
actual_checksum=$(shasum -a 256 geth | awk '{print $1}')
echo "Checksum: ${actual_checksum}"
popd
if [ "${{ steps.build.outputs.checksum }}" != "${actual_checksum}" ]; then
echo "::error::geth checksum validation fails"
exit 1
fi
- name: 'Upload artifact'
uses: actions/upload-artifact@v2
with:
path: ${{ env.WORKING_DIR }}/build/artifact
name: ${{ steps.env.outputs.key }}
if-no-files-found: error
deploy-cloudsmith:
name: 'Deploy binary to Cloudsmith for ${{ matrix.goarch }}'
needs:
- build-binary
strategy:
fail-fast: false
matrix:
# goarch: [ "linux_amd64", "darwin_arm64" ]
goarch: [ "darwin_arm64" ]
runs-on: ubuntu-latest
steps:
- name: 'Prepare environment'
id: env
run: |
echo "$(go env GOPATH)/bin" >> $GITHUB_PATH
echo "::set-output name=version::v24.4.0"
# echo "::set-output name=version::${GITHUB_REF##*/}"
- name: 'Download artifacts'
uses: actions/download-artifact@v2
with:
path: artifact
- name: 'Upload artifacts to Cloudsmith'
id: push
uses: cloudsmith-io/action@master
with:
api-key: ${{ secrets.CLOUDSMITH_API_KEY }}
command: "push"
format: "raw"
owner: "consensys"
repo: "go-quorum"
file: "artifact/${{ matrix.goarch }}/geth_${{ steps.env.outputs.version }}_${{ matrix.goarch }}.tar.gz"
name: "geth_${{ steps.env.outputs.version }}_${{ matrix.goarch }}.tar.gz"
summary: "GoQuorum ${{ steps.env.outputs.version }} - binary distribution for ${{ matrix.goarch }}"
description: "See https://github.com/ConsenSys/quorum/"
version: "${{ steps.env.outputs.version }}"
draft-release:
if: always()
name: 'Draft Github release'
needs:
- deploy-cloudsmith
- publish-docker
runs-on: ubuntu-20.04
steps:
- name: 'Check out project files'
uses: actions/checkout@v2
- name: 'Generate release notes'
id: release_notes
run: |
echo "skipping..."
# git fetch --depth=1 origin +refs/tags/*:refs/tags/*
# file="generated-release-notes.md"
# current_version="${GITHUB_REF##*/}"
# last_version=$(git describe --abbrev=0 --tags `git rev-list --tags --skip=1 --max-count=1`)
# last_release_date=$(git log -1 --format=%cd --date=short $last_version)
# echo "Last version: $last_version on $last_release_date"
# # pulling from git logs
# curl -q -s -H "Accept: application/vnd.github.v3+json" \
# "https://api.github.com/search/issues?q=repo:ConsenSys/quorum+is:pr+is:merged+merged%3A>=$last_release_date+sort%3Aupdated-desc" | jq -r '"* " + (.items[]|.title + " #" + (.number|tostring))' \
# >> $file
# # pulling file hashes from Cloudsmith
# echo "" >> $file
# echo "| Filename | SHA256 Hash |" >> $file
# echo "|:---------|:------------|" >> $file
# curl --request GET \
# --url "https://api.cloudsmith.io/v1/packages/consensys/go-quorum/?query=version:$current_version" \
# --header 'Accept: application/json' \
# --header 'X-Api-Key: ${{ secrets.CLOUDSMITH_API_KEY }}' \
# | jq '.[] | select(.name | endswith(".asc") | not) | "|[\(.name)](\(.cdn_url))|`\(.checksum_sha256)`|"' -r \
# >> $file
# content=$(cat $file)
# # escape newline
# content="${content//'%'/'%25'}"
# content="${content//$'\n'/'%0A'}"
# content="${content//$'\r'/'%0D'}"
# echo "::set-output name=content::$content"
# - name: 'Create Github draft release'
# uses: actions/create-release@v1
# env:
# # This token is provided by Actions, you do not need to create your own token
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# with:
# tag_name: ${{ github.ref }}
# release_name: ${{ github.ref }}
# body: |
# ${{ steps.release_notes.outputs.content }}
# draft: true
# prerelease: false
notify:
if: always()
name: 'Notify'
needs:
- build-binary
- deploy-cloudsmith
- publish-docker
- draft-release
runs-on: ubuntu-20.04
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"
echo "::set-output name=version::${GITHUB_REF##*/}"
- 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:* <https://github.com/${{ github.repository }}|${{ github.repository }}>"
},
{
"type": "mrkdwn",
"text": `*Branch:* <https://github.com/${{ github.repository }}/${gitref_path}|${{ github.ref }}>`
},
{
"type": "mrkdwn",
"text": `*Event:* ${wf_run.data.event}`
},
{
"type": "mrkdwn",
"text": `*Commit:* <https://github.com/${{ github.repository }}/commit/${wf_run.data.head_commit.id}|${wf_run.data.head_commit.id.substr(0, 8)}>`
},
{
"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 }} ${{ steps.setup.outputs.version }}* <${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 <<JSON > long_message.json
${{ steps.status.outputs.result }}
JSON
cat <<JSON > 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"