Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 117 additions & 0 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
name: Docker images

on:
push:
branches: [master]
workflow_dispatch:
workflow_call:
inputs:
tag_name:
type: string
default: ""
secrets:
DOCKERHUB_USERNAME:
required: false
DOCKERHUB_TOKEN:
required: false

permissions:
contents: read

jobs:
docker:
name: Build and push images
# The Dockerfile compiles graph-node in release mode, which needs the
# cores and disk of a large runner.
runs-on: nscloud-ubuntu-22.04-amd64-16x32
timeout-minutes: 60
permissions:
contents: read
packages: write
# Docker Hub is pushed to only when its token is set; `if:` can't read
# secrets directly.
env:
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
steps:
- name: Checkout code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
with:
ref: ${{ inputs.tag_name }}

# The same tags as the Cloud Build setup: the short SHA always, plus
# `nightly` for master, or the release tag and `latest` for a release. A
# release is told apart by tag_name, not the event: called from
# release.yml, the event is the caller's push to master.
- name: Image metadata (graph-node)
id: meta
uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6
with:
images: |
ghcr.io/graphprotocol/graph-node
name=docker.io/graphprotocol/graph-node,enable=${{ env.DOCKERHUB_TOKEN != '' }}
flavor: latest=false
tags: &tags |
type=sha,prefix=
type=raw,value=nightly,enable=${{ inputs.tag_name == '' && github.ref == 'refs/heads/master' }}
type=raw,value=${{ inputs.tag_name }},enable=${{ inputs.tag_name != '' }}
type=raw,value=latest,enable=${{ inputs.tag_name != '' }}

- name: Image metadata (graph-node-debug)
id: meta-debug
uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6
with:
images: |
ghcr.io/graphprotocol/graph-node-debug
name=docker.io/graphprotocol/graph-node-debug,enable=${{ env.DOCKERHUB_TOKEN != '' }}
flavor: latest=false
tags: *tags

- name: Log in to ghcr.io
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Log in to Docker Hub
if: env.DOCKERHUB_TOKEN != ''
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

# Both images are built by one builder, so the graph-node-debug build
# reuses the graph-node-build stage from its cache.
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 # v4

# context is set because the action's default is a git context of
# github.sha, which is not the checked-out release tag. linux/amd64 only,
# as Cloud Build built.
- name: Build and push graph-node
uses: docker/build-push-action@c3c9e263c25d99ce0380d002d59b67737d91b0dc # v7
with:
context: .
file: docker/Dockerfile
target: graph-node
platforms: linux/amd64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-args: &build-args |
COMMIT_SHA=${{ github.sha }}
REPO_NAME=${{ github.event.repository.name }}
BRANCH_NAME=${{ inputs.tag_name == '' && github.ref_name || '' }}
TAG_NAME=${{ inputs.tag_name }}

- name: Build and push graph-node-debug
uses: docker/build-push-action@c3c9e263c25d99ce0380d002d59b67737d91b0dc # v7
with:
context: .
file: docker/Dockerfile
target: graph-node-debug
platforms: linux/amd64
push: true
tags: ${{ steps.meta-debug.outputs.tags }}
labels: ${{ steps.meta-debug.outputs.labels }}
build-args: *build-args
178 changes: 178 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
name: Publish

on:
workflow_call:
inputs:
tag_name:
required: true
type: string
dry_run:
type: boolean
default: false
workflow_dispatch:
inputs:
tag_name:
description: "Tag to publish (e.g. v0.46.0); with dry_run, any ref"
required: true
type: string
dry_run:
description: "Build and upload workflow artifacts only; leave the release untouched"
type: boolean
default: false

env:
CARGO_TERM_COLOR: always

permissions:
contents: read

jobs:
build:
name: Build ${{ matrix.asset_suffix }}
runs-on: nscloud-ubuntu-22.04-amd64-16x32
timeout-minutes: 60
strategy:
fail-fast: true
matrix:
# run_check marks the entries whose target is the runner's own architecture.
include:
- target: x86_64-unknown-linux-gnu
asset_suffix: linux-x86_64
run_check: true
file_type: "^ELF 64-bit LSB .*x86-64"
- target: aarch64-unknown-linux-gnu
asset_suffix: linux-aarch64
run_check: false
file_type: "^ELF 64-bit LSB .*ARM aarch64"
steps:
- name: Checkout code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
with:
ref: ${{ inputs.tag_name }}

# rustflags is cleared because the action otherwise sets RUSTFLAGS to
# "-D warnings", which would let a new warning fail a release build.
- name: Setup rust toolchain
uses: actions-rust-lang/setup-rust-toolchain@fb51252c7ba57d633bc668f941da052e410add48 # v1
with:
target: ${{ matrix.target }}
cache: false
rustflags: ""

# perl and make build the vendored OpenSSL; libprotobuf-dev carries the
# well-known protos the firehose build script imports.
- name: Install system packages
run: |
set -euo pipefail
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
file make perl pkg-config protobuf-compiler libprotobuf-dev
if [ "${{ matrix.target }}" = aarch64-unknown-linux-gnu ]; then
sudo apt-get install -y --no-install-recommends gcc-aarch64-linux-gnu libc6-dev-arm64-cross
echo "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc" >> "$GITHUB_ENV"
fi

# gnd is built alongside only for its pq-sys `bundled` feature, which
# links libpq statically into graph-node too, so the binary needs no
# libpq on the host. gnd itself is released by gnd-binary-build.yml.
- name: Build
run: cargo build --release --locked --target ${{ matrix.target }} --bin graph-node --bin gnd

# A cross-built binary cannot run here, so its architecture is asserted instead.
- name: Stage binary
env:
FILE_TYPE: ${{ matrix.file_type }}
RUN_CHECK: ${{ matrix.run_check }}
run: |
set -euo pipefail
mkdir -p release
binary="release/graph-node-${{ matrix.asset_suffix }}"
cp "target/${{ matrix.target }}/release/graph-node" "$binary"
chmod +x "$binary"
kind=$(file -b "$binary")
echo "$kind"
grep -qE "$FILE_TYPE" <<<"$kind" || { echo "unexpected binary type: $kind" >&2; exit 1; }
if [ "$RUN_CHECK" = true ]; then
"$binary" --help > /dev/null
fi
gzip "$binary"

- name: Upload artifact
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
with:
name: binaries-${{ matrix.asset_suffix }}
path: release/*.gz
if-no-files-found: error

publish:
name: Publish
needs: build
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: write
concurrency:
group: publish
steps:
- name: Resolve tag
id: v
env:
TAG: ${{ inputs.tag_name }}
DRY_RUN: ${{ inputs.dry_run || false }}
run: |
set -euo pipefail
if [ "$DRY_RUN" != true ]; then
[[ "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]] || { echo "tag_name must be vX.Y.Z, got: $TAG" >&2; exit 1; }
fi
echo "tag=$TAG" >> "$GITHUB_OUTPUT"

- name: Download binaries
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8
with:
path: dist
pattern: binaries-*
merge-multiple: true

# graph-node for both Linux targets.
- name: Checksum binaries
working-directory: dist
run: |
set -euo pipefail
shopt -s nullglob
archives=(*.gz)
[ "${#archives[@]}" -eq 2 ] || { echo "expected 2 archives, found ${#archives[@]}" >&2; exit 1; }
sha256sum -- "${archives[@]}" > SHA256SUMS
cat SHA256SUMS

- name: Upload release bundle
if: inputs.dry_run
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
with:
name: release-bundle
path: dist/*

- name: Attach to release
if: ${{ !inputs.dry_run }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail
gh release upload "${{ steps.v.outputs.tag }}" --repo "$GITHUB_REPOSITORY" --clobber \
dist/*.gz dist/SHA256SUMS

- name: Summary
env:
DRY_RUN: ${{ inputs.dry_run || false }}
run: |
set -euo pipefail
{
if [ "$DRY_RUN" = true ]; then
echo "### Dry run for ${{ steps.v.outputs.tag }}: release left untouched"
else
echo "### graph-node ${{ steps.v.outputs.tag }}"
echo "https://github.com/${GITHUB_REPOSITORY}/releases/tag/${{ steps.v.outputs.tag }}"
fi
echo '```'
cat dist/SHA256SUMS
echo '```'
} >> "$GITHUB_STEP_SUMMARY"
30 changes: 27 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,16 @@ on:
permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}

jobs:
release-please:
name: Release Please
runs-on: ubuntu-latest
timeout-minutes: 5
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
outputs:
release_created: ${{ steps.release.outputs.release_created }}
tag_name: ${{ steps.release.outputs.tag_name }}
steps:
# A pull request opened with GITHUB_TOKEN does not trigger workflows, so
# the release PR is opened as the app instead.
Expand Down Expand Up @@ -47,3 +49,25 @@ jobs:
else
echo "Nothing to release" >> "$GITHUB_STEP_SUMMARY"
fi

publish:
name: Publish binaries
needs: release-please
if: needs.release-please.outputs.release_created == 'true'
permissions:
contents: write
uses: ./.github/workflows/publish.yml
with:
tag_name: ${{ needs.release-please.outputs.tag_name }}

docker:
name: Docker images
needs: release-please
if: needs.release-please.outputs.release_created == 'true'
permissions:
contents: read
packages: write
uses: ./.github/workflows/docker.yml
secrets: inherit
with:
tag_name: ${{ needs.release-please.outputs.tag_name }}
2 changes: 1 addition & 1 deletion docker/build.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#! /bin/bash

# This file is only here to ease testing/development. Official images are
# built using the 'cloudbuild.yaml' file
# built by the .github/workflows/docker.yml workflow

type -p podman > /dev/null && docker=podman || docker=docker

Expand Down
Loading