diff --git a/docker/.dockerignore b/.dockerignore similarity index 85% rename from docker/.dockerignore rename to .dockerignore index 3645101174c..fae64da0fe6 100644 --- a/docker/.dockerignore +++ b/.dockerignore @@ -2,4 +2,5 @@ target Dockerfile .dockerignore .git +.github .gitignore diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 27307df1af9..65dfc8f488a 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -2,22 +2,31 @@ name: CD on: workflow_dispatch: + inputs: + network: + default: 'Mainnet' + checkpoint_sync: + default: true push: branches: - main env: + CARGO_INCREMENTAL: '1' + NETWORK: Mainnet PROJECT_ID: ${{ secrets.GCP_PROJECT_ID }} - REGION: us-east1 - ZONE: us-east1-b - MACHINE_TYPE: n2d-standard-4 - DEPLOY_SA: cos-vm@${{ secrets.GCP_PROJECT_ID }}.iam.gserviceaccount.com + GAR_BASE: us-docker.pkg.dev/${{ secrets.GCP_PROJECT_ID }}/zebra + GCR_BASE: gcr.io/${{ secrets.GCP_PROJECT_ID }} + REGION: us-central1 + ZONE: us-central1-a + MACHINE_TYPE: c2-standard-4 jobs: build: name: Build images timeout-minutes: 60 runs-on: ubuntu-latest + steps: - uses: actions/checkout@v2.4.0 with: @@ -27,25 +36,61 @@ jobs: uses: rlespinasse/github-slug-action@v4 # Setup gcloud CLI - - name: Set up gcloud SDK environment - uses: google-github-actions/setup-gcloud@v0.5.0 + - name: Authenticate to Google Cloud + id: auth + uses: google-github-actions/auth@v0.5.0 + with: + credentials_json: ${{ secrets.GOOGLE_CREDENTIALS }} + + # Setup Docker Buildx to allow use of docker cache layers from GH + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + + - name: Login to Google Artifact Registry + uses: docker/login-action@v1.12.0 + with: + registry: us-docker.pkg.dev + username: _json_key + password: ${{ secrets.GOOGLE_CREDENTIALS }} + + - name: Login to Google Container Registry + uses: docker/login-action@v1.12.0 + with: + registry: gcr.io + username: _json_key + password: ${{ secrets.GOOGLE_CREDENTIALS }} + + # Build and push image to Google Artifact Registry + - name: Build & push + id: docker_build + uses: docker/build-push-action@v2.8.0 with: - project_id: ${{ env.PROJECT_ID }} - service_account_key: ${{ secrets.GCLOUD_AUTH }} - - # Build and push image to Google Container Registry - - name: Build - # Tagging w/ the commit SHA blocks the :latest tag on GCR - run: | - gcloud builds submit \ - --config cloudbuild.yaml \ - --substitutions SHORT_SHA="${{ env.GITHUB_SHA_SHORT }}",BRANCH_NAME="${{ env.GITHUB_HEAD_REF_SLUG || env.GITHUB_REF_SLUG }}" - - deploy: - name: Deploy mainnet nodes + target: runtime + context: . + file: ./docker/Dockerfile.build + tags: | + ${{ env.GAR_BASE }}/${{ env.GITHUB_HEAD_REF_SLUG || env.GITHUB_REF_SLUG }}:latest + ${{ env.GAR_BASE }}/${{ env.GITHUB_HEAD_REF_SLUG || env.GITHUB_REF_SLUG }}:${{ env.GITHUB_SHA_SHORT }} + ${{ env.GCR_BASE }}/${{ env.GITHUB_REPOSITORY_SLUG_URL }}/${{ env.GITHUB_REPOSITORY_SLUG_URL }}/${{ env.GITHUB_HEAD_REF_SLUG || env.GITHUB_REF_SLUG }}:latest + ${{ env.GCR_BASE }}/${{ env.GITHUB_REPOSITORY_SLUG_URL }}/${{ env.GITHUB_REPOSITORY_SLUG_URL }}/${{ env.GITHUB_HEAD_REF_SLUG || env.GITHUB_REF_SLUG }}:${{ env.GITHUB_SHA_SHORT }} + build-args: | + NETWORK=${{ github.event.inputs.network || env.NETWORK }} + SHORT_SHA=${{ env.GITHUB_SHA_SHORT }} + RUST_BACKTRACE=1 + ZEBRA_SKIP_IPV6_TESTS="1" + CHECKPOINT_SYNC=${{ github.event.inputs.checkpoint_sync || true }} + SENTRY_DSN=${{ secrets.SENTRY_ENDPOINT }} + push: true + cache-from: type=gha + cache-to: type=gha,mode=max + + deploy-nodes: + name: Deploy Mainnet nodes needs: build runs-on: ubuntu-latest timeout-minutes: 30 + if: github.event_name == 'push' && github.ref == 'ref/head/main' + steps: - uses: actions/checkout@v2.4.0 with: @@ -55,23 +100,27 @@ jobs: uses: rlespinasse/github-slug-action@v4 # Setup gcloud CLI + - name: Authenticate to Google Cloud + id: auth + uses: google-github-actions/auth@v0.5.0 + with: + credentials_json: ${{ secrets.GOOGLE_CREDENTIALS }} + - name: Set up gcloud SDK environment uses: google-github-actions/setup-gcloud@v0.5.0 with: project_id: ${{ env.PROJECT_ID }} - service_account_key: ${{ secrets.GCLOUD_AUTH }} - # Create instance template from container image - name: Create instance template run: | - gcloud compute instance-templates create-with-container "zebrad-${{ env.GITHUB_HEAD_REF_SLUG || env.GITHUB_REF_SLUG }}-${{ env.GITHUB_SHA_SHORT }}" \ - --container-image "gcr.io/${{ env.PROJECT_ID}}/${{ env.GITHUB_REPOSITORY_NAME_PART_SLUG }}/${{ env.GITHUB_HEAD_REF_SLUG || env.GITHUB_REF_SLUG }}:${{ env.GITHUB_SHA_SHORT }}" \ - --create-disk name=zebrad-cache-${{ env.GITHUB_SHA_SHORT }},auto-delete=yes,size=100GB,type=pd-balanced \ + gcloud compute instance-templates create-with-container zebrad-${{ env.GITHUB_HEAD_REF_SLUG || env.GITHUB_REF_SLUG }}-${{ env.GITHUB_SHA_SHORT }} \ + --boot-disk-type=pd-ssd \ + --container-image ${{ env.GAR_BASE }}/${{ env.GITHUB_HEAD_REF_SLUG || env.GITHUB_REF_SLUG }}:${{ env.GITHUB_SHA_SHORT }} \ + --create-disk name=zebrad-cache-${{ env.GITHUB_SHA_SHORT }},auto-delete=yes,size=100GB,type=pd-ssd \ --container-mount-disk mount-path="/zebrad-cache",name=zebrad-cache-${{ env.GITHUB_SHA_SHORT }} \ --machine-type ${{ env.MACHINE_TYPE }} \ - --service-account ${{ env.DEPLOY_SA }} \ --scopes cloud-platform \ - --tags zebrad \ + --tags zebrad # Check if our destination instance group exists already - name: Check if instance group exists @@ -100,3 +149,45 @@ jobs: "zebrad-${{ env.GITHUB_HEAD_REF_SLUG || env.GITHUB_REF_SLUG }}" \ --version template="zebrad-${{ env.GITHUB_HEAD_REF_SLUG || env.GITHUB_REF_SLUG }}-${{ env.GITHUB_SHA_SHORT }}" \ --region "${{ env.REGION }}" + + deploy-instance: + name: Deploy single instance + needs: build + runs-on: ubuntu-latest + timeout-minutes: 30 + if: github.event_name == 'workflow_dispatch' + + steps: + - uses: actions/checkout@v2.4.0 + with: + persist-credentials: false + + - name: Inject slug/short variables + uses: rlespinasse/github-slug-action@v4 + + # Setup gcloud CLI + - name: Authenticate to Google Cloud + id: auth + uses: google-github-actions/auth@v0.5.0 + with: + credentials_json: ${{ secrets.GOOGLE_CREDENTIALS }} + + - name: Set up gcloud SDK environment + uses: google-github-actions/setup-gcloud@v0.5.0 + with: + project_id: ${{ env.PROJECT_ID }} + + # Create instance template from container image + - name: Manual deploy of a single instance running zebrad + run: | + gcloud compute instances create-with-container "zebrad-${{ env.GITHUB_HEAD_REF_SLUG || env.GITHUB_REF_SLUG }}-${{ env.GITHUB_SHA_SHORT }}" \ + --boot-disk-size 100GB \ + --boot-disk-type=pd-ssd \ + --container-stdin \ + --container-tty \ + --container-image ${{ env.GAR_BASE }}/${{ env.GITHUB_HEAD_REF_SLUG || env.GITHUB_REF_SLUG }}:${{ env.GITHUB_SHA_SHORT }} \ + --create-disk name=zebrad-cache-${{ env.GITHUB_SHA_SHORT }},auto-delete=yes,size=100GB,type=pd-ssd \ + --container-mount-disk mount-path='/zebrad-cache',name=zebrad-cache-${{ env.GITHUB_SHA_SHORT }} \ + --machine-type ${{ env.MACHINE_TYPE }} \ + --zone ${{ env.ZONE }} \ + --tags zebrad diff --git a/.github/workflows/manual-deploy.yml b/.github/workflows/manual-deploy.yml deleted file mode 100644 index bb19baf752c..00000000000 --- a/.github/workflows/manual-deploy.yml +++ /dev/null @@ -1,53 +0,0 @@ -name: Manual Deploy - -on: - workflow_dispatch: - inputs: - network: - default: 'Mainnet' - checkpoint_sync: - default: true - -env: - PROJECT_ID: ${{ secrets.GCP_PROJECT_ID }} - ZONE: us-central1-a - MACHINE_TYPE: n2-standard-4 - DEPLOY_SA: cos-vm@${{ secrets.GCP_PROJECT_ID }}.iam.gserviceaccount.com - -jobs: - deploy: - name: Deploy one zebrad node - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2.4.0 - with: - persist-credentials: false - - - name: Inject slug/short variables - uses: rlespinasse/github-slug-action@v4 - - - name: Set up gcloud - uses: google-github-actions/setup-gcloud@v0.5.0 - with: - project_id: ${{ env.PROJECT_ID }} - service_account_key: ${{ secrets.GCLOUD_AUTH }} - - # Build and push image to Google Container Registry - - name: Build - # Tagging w/ the commit SHA blocks the :latest tag on GCR - run: | - gcloud builds submit \ - --config cloudbuild.yaml \ - --substitutions SHORT_SHA="${{ env.GITHUB_SHA_SHORT }}",BRANCH_NAME="${{ env.GITHUB_HEAD_REF_SLUG || env.GITHUB_REF_SLUG }}",_CHECKPOINT_SYNC="${{ github.event.inputs.checkpoint_sync }}",_NETWORK="${{ github.event.inputs.network }}" - - # Creates Compute Engine virtual machine instance w/ zebrad container and disks - - name: Create instance running zebrad container image - run: | - gcloud compute instances create-with-container "zebrad-${{ env.GITHUB_HEAD_REF_SLUG || env.GITHUB_REF_SLUG }}-${{ env.GITHUB_SHA_SHORT }}" \ - --container-image "gcr.io/${{ env.PROJECT_ID }}/${{ env.GITHUB_REPOSITORY_NAME_PART_SLUG }}/${{ env.GITHUB_HEAD_REF_SLUG || env.GITHUB_REF_SLUG }}:${{ env.GITHUB_SHA_SHORT }}" \ - --container-mount-disk mount-path='/zebrad-cache',name=zebrad-cache-${{ env.GITHUB_SHA_SHORT }} \ - --create-disk name=zebrad-cache-${{ env.GITHUB_SHA_SHORT }},auto-delete=yes,size=100GB,type=pd-balanced \ - --machine-type ${{ env.MACHINE_TYPE }} \ - --service-account ${{ env.DEPLOY_SA }} \ - --tags zebrad \ - --zone ${{ env.ZONE }} diff --git a/.github/workflows/zcash-params.yml b/.github/workflows/zcash-params.yml new file mode 100644 index 00000000000..fd41437bfe7 --- /dev/null +++ b/.github/workflows/zcash-params.yml @@ -0,0 +1,68 @@ +name: zcash-params + +on: + workflow_dispatch: + pull_request: + path: + - 'zebra-consensus/src/primitives/groth16/params.rs' + - 'zebra-consensus/src/chain.rs' + - 'zebrad/src/commands/start.rs' + - '.github/workflows/zcash-params.yml' + +env: + CARGO_INCREMENTAL: '1' + PROJECT_ID: ${{ secrets.GCP_PROJECT_ID }} + GAR_BASE: us-docker.pkg.dev/${{ secrets.GCP_PROJECT_ID }}/zebra + GCR_BASE: gcr.io/${{ secrets.GCP_PROJECT_ID }} + IMAGE_NAME: zcash-params + +jobs: + build: + name: Build images + timeout-minutes: 60 + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2.4.0 + with: + persist-credentials: false + + - name: Inject slug/short variables + uses: rlespinasse/github-slug-action@v4 + + # Setup gcloud CLI + - name: Authenticate to Google Cloud + id: auth + uses: google-github-actions/auth@v0.5.0 + with: + credentials_json: ${{ secrets.GOOGLE_CREDENTIALS }} + + # Setup Docker Buildx to allow use of docker cache layers from GH + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + + - name: Login to Google Artifact Registry + uses: docker/login-action@v1.12.0 + with: + registry: us-docker.pkg.dev + username: _json_key + password: ${{ secrets.GOOGLE_CREDENTIALS }} + + # Build and push image to Google Artifact Registry + - name: Build & push + id: docker_build + uses: docker/build-push-action@v2.8.0 + with: + target: builder + context: . + file: ./docker/Dockerfile.params + tags: | + ${{ env.GAR_BASE }}/${{ env.IMAGE_NAME }}:latest + ${{ env.GAR_BASE }}/${{ env.IMAGE_NAME }}:${{ env.GITHUB_SHA_SHORT }} + build-args: | + SHORT_SHA=${{ env.GITHUB_SHA_SHORT }} + ZEBRA_SKIP_IPV6_TESTS="1" + SENTRY_DSN=${{ secrets.SENTRY_ENDPOINT }} + push: true + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/.github/workflows/zcashd-manual-deploy.yml b/.github/workflows/zcashd-manual-deploy.yml index 3cb14bfbe95..927ac5e6d67 100644 --- a/.github/workflows/zcashd-manual-deploy.yml +++ b/.github/workflows/zcashd-manual-deploy.yml @@ -71,4 +71,4 @@ jobs: gcloud compute instance-groups managed rolling-action start-update \ "zcashd-${{ env.GITHUB_HEAD_REF_SLUG || env.GITHUB_REF_SLUG }}-${{ github.event.inputs.network }}" \ --version template="zcashd-${{ env.GITHUB_HEAD_REF_SLUG || env.GITHUB_REF_SLUG }}-${{ env.GITHUB_SHA_SHORT }}" \ - --region "${{ env.REGION }}" + --region "${{ env.REGION }}" \ No newline at end of file diff --git a/cloudbuild.yaml b/cloudbuild.yaml deleted file mode 100644 index f09a10e0292..00000000000 --- a/cloudbuild.yaml +++ /dev/null @@ -1,25 +0,0 @@ -steps: -- name: 'gcr.io/cloud-builders/docker' - args: ['build', - '--build-arg', - 'SHORT_SHA=$SHORT_SHA', - '--build-arg', - 'checkpoint_sync=${_CHECKPOINT_SYNC}', - '--build-arg', - 'network=${_NETWORK}', - '--target', - 'zebrad-release', - '-t', - 'gcr.io/$PROJECT_ID/zcashfoundation/zebra/$BRANCH_NAME:$SHORT_SHA', - '-f', - 'docker/Dockerfile.build', - '.'] - -images: -- 'gcr.io/$PROJECT_ID/zcashfoundation/zebra/$BRANCH_NAME:$SHORT_SHA' - -options: - machineType: 'N1_HIGHCPU_32' - substitution_option: 'ALLOW_LOOSE' - -timeout: 3600s # 60 mins diff --git a/docker/Dockerfile.build b/docker/Dockerfile.build index 31e1d1c04a2..b599474afe5 100644 --- a/docker/Dockerfile.build +++ b/docker/Dockerfile.build @@ -1,56 +1,102 @@ -# Builder image -FROM rust:buster as builder - -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - make cmake g++ gcc llvm libclang-dev clang ca-certificates +# This steps implement cargo-chef for docker layer caching +# We are using four stages: +# - chef: installs cargo-chef +# - planner: computes the recipe file +# - builder: caches our dependencies and builds the binary +# - tester: builds and run tests +# - runtime: is our runtime environment +FROM rust:bullseye as chef +RUN cargo install cargo-chef --locked +WORKDIR /app + +FROM chef AS planner +COPY . . +RUN cargo chef prepare --recipe-path recipe.json + +FROM chef AS builder +COPY --from=planner /app/recipe.json recipe.json + +# Install zebra build deps +RUN apt-get -qq update && \ + apt-get -qq install -y --no-install-recommends \ + llvm \ + libclang-dev \ + clang \ + ca-certificates \ + ; \ + rm -rf /var/lib/apt/lists/* /tmp/* + +# Install google OS Config agent +RUN apt-get -qq update && \ + apt-get -qq install -y --no-install-recommends \ + curl \ + lsb-release \ + ; \ + echo "deb http://packages.cloud.google.com/apt google-compute-engine-$(lsb_release -cs)-stable main" > /etc/apt/sources.list.d/google-compute-engine.list && \ + curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add - && \ + apt-get -qq update && \ + apt-get -qq install -y --no-install-recommends google-osconfig-agent && \ + rm -rf /var/lib/apt/lists/* /tmp/* + +# Optimize builds. In particular, regenerate-stateful-test-disks.yml was reaching the +# GitHub Actions time limit (6 hours), so we needed to make it faster. +ENV RUSTFLAGS -O +ENV CARGO_HOME /app/.cargo/ +# Build dependencies - this is the caching Docker layer! +RUN cargo chef cook --release --features enable-sentry --recipe-path recipe.json + +ARG RUST_BACKTRACE=1 +ENV RUST_BACKTRACE ${RUST_BACKTRACE} -RUN mkdir /zebra -WORKDIR /zebra +COPY . . +# Build zebra +RUN cargo build --locked --release --features enable-sentry --bin zebrad -ARG SHORT_SHA -ENV SHORT_SHA $SHORT_SHA +FROM builder AS tester +# Pre-download Zcash Sprout and Sapling parameters +# TODO: do not hardcode the user /root/ even though is a safe assumption +COPY --from=us-docker.pkg.dev/zealous-zebra/zebra/zcash-params /root/.zcash-params /root/.zcash-params -ENV RUST_BACKTRACE full -ENV CARGO_HOME /zebra/.cargo/ +# Skip IPv6 tests by default, as some CI environment don't have IPv6 available +ARG ZEBRA_SKIP_IPV6_TESTS=1 +ENV ZEBRA_SKIP_IPV6_TESTS ${ZEBRA_SKIP_IPV6_TESTS} -RUN rustc -V; cargo -V; rustup -V +RUN cargo test --locked --release --features enable-sentry --workspace --no-run -COPY . . - -RUN cd zebrad/; cargo build --release --features enable-sentry +CMD ["cargo" "test" "--locked" "--release" "--features" "enable-sentry" "--workspace"] # Runner image -FROM debian:buster-slim AS zebrad-release +FROM debian:bullseye-slim AS runtime +COPY --from=builder /app/target/release/zebrad /usr/local/bin +COPY --from=us-docker.pkg.dev/zealous-zebra/zebra/zcash-params /root/.zcash-params /root/.zcash-params RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - ca-certificates - -COPY --from=builder /zebra/target/release/zebrad / + apt-get install -y --no-install-recommends \ + ca-certificates ARG CHECKPOINT_SYNC=true ARG NETWORK=Mainnet -RUN printf "[consensus]\n" >> /zebrad.toml -RUN printf "checkpoint_sync = ${CHECKPOINT_SYNC}\n" >> /zebrad.toml -RUN printf "[metrics]\n" >> /zebrad.toml -RUN printf "endpoint_addr = '0.0.0.0:9999'\n" >> /zebrad.toml -RUN printf "[network]\n" >> /zebrad.toml -RUN printf "network = '${NETWORK}'\n" >> /zebrad.toml -RUN printf "[state]\n" >> /zebrad.toml -RUN printf "cache_dir = '/zebrad-cache'\n" >> /zebrad.toml -RUN printf "[tracing]\n" >> /zebrad.toml -RUN printf "endpoint_addr = '0.0.0.0:3000'\n" >> /zebrad.toml -RUN cat /zebrad.toml - -# Pre-download Zcash Sprout and Sapling parameters -RUN /zebrad download +RUN set -ex; \ + { \ + echo "[consensus]"; \ + echo "checkpoint_sync = ${CHECKPOINT_SYNC}"; \ + echo "[metrics]"; \ + echo "endpoint_addr = '0.0.0.0:9999'"; \ + echo "[network]"; \ + echo "network = '${NETWORK}'"; \ + echo "[state]"; \ + echo "cache_dir = '/zebrad-cache'"; \ + echo "[tracing]"; \ + echo "endpoint_addr = '0.0.0.0:3000'"; \ + } > "zebrad.toml" EXPOSE 3000 8233 18233 -ENV RUST_LOG debug -ENV RUST_BACKTRACE full -ENV SENTRY_DSN https://94059ee72a44420286310990b7c614b5@o485484.ingest.sentry.io/5540918 +ARG SHORT_SHA +ENV SHORT_SHA $SHORT_SHA + +ARG SENTRY_DSN +ENV SENTRY_DSN ${SENTRY_DSN} -CMD [ "/zebrad", "-c", "/zebrad.toml", "start" ] +CMD [ "zebrad", "-c", "zebrad.toml", "start" ] diff --git a/docker/Dockerfile.params b/docker/Dockerfile.params new file mode 100644 index 00000000000..13d86691f68 --- /dev/null +++ b/docker/Dockerfile.params @@ -0,0 +1,36 @@ +# This steps implement cargo-chef for docker layer caching +# This image is for caching Zcash Sprout and Sapling parameters +FROM rust:bullseye as chef +RUN cargo install cargo-chef --locked +WORKDIR /app + +FROM chef AS planner +COPY . . +RUN cargo chef prepare --recipe-path recipe.json + +FROM chef AS builder +COPY --from=planner /app/recipe.json recipe.json + +# Install zebra build deps +RUN apt-get -qq update && \ + apt-get -qq install -y --no-install-recommends \ + llvm \ + libclang-dev \ + clang \ + ca-certificates \ + ; \ + rm -rf /var/lib/apt/lists/* /tmp/* + +# Optimize builds. In particular, regenerate-stateful-test-disks.yml was reaching the +# GitHub Actions time limit (6 hours), so we needed to make it faster. +ENV RUSTFLAGS -O +ENV CARGO_HOME /app/.cargo/ +# Build dependencies - this is the caching Docker layer! +RUN cargo chef cook --release --features enable-sentry --recipe-path recipe.json + +ARG RUST_BACKTRACE=1 +ENV RUST_BACKTRACE ${RUST_BACKTRACE} + +COPY . . +# Pre-download Zcash Sprout and Sapling parameters +RUN cargo run --locked --release --features enable-sentry --bin zebrad download