diff --git a/.github/workflows/release-push-image.yaml b/.github/workflows/release-push-image.yaml index 85425f719..be5bb27d8 100644 --- a/.github/workflows/release-push-image.yaml +++ b/.github/workflows/release-push-image.yaml @@ -43,6 +43,22 @@ env: REGISTRY: ghcr.io jobs: +# check-gradle: +# name: Gradle +# uses: ./.github/workflows/zxc-verify-gradle-build-determinism.yaml +# with: +# ref: ${{ github.event.inputs.ref || '' }} +# java-distribution: ${{ inputs.java-distribution || 'temurin' }} +# java-version: ${{ inputs.java-version || '21.0.4' }} + +# check-docker: +# name: Docker +# uses: ./.github/workflows/zxc-verify-docker-build-determinism.yaml +# with: +# ref: ${{ github.event.inputs.ref || '' }} +# java-distribution: ${{ inputs.java-distribution || 'temurin' }} +# java-version: ${{ inputs.java-version || '21.0.4' }} + publish: runs-on: block-node-linux-medium diff --git a/.github/workflows/support/scripts/generate-docker-artifact-baseline.sh b/.github/workflows/support/scripts/generate-docker-artifact-baseline.sh new file mode 100755 index 000000000..b40966c62 --- /dev/null +++ b/.github/workflows/support/scripts/generate-docker-artifact-baseline.sh @@ -0,0 +1,200 @@ +#!/usr/bin/env bash +set -o pipefail +set +e + +readonly DOCKER_IMAGE_NAME="server" + +GROUP_ACTIVE="false" + +function fail { + printf '%s\n' "$1" >&2 ## Send message to stderr. Exclude >&2 if you don't want it that way. + if [[ "${GROUP_ACTIVE}" == "true" ]]; then + end_group + fi + exit "${2-1}" ## Return a code specified by $2 or 1 by default. +} + +function start_group { + if [[ "${GROUP_ACTIVE}" == "true" ]]; then + end_group + fi + + GROUP_ACTIVE="true" + printf "::group::%s\n" "${1}" +} + +function end_group { + GROUP_ACTIVE="false" + printf "::endgroup::\n" +} + +function log { + local message="${1}" + shift + # shellcheck disable=SC2059 + printf "${message}" "${@}" +} + +function log_line { + local message="${1}" + shift + # shellcheck disable=SC2059 + printf "${message}\n" "${@}" +} + +function start_task { + local message="${1}" + shift + # shellcheck disable=SC2059 + printf "${message} .....\t" "${@}" +} + +function end_task { + printf "%s\n" "${1:-DONE}" +} + +start_group "Configuring Environment" + # Access workflow environment variables + export GITHUB_WORKSPACE GITHUB_SHA GITHUB_OUTPUT MANIFEST_PATH DOCKER_REGISTRY DOCKER_TAG SKOPEO_VERSION SKOPEO_IMAGE_NAME + + start_task "Initializing Temporary Directory" + TEMP_DIR="$(mktemp -d)" || fail "ERROR (Exit Code: ${?})" "${?}" + trap 'rm -rf "${TEMP_DIR}"' EXIT + end_task "DONE (Path: ${TEMP_DIR})" + +# start_task "Resolving the GITHUB_WORKSPACE path" +# # Ensure GITHUB_WORKSPACE is provided or default to the repository root +# if [[ -z "${GITHUB_WORKSPACE}" || ! -d "${GITHUB_WORKSPACE}" ]]; then +# GITHUB_WORKSPACE="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../../../" && pwd)" +# fi +# end_task "DONE (Path: ${GITHUB_WORKSPACE})" +# +# start_task "Resolving the GITHUB_OUTPUT path" +# # Ensure GITHUB_OUTPUT is provided or default to the repository root +# if [[ -z "${GITHUB_OUTPUT}" ]]; then +# GITHUB_OUTPUT="${TEMP_DIR}/workflow-output.txt" +# fi +# end_task "DONE (Path: ${GITHUB_OUTPUT})" +# +# start_task "Resolving the GITHUB_SHA hash" +# if [[ -z "${GITHUB_SHA}" ]]; then +# GITHUB_SHA="$(git rev-parse HEAD | tr -d '[:space:]')" || fail "ERROR (Exit Code: ${?})" "${?}" +# fi +# end_task "DONE (Commit: ${GITHUB_SHA})" +# +# start_task "Resolving the MANIFEST_PATH variable" +# if [[ -z "${MANIFEST_PATH}" ]]; then +# MANIFEST_PATH="${GITHUB_WORKSPACE}/.manifests/gradle" +# fi +# end_task "DONE (Path: ${MANIFEST_PATH})" +# +# start_task "Ensuring the MANIFEST_PATH location is present" +# if [[ ! -d "${MANIFEST_PATH}" ]]; then +# mkdir -p "${MANIFEST_PATH}" || fail "ERROR (Exit Code: ${?})" "${?}" +# fi +# end_task +# +# start_task "Resolving the SKOPEO_VERSION variable" +# if [[ -z "${SKOPEO_VERSION}" ]]; then +# SKOPEO_VERSION="v1.14.0" +# fi +# end_task "DONE (Version: ${SKOPEO_VERSION})" +# +# start_task "Resolving the SKOPEO_IMAGE_NAME variable" +# if [[ -z "${SKOPEO_IMAGE_NAME}" ]]; then +# SKOPEO_IMAGE_NAME="quay.io/skopeo/stable:${SKOPEO_VERSION}" +# fi +# end_task "DONE (Image Name: ${SKOPEO_IMAGE_NAME})" +# +# start_task "Checking for the DOCKER command" +# if command -v docker >/dev/null 2>&1; then +# DOCKER="$(command -v docker)" || fail "ERROR (Exit Code: ${?})" "${?}" +# export DOCKER +# else +# fail "ERROR (Exit Code: ${?})" "${?}" +# fi +# end_task "DONE (Found: ${DOCKER})" +# +# start_task "Resolving the Docker Client Configuration" +# SKOPEO_BIND_MOUNT="" +# SKOPEO_CREDENTIAL_OPTS="" +# DOCKER_CONFIG_DIR="${HOME}/.docker" +# if [[ -d "${DOCKER_CONFIG_DIR}" ]]; then +# SKOPEO_BIND_MOUNT="--volume ${DOCKER_CONFIG_DIR}:/tmp/docker" +# SKOPEO_CREDENTIAL_OPTS="--authfile /tmp/docker/config.json" +# fi +# export SKOPEO_BIND_MOUNT SKOPEO_CREDENTIAL_OPTS +# end_task "DONE" +# +# start_task "Checking for the SKOPEO command" +# if command -v skopeo >/dev/null 2>&1; then +# SKOPEO="$(command -v skopeo)" || fail "ERROR (Exit Code: ${?})" "${?}" +# export SKOPEO +# else +# ${DOCKER} pull "${SKOPEO_IMAGE_NAME}" >/dev/null 2>&1 || fail "ERROR (Exit Code: ${?})" "${?}" +# SKOPEO="${DOCKER} run ${SKOPEO_BIND_MOUNT} --rm --network host ${SKOPEO_IMAGE_NAME}" +# export SKOPEO +# fi +# end_task "DONE (Found: ${SKOPEO})" +# +# start_task "Checking for the JQ command" +# if command -v jq >/dev/null 2>&1; then +# JQ="$(command -v jq)" || fail "ERROR (Exit Code: ${?})" "${?}" +# export JQ +# else +# fail "ERROR (Exit Code: ${?})" "${?}" +# fi +# end_task "DONE (Found: ${JQ})" +#end_group +# +#start_group "Prepare the Docker Image Information" +# start_task "Resolving the DOCKER_REGISTRY variable" +# if [[ -z "${DOCKER_REGISTRY}" ]]; then +# DOCKER_REGISTRY="localhost:5000" +# fi +# end_task "DONE (Registry: ${DOCKER_REGISTRY})" +# +# start_task "Resolving the DOCKER_TAG variable" +# if [[ -z "${DOCKER_TAG}" ]]; then +# DOCKER_TAG="$(echo "${GITHUB_SHA}" | tr -d '[:space:]' | cut -c1-8)" +# fi +# end_task "DONE (Tag: ${DOCKER_TAG})" +# +# start_task "Resolving the Fully Qualified Image Name" +# FQ_IMAGE_NAME="${DOCKER_REGISTRY}/${DOCKER_IMAGE_NAME}:${DOCKER_TAG}" +# end_task "DONE (Image: ${FQ_IMAGE_NAME})" +#end_group +# +#start_group "Generate Docker Image Manifest (linux/amd64)" +# ${SKOPEO} --override-os linux --override-arch amd64 inspect ${SKOPEO_CREDENTIAL_OPTS} --tls-verify=false "docker://${FQ_IMAGE_NAME}" | tee "${TEMP_DIR}/linux-amd64.manifest.json" || fail "SKOPEO ERROR (Exit Code: ${?})" "${?}" +# ${JQ} -r '.Layers[]' "${TEMP_DIR}/linux-amd64.manifest.json" | tee "${TEMP_DIR}/linux-amd64.layers.json" >/dev/null 2>&1 || fail "JQ LAYER ERROR (Exit Code: ${?})" "${?}" +# ${JQ} -r 'del(.RepoTags) | del(.LayersData) | del(.Digest) | del(.Name)' "${TEMP_DIR}/linux-amd64.manifest.json" | tee "${TEMP_DIR}/linux-amd64.comparable.json" >/dev/null 2>&1 || fail "JQ COMP ERROR (Exit Code: ${?})" "${?}" +#end_group +# +#start_group "Generate Docker Image Manifest (linux/arm64)" +# ${SKOPEO} --override-os linux --override-arch arm64 inspect ${SKOPEO_CREDENTIAL_OPTS} --tls-verify=false "docker://${FQ_IMAGE_NAME}" | tee "${TEMP_DIR}/linux-arm64.manifest.json" || fail "SKOPEO ERROR (Exit Code: ${?})" "${?}" +# ${JQ} -r '.Layers[]' "${TEMP_DIR}/linux-arm64.manifest.json" | tee "${TEMP_DIR}/linux-arm64.layers.json" >/dev/null 2>&1 || fail "JQ LAYER ERROR (Exit Code: ${?})" "${?}" +# ${JQ} -r 'del(.RepoTags) | del(.LayersData) | del(.Digest) | del(.Name)' "${TEMP_DIR}/linux-arm64.manifest.json" | tee "${TEMP_DIR}/linux-arm64.comparable.json" >/dev/null 2>&1 || fail "JQ COMP ERROR (Exit Code: ${?})" "${?}" +#end_group +# +#start_group "Generating Final Release Manifests" +# +# start_task "Generating the manifest archive" +# MANIFEST_FILES=("linux-amd64.manifest.json" "linux-amd64.layers.json" "linux-amd64.comparable.json") +# MANIFEST_FILES+=("linux-arm64.manifest.json" "linux-arm64.layers.json" "linux-arm64.comparable.json") +# tar -czf "${TEMP_DIR}/manifest.tar.gz" -C "${TEMP_DIR}" "${MANIFEST_FILES[@]}" >/dev/null 2>&1 || fail "TAR ERROR (Exit Code: ${?})" "${?}" +# end_task +# +# start_task "Copying the manifest files" +# cp "${TEMP_DIR}/manifest.tar.gz" "${MANIFEST_PATH}/${GITHUB_SHA}.tar.gz" || fail "COPY ERROR (Exit Code: ${?})" "${?}" +# cp "${TEMP_DIR}"/*.json "${MANIFEST_PATH}/" || fail "COPY ERROR (Exit Code: ${?})" "${?}" +# end_task "DONE (Path: ${MANIFEST_PATH}/${GITHUB_SHA}.tar.gz)" +# +# start_task "Setting Step Outputs" +# { +# printf "path=%s\n" "${MANIFEST_PATH}" +# printf "file=%s\n" "${MANIFEST_PATH}/${GITHUB_SHA}.tar.gz" +# printf "name=%s\n" "${GITHUB_SHA}.tar.gz" +# } >> "${GITHUB_OUTPUT}" +# end_task +end_group diff --git a/.github/workflows/support/scripts/generate-gradle-artifact-baseline.sh b/.github/workflows/support/scripts/generate-gradle-artifact-baseline.sh index b0fe6ebe2..3b4168771 100755 --- a/.github/workflows/support/scripts/generate-gradle-artifact-baseline.sh +++ b/.github/workflows/support/scripts/generate-gradle-artifact-baseline.sh @@ -2,8 +2,7 @@ set -o pipefail set +e -readonly RELEASE_LIB_PATH="hedera-node/data/lib" -readonly RELEASE_APPS_PATH="hedera-node/data/apps" +readonly RELEASE_APPS_PATH="server/build/libs" GROUP_ACTIVE="false" @@ -63,86 +62,74 @@ start_group "Configuring Environment" trap 'rm -rf "${TEMP_DIR}"' EXIT end_task "DONE (Path: ${TEMP_DIR})" -# start_task "Resolving the GITHUB_WORKSPACE path" -# # Ensure GITHUB_WORKSPACE is provided or default to the repository root -# if [[ -z "${GITHUB_WORKSPACE}" || ! -d "${GITHUB_WORKSPACE}" ]]; then -# GITHUB_WORKSPACE="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../../../" && pwd)" -# fi -# end_task "DONE (Path: ${GITHUB_WORKSPACE})" -# -# start_task "Resolving the GITHUB_OUTPUT path" -# # Ensure GITHUB_OUTPUT is provided or default to the repository root -# if [[ -z "${GITHUB_OUTPUT}" ]]; then -# GITHUB_OUTPUT="${TEMP_DIR}/workflow-output.txt" -# fi -# end_task "DONE (Path: ${GITHUB_OUTPUT})" -# -# start_task "Resolving the GITHUB_SHA hash" -# if [[ -z "${GITHUB_SHA}" ]]; then -# GITHUB_SHA="$(git rev-parse HEAD | tr -d '[:space:]')" || fail "ERROR (Exit Code: ${?})" "${?}" -# fi -# end_task "DONE (Commit: ${GITHUB_SHA})" -# -# start_task "Resolving the MANIFEST_PATH variable" -# if [[ -z "${MANIFEST_PATH}" ]]; then -# MANIFEST_PATH="${GITHUB_WORKSPACE}/.manifests/gradle" -# fi -# end_task "DONE (Path: ${MANIFEST_PATH})" -# -# start_task "Ensuring the MANIFEST_PATH location is present" -# if [[ ! -d "${MANIFEST_PATH}" ]]; then -# mkdir -p "${MANIFEST_PATH}" || fail "ERROR (Exit Code: ${?})" "${?}" -# fi -# end_task -# -# start_task "Checking for the sha256sum command" -# if command -v sha256sum >/dev/null 2>&1; then -# SHA256SUM="$(command -v sha256sum)" || fail "ERROR (Exit Code: ${?})" "${?}" -# else -# fail "ERROR (Exit Code: ${?})" "${?}" -# fi -# end_task "DONE (Found: ${SHA256SUM})" -# -# start_task "Checking for prebuilt libraries" -# ls -al "${GITHUB_WORKSPACE}/${RELEASE_LIB_PATH}"/*.jar >/dev/null 2>&1 || fail "ERROR (Exit Code: ${?})" "${?}" -# end_task "FOUND (Path: ${GITHUB_WORKSPACE}/${RELEASE_LIB_PATH}/*.jar)" -# -# start_task "Checking for prebuilt applications" -# ls -al "${GITHUB_WORKSPACE}/${RELEASE_APPS_PATH}"/*.jar >/dev/null 2>&1 || fail "ERROR (Exit Code: ${?})" "${?}" -# end_task "FOUND (Path: ${GITHUB_WORKSPACE}/${RELEASE_APPS_PATH}/*.jar)" + start_task "Resolving the GITHUB_WORKSPACE path" + # Ensure GITHUB_WORKSPACE is provided or default to the repository root + if [[ -z "${GITHUB_WORKSPACE}" || ! -d "${GITHUB_WORKSPACE}" ]]; then + GITHUB_WORKSPACE="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../../../" && pwd)" + fi + end_task "DONE (Path: ${GITHUB_WORKSPACE})" + + start_task "Resolving the GITHUB_OUTPUT path" + # Ensure GITHUB_OUTPUT is provided or default to the repository root + if [[ -z "${GITHUB_OUTPUT}" ]]; then + GITHUB_OUTPUT="${TEMP_DIR}/workflow-output.txt" + fi + end_task "DONE (Path: ${GITHUB_OUTPUT})" + + start_task "Resolving the GITHUB_SHA hash" + if [[ -z "${GITHUB_SHA}" ]]; then + GITHUB_SHA="$(git rev-parse HEAD | tr -d '[:space:]')" || fail "ERROR (Exit Code: ${?})" "${?}" + fi + end_task "DONE (Commit: ${GITHUB_SHA})" + + start_task "Resolving the MANIFEST_PATH variable" + if [[ -z "${MANIFEST_PATH}" ]]; then + MANIFEST_PATH="${GITHUB_WORKSPACE}/.manifests/gradle" + fi + end_task "DONE (Path: ${MANIFEST_PATH})" + + start_task "Ensuring the MANIFEST_PATH location is present" + if [[ ! -d "${MANIFEST_PATH}" ]]; then + mkdir -p "${MANIFEST_PATH}" || fail "ERROR (Exit Code: ${?})" "${?}" + fi + end_task + + start_task "Checking for the sha256sum command" + if command -v sha256sum >/dev/null 2>&1; then + SHA256SUM="$(command -v sha256sum)" || fail "ERROR (Exit Code: ${?})" "${?}" + else + fail "ERROR (Exit Code: ${?})" "${?}" + fi + end_task "DONE (Found: ${SHA256SUM})" + + start_task "Checking for prebuilt applications" + ls -al "${GITHUB_WORKSPACE}/${RELEASE_APPS_PATH}"/*.jar >/dev/null 2>&1 || fail "ERROR (Exit Code: ${?})" "${?}" + end_task "FOUND (Path: ${GITHUB_WORKSPACE}/${RELEASE_APPS_PATH}/*.jar)" +end_group + +start_group "Generating Application Hashes (${GITHUB_WORKSPACE}/${RELEASE_APPS_PATH}/*.jar)" + pushd "${GITHUB_WORKSPACE}/${RELEASE_APPS_PATH}" >/dev/null 2>&1 || fail "PUSHD ERROR (Exit Code: ${?})" "${?}" + ${SHA256SUM} -b -- *.jar | sort -k 2 | tee -a "${TEMP_DIR}"/applications.sha256 + popd >/dev/null 2>&1 || fail "POPD ERROR (Exit Code: ${?})" "${?}" end_group -#start_group "Generating Library Hashes (${GITHUB_WORKSPACE}/${RELEASE_LIB_PATH}/*.jar)" -# pushd "${GITHUB_WORKSPACE}/${RELEASE_LIB_PATH}" >/dev/null 2>&1 || fail "PUSHD ERROR (Exit Code: ${?})" "${?}" -# ${SHA256SUM} -b -- *.jar | sort -k 2 | tee -a "${TEMP_DIR}"/libraries.sha256 -# popd >/dev/null 2>&1 || fail "POPD ERROR (Exit Code: ${?})" "${?}" -#end_group -# -#start_group "Generating Application Hashes (${GITHUB_WORKSPACE}/${RELEASE_APPS_PATH}/*.jar)" -# pushd "${GITHUB_WORKSPACE}/${RELEASE_APPS_PATH}" >/dev/null 2>&1 || fail "PUSHD ERROR (Exit Code: ${?})" "${?}" -# ${SHA256SUM} -b -- *.jar | sort -k 2 | tee -a "${TEMP_DIR}"/applications.sha256 -# popd >/dev/null 2>&1 || fail "POPD ERROR (Exit Code: ${?})" "${?}" -#end_group -# -#start_group "Generating Final Release Manifests" -# -# start_task "Generating the manifest archive" -# tar -czf "${TEMP_DIR}/manifest.tar.gz" -C "${TEMP_DIR}" libraries.sha256 applications.sha256 >/dev/null 2>&1 || fail "TAR ERROR (Exit Code: ${?})" "${?}" -# end_task -# -# start_task "Copying the manifest files" -# cp "${TEMP_DIR}/manifest.tar.gz" "${MANIFEST_PATH}/${GITHUB_SHA}.tar.gz" || fail "COPY ERROR (Exit Code: ${?})" "${?}" -# cp "${TEMP_DIR}/libraries.sha256" "${MANIFEST_PATH}/libraries.sha256" || fail "COPY ERROR (Exit Code: ${?})" "${?}" -# cp "${TEMP_DIR}/applications.sha256" "${MANIFEST_PATH}/applications.sha256" || fail "COPY ERROR (Exit Code: ${?})" "${?}" -# end_task "DONE (Path: ${MANIFEST_PATH}/${GITHUB_SHA}.tar.gz)" -# -# start_task "Setting Step Outputs" -# { -# printf "path=%s\n" "${MANIFEST_PATH}" -# printf "file=%s\n" "${MANIFEST_PATH}/${GITHUB_SHA}.tar.gz" -# printf "name=%s\n" "${GITHUB_SHA}.tar.gz" -# printf "applications=%s\n" "${MANIFEST_PATH}/applications.sha256" -# printf "libraries=%s\n" "${MANIFEST_PATH}/libraries.sha256" -# } >> "${GITHUB_OUTPUT}" -# end_task -#end_group +start_group "Generating Final Release Manifests" + + start_task "Generating the manifest archive" + tar -czf "${TEMP_DIR}/manifest.tar.gz" -C "${TEMP_DIR}" applications.sha256 >/dev/null 2>&1 || fail "TAR ERROR (Exit Code: ${?})" "${?}" + end_task + + start_task "Copying the manifest files" + cp "${TEMP_DIR}/manifest.tar.gz" "${MANIFEST_PATH}/${GITHUB_SHA}.tar.gz" || fail "COPY ERROR (Exit Code: ${?})" "${?}" + cp "${TEMP_DIR}/applications.sha256" "${MANIFEST_PATH}/applications.sha256" || fail "COPY ERROR (Exit Code: ${?})" "${?}" + end_task "DONE (Path: ${MANIFEST_PATH}/${GITHUB_SHA}.tar.gz)" + + start_task "Setting Step Outputs" + { + printf "path=%s\n" "${MANIFEST_PATH}" + printf "file=%s\n" "${MANIFEST_PATH}/${GITHUB_SHA}.tar.gz" + printf "name=%s\n" "${GITHUB_SHA}.tar.gz" + printf "applications=%s\n" "${MANIFEST_PATH}/applications.sha256" + } >> "${GITHUB_OUTPUT}" + end_task +end_group diff --git a/.github/workflows/zxc-verify-docker-build-determinism.yaml b/.github/workflows/zxc-verify-docker-build-determinism.yaml new file mode 100644 index 000000000..79f4c239f --- /dev/null +++ b/.github/workflows/zxc-verify-docker-build-determinism.yaml @@ -0,0 +1,81 @@ +## +# Copyright (C) 2023-2024 Hedera Hashgraph, LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +## +name: "ZXC: Verify Docker Build Determinism" +on: + workflow_call: + inputs: + ref: + description: "The branch, tag, or commit to checkout:" + type: string + required: false + default: "" + java-distribution: + description: "Java JDK Distribution:" + type: string + required: false + default: "temurin" + java-version: + description: "Java JDK Version:" + type: string + required: false + default: "21.0.4" + +# secrets: +# gradle-cache-username: +# description: "The username used to authenticate with the Gradle Build Cache Node." +# required: true +# gradle-cache-password: +# description: "The password used to authenticate with the Gradle Build Cache Node." +# required: true + +defaults: + run: + shell: bash + +permissions: + id-token: write + contents: read + +env: +# GRADLE_CACHE_USERNAME: ${{ secrets.gradle-cache-username }} +# GRADLE_CACHE_PASSWORD: ${{ secrets.gradle-cache-password }} + DOCKER_MANIFEST_GENERATOR: .github/workflows/support/scripts/generate-docker-artifact-baseline.sh + DOCKER_MANIFEST_PATH: ${{ github.workspace }}/.manifests/docker + DOCKER_REGISTRY: localhost:5000 + DOCKER_IMAGE_NAME: consensus-node + DOCKER_CONTEXT_PATH: hedera-node/infrastructure/docker/containers/production-next/consensus-node + SKOPEO_VERSION: v1.14.0 + +jobs: + generate-baseline: + name: Generate Baseline + runs-on: block-node-linux-medium +# outputs: +# sha: ${{ steps.commit.outputs.sha }} +# sha-abbrev: ${{ steps.commit.outputs.sha-abbrev }} +# source-date: ${{ steps.commit.outputs.source-date }} +# path: ${{ steps.baseline.outputs.path }} +# file: ${{ steps.baseline.outputs.file }} +# name: ${{ steps.baseline.outputs.name }} + + steps: + - name: Harden Runner + uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2 + with: + egress-policy: audit + + - name: Hello World + run: echo "Testing Docker Build Determinism" diff --git a/.github/workflows/zxc-verify-gradle-build-determinism.yaml b/.github/workflows/zxc-verify-gradle-build-determinism.yaml index 1ad85e98a..d8d1fb3bd 100644 --- a/.github/workflows/zxc-verify-gradle-build-determinism.yaml +++ b/.github/workflows/zxc-verify-gradle-build-determinism.yaml @@ -18,7 +18,6 @@ name: "ZXC: Verify Gradle Build Determinism" # Z - Ensures sort order such that this script appears at the bottom of the UI # X - Indicates it's not for direct user consumption # C - Indicates this is a 'workflow_call' based reusable workflow - on: workflow_call: inputs: @@ -53,10 +52,171 @@ permissions: contents: read packages: write +env: + GRADLE_MANIFEST_PATH: ${{ github.workspace }}/.manifests/gradle + GRADLE_MANIFEST_GENERATOR: .github/workflows/support/scripts/generate-gradle-artifact-baseline.sh + LC_ALL: C.UTF-8 + jobs: generate-baseline: name: Generate Baseline - runs-on: network-node-linux-medium + runs-on: block-node-linux-medium + outputs: + sha: ${{ steps.commit.outputs.sha }} + path: ${{ steps.baseline.outputs.path }} + file: ${{ steps.baseline.outputs.file }} + name: ${{ steps.baseline.outputs.name }} + steps: + - name: Harden Runner + uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2 + with: + egress-policy: audit + + - name: Checkout Code + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + ref: ${{ inputs.ref }} + + - name: Setup Java + uses: actions/setup-java@8df1039502a15bceb9433410b1a100fbe190c53b # v4.5.0 + with: + distribution: ${{ inputs.java-distribution }} + java-version: ${{ inputs.java-version }} + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@cc4fc85e6b35bafd578d5ffbc76a5518407e1af0 # v4.2.1 + with: + cache-disabled: true + + - name: Retrieve Commit Hash + id: commit + run: echo "sha=$(git rev-parse HEAD)" >> "${GITHUB_OUTPUT}" + + - name: Baseline Existence Check + id: baseline + run: | + BASELINE_NAME="${{ steps.commit.outputs.sha }}.tar.gz" + BASELINE_PATH="gs://hedera-ci-ephemeral-artifacts/${{ github.repository }}/gradle/baselines" + BASELINE_FILE="${BASELINE_PATH}/${BASELINE_NAME}" + BASELINE_EXISTS="false" + + if gsutil ls "${BASELINE_FILE}" >/dev/null 2>&1; then + BASELINE_EXISTS="true" + fi + + echo "exists=${BASELINE_EXISTS}" >> "${GITHUB_OUTPUT}" + echo "path=${BASELINE_PATH}" >> "${GITHUB_OUTPUT}" + echo "name=${BASELINE_NAME}" >> "${GITHUB_OUTPUT}" + echo "file=${BASELINE_FILE}" >> "${GITHUB_OUTPUT}" + + - name: Build Artifacts + id: gradle-build + run: ./gradlew assemble --scan + + - name: Generate Manifest + id: manifest + env: + MANIFEST_PATH: ${{ env.GRADLE_MANIFEST_PATH }} + run: ${{ env.GRADLE_MANIFEST_GENERATOR }} + + verify-artifacts: + name: "Verify Artifacts (${{ join(matrix.os, ', ') }})" + runs-on: ${{ matrix.os }} + needs: + - generate-baseline + strategy: + fail-fast: false + matrix: + os: + - ubuntu-22.04 + - ubuntu-20.04 + - windows-2022 + - windows-2019 + - block-node-linux-medium + - block-node-linux-large steps: - - name: Print - run: echo "Hello, baseline!" + - name: Harden Runner + uses: step-security/harden-runner@0080882f6c36860b6ba35c610c98ce87d4e2f26f # v2.10.2 + with: + egress-policy: audit + + - name: Standardize Git Line Endings + run: | + git config --global core.autocrlf false + git config --global core.eol lf + + - name: Checkout Code + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + ref: ${{ inputs.ref }} + + - name: Setup Python + uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0 + with: + python-version: 3.9 + + - name: Setup Java + uses: actions/setup-java@8df1039502a15bceb9433410b1a100fbe190c53b # v4.5.0 + with: + distribution: ${{ inputs.java-distribution }} + java-version: ${{ inputs.java-version }} + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@cc4fc85e6b35bafd578d5ffbc76a5518407e1af0 # v4.2.1 + with: + cache-disabled: true + +# - name: Setup CoreUtils (macOS) +# if: ${{ runner.os == 'macOS' }} +# run: brew install coreutils + +# - name: Authenticate to Google Cloud +# id: google-auth +# uses: google-github-actions/auth@6fc4af4b145ae7821d527454aa9bd537d1f2dc5f # v2.1.7 +# with: +# workload_identity_provider: "projects/235822363393/locations/global/workloadIdentityPools/hedera-builds-pool/providers/hedera-builds-gh-actions" +# service_account: "swirlds-automation@hedera-registry.iam.gserviceaccount.com" + +# - name: Setup Google Cloud SDK +# uses: google-github-actions/setup-gcloud@6189d56e4096ee891640bb02ac264be376592d6a # v2.1.2 +# env: +# CLOUDSDK_PYTHON: ${{ format('{0}{1}', env.pythonLocation, runner.os == 'Windows' && '\python.exe' || '/bin/python3') }} +# + - name: Download Baseline + env: + CLOUDSDK_PYTHON: ${{ format('{0}{1}', env.pythonLocation, runner.os == 'Windows' && '\python.exe' || '/bin/python3') }} + run: | + mkdir -p "${GRADLE_MANIFEST_PATH}" + cd "${GRADLE_MANIFEST_PATH}" +# gsutil cp "${{ needs.generate-baseline.outputs.file }}" . +# tar -xzf "${{ needs.generate-baseline.outputs.name }}" + + - name: Build Artifacts + id: gradle-build + run: ./gradlew assemble --scan --no-build-cache + + - name: Regenerate Manifest + id: regen-manifest + env: + MANIFEST_PATH: ${{ env.GRADLE_MANIFEST_PATH }}/regenerated + run: ${{ env.GRADLE_MANIFEST_GENERATOR }} + + - name: Validate Applications + working-directory: ${{ github.workspace }}/server/build/libs + run: sha256sum -c "${GRADLE_MANIFEST_PATH}/applications.sha256" + +# - name: Compare Application Manifests +# run: | +# if ! diff -u "${GRADLE_MANIFEST_PATH}/applications.sha256" "${{ steps.regen-manifest.outputs.applications }}" >/dev/null 2>&1; then +# echo "::group::Application Manifest Differences" +# diff -u "${GRADLE_MANIFEST_PATH}/applications.sha256" "${{ steps.regen-manifest.outputs.applications }}" +# echo "::endgroup::" +# exit 1 +# fi +# +# - name: Publish Manifests +# uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 +# if: ${{ steps.regen-manifest.conclusion == 'success' && failure() && !cancelled() }} +# with: +# name: Gradle Manifests [${{ join(matrix.os, ', ') }}] +# path: ${{ env.GRADLE_MANIFEST_PATH }}/** diff --git a/buildSrc/src/main/kotlin/com.hedera.block.conventions.gradle.kts b/buildSrc/src/main/kotlin/com.hedera.block.conventions.gradle.kts index 13d0fd47b..a86b3f95d 100644 --- a/buildSrc/src/main/kotlin/com.hedera.block.conventions.gradle.kts +++ b/buildSrc/src/main/kotlin/com.hedera.block.conventions.gradle.kts @@ -108,7 +108,6 @@ tasks.withType().configureEach { options.encoding = "UTF-8" options.isFork = true // run compiler in separate JVM process (independent of toolchain setup) options.compilerArgs.add("-implicit:none") - options.compilerArgs.add("-Xlint:all,-" + deactivatedCompileLintOptions.joinToString(",-")) doLast { // Make sure consistent line ending are used in files generated by annotation processors by diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index d64cd4917..e6441136f 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a4413138c..e2847c820 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index 1aa94a426..b740cf133 100755 --- a/gradlew +++ b/gradlew @@ -55,7 +55,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. diff --git a/gradlew.bat b/gradlew.bat index 6689b85be..7101f8e46 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -43,11 +43,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail diff --git a/server/docker/Dockerfile b/server/docker/Dockerfile index 0af9bdb80..72b762f7c 100644 --- a/server/docker/Dockerfile +++ b/server/docker/Dockerfile @@ -1,5 +1,84 @@ -# Use Eclipse Temurin with Java 21 as the base image -FROM eclipse-temurin:21 +######################################################################################################################## +# +# Define Global Build Arguments +# +######################################################################################################################## +ARG UBUNTU_TAG="focal-20230605" + +######################################################################################################################## +# +# Setup Builder Image +# +######################################################################################################################## +FROM ubuntu:${UBUNTU_TAG} AS openjdk-builder + +# Define Standard Environment Variables +ENV LC_ALL=C.UTF-8 +ENV DEBIAN_FRONTEND=noninteractive + +# Install basic OS utilities for building +RUN apt-get update && \ + apt-get install --yes tar gzip gnupg2 curl + +########################## +#### Java Setup #### +########################## + +RUN set -eux; \ + ARCH="$(dpkg --print-architecture)"; \ + case "${ARCH}" in \ + aarch64|arm64) \ + ESUM='e184dc29a6712c1f78754ab36fb48866583665fa345324f1a79e569c064f95e9'; \ + BINARY_URL='https://github.com/adoptium/temurin21-binaries/releases/download/jdk-21.0.1%2B12/OpenJDK21U-jdk_aarch64_linux_hotspot_21.0.1_12.tar.gz'; \ + ;; \ + amd64|i386:x86-64) \ + ESUM='1a6fa8abda4c5caed915cfbeeb176e7fbd12eb6b222f26e290ee45808b529aa1'; \ + BINARY_URL='https://github.com/adoptium/temurin21-binaries/releases/download/jdk-21.0.1%2B12/OpenJDK21U-jdk_x64_linux_hotspot_21.0.1_12.tar.gz'; \ + ;; \ + ppc64el|powerpc:common64) \ + ESUM='9574828ef3d735a25404ced82e09bf20e1614f7d6403956002de9cfbfcb8638f'; \ + BINARY_URL='https://github.com/adoptium/temurin21-binaries/releases/download/jdk-21.0.1%2B12/OpenJDK21U-jdk_ppc64le_linux_hotspot_21.0.1_12.tar.gz'; \ + ;; \ + *) \ + echo "Unsupported arch: ${ARCH}"; \ + exit 1; \ + ;; \ + esac; \ + curl -LfsSo /tmp/openjdk.tar.gz ${BINARY_URL}; \ + echo "${ESUM} */tmp/openjdk.tar.gz" | sha256sum -c -; \ + mkdir -p /usr/local/java; \ + tar --extract \ + --file /tmp/openjdk.tar.gz \ + --directory "/usr/local/java" \ + --strip-components 1 \ + --no-same-owner \ + ; \ + rm -f /tmp/openjdk.tar.gz /usr/local/java/lib/src.zip; + +######################################################################################################################## +# +# Build Final Image +# +######################################################################################################################## +FROM ubuntu:${UBUNTU_TAG} AS openjdk-base + +# Define Standard Environment Variables +ENV LC_ALL=C.UTF-8 +ENV DEBIAN_FRONTEND=noninteractive +ENV JAVA_VERSION="jdk-21.0.1+12" +ENV JAVA_HOME="/usr/local/java/" + +# Fetch Validated Java Binaries +COPY --from=openjdk-builder /usr/local/java/ /usr/local/java/ + +# Install Basic OS Requirements +RUN apt-get update && \ + apt-get install --yes --no-install-recommends tar gzip openssl curl && \ + apt-get autoremove --yes && \ + apt-get autoclean --yes && \ + apt-get clean all --yes && \ + rm -rf /var/lib/{apt,dpkg,cache,log}/ + # Expose the port that the application will run on EXPOSE 8080 @@ -11,8 +90,11 @@ ARG VERSION ARG UNAME=hedera ARG UID=2000 ARG GID=2000 -RUN groupadd -g $GID -o $UNAME -RUN useradd -m -u $UID -g $GID -o -s /bin/bash $UNAME + +# Configure the standard user account +RUN groupadd --gid ${GID} ${UNAME} && \ + useradd --no-user-group --create-home --uid ${UID} --gid ${GID} --shell /bin/bash ${UNAME} + USER $UNAME # Set the working directory inside the container