1#!/bin/bash 2# Copyright 2023 The gRPC Authors 3# 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15 16set -e 17 18ARCHIVE_WO_SUBMODULES="$1" 19ARCHIVE_WITH_SUBMODULES="$2" 20export ARCHIVES_DIR="$(pwd)/archives" 21 22export ARCHIVE_FORMAT=tar 23 24mkdir -p "${ARCHIVES_DIR}" 25rm -rf "${ARCHIVES_DIR}"/* 26 27# TODO(jtattermusch): This script is currently only tested on linux. 28# Nothing prevents it from working on other systems in principle, 29# but more work is needed. 30 31# HACK: To be able to collect all grpc source files as an archive 32# we need to break from bazel's "sandbox" to be able to read files 33# from the original bazel workspace (which in our case is the grpc repository root) 34# This action runs with the "standalone" (a.k.a) local strategy, 35# so path to the original bazel workspace from where this was invoked 36# can be obtained by resolving the link that points to one of the 37# source files. 38# 1. find first component of the relative path to this script 39# 2. resolve the symlink (it will point to same dir in the workspace) 40# 3. one level up is the root of the original bazel workspace 41FIRST_PATH_COMPONENT="$(echo $0 | sed 's|/.*||')" 42ORIGINAL_BAZEL_WORKSPACE_ROOT="$(dirname $(readlink ${FIRST_PATH_COMPONENT}))" 43 44# extract STABLE_GIT_COMMIT from stable-status.txt 45GRPC_GIT_COMMIT_FROM_STABLE_STATUS=$(grep ^STABLE_GRPC_GIT_COMMIT bazel-out/stable-status.txt | cut -d' ' -f2) 46 47if [ "${GRPC_GIT_COMMIT_FROM_STABLE_STATUS}" == "" ] 48then 49 echo "Failed to obtain info about gRPC git commit from the bazel workspace. Make sure you invoke bazel with --workspace_status_command=tools/bazelify_tests/workspace_status_cmd.sh" >&2 50 exit 1 51fi 52 53GRPC_UNCOMMITED_PATCH_CHECKSUM_FROM_STABLE_STATUS=$(grep ^STABLE_GRPC_UNCOMMITED_PATCH_CHECKSUM bazel-out/stable-status.txt | cut -d' ' -f2) 54GRPC_GIT_WORKSPACE_DIRTY_FROM_STABLE_STATUS=$(grep ^STABLE_GRPC_GIT_WORKSPACE_DIRTY bazel-out/stable-status.txt | cut -d' ' -f2) 55 56pushd ${ORIGINAL_BAZEL_WORKSPACE_ROOT} >/dev/null 57 58if [ "${GRPC_GIT_COMMIT_FROM_STABLE_STATUS}" != "$(git rev-parse HEAD)" ] 59then 60 echo "Info about gRPC commit from stable-status.txt doesn't match the commit at which the workspace root is." >&2 61 echo "This is unexpected and giving up early is better than risking to end up with bogus results." >&2 62 exit 1 63fi 64 65mkdir -p ${ARCHIVES_DIR}/grpc 66git archive --format="${ARCHIVE_FORMAT}" HEAD >"${ARCHIVES_DIR}/grpc/$(git rev-parse HEAD).${ARCHIVE_FORMAT}" 67 68if [ "${GRPC_UNCOMMITED_PATCH_CHECKSUM_FROM_STABLE_STATUS}" != "" ] 69then 70 git diff HEAD >"${ARCHIVES_DIR}/grpc/grpc_uncommited_${GRPC_UNCOMMITED_PATCH_CHECKSUM_FROM_STABLE_STATUS}.patch" 71 # check that the actual checksum of the patch file is what we expect it to be 72 echo "${GRPC_UNCOMMITED_PATCH_CHECKSUM_FROM_STABLE_STATUS} ${ARCHIVES_DIR}/grpc/grpc_uncommited_${GRPC_UNCOMMITED_PATCH_CHECKSUM_FROM_STABLE_STATUS}.patch" | sha256sum --quiet --check 73fi 74 75# produce archive for each submodule 76git submodule --quiet foreach 'git_commit="$(git rev-parse HEAD)"; mkdir -p ${ARCHIVES_DIR}/${name}; git archive --format=${ARCHIVE_FORMAT} HEAD >${ARCHIVES_DIR}/${name}/${git_commit}.${ARCHIVE_FORMAT}' 77 78popd >/dev/null 79 80# Extract grpc 81mkdir grpc 82tar -xopf "${ARCHIVES_DIR}/grpc/${GRPC_GIT_COMMIT_FROM_STABLE_STATUS}.${ARCHIVE_FORMAT}" -C grpc 83 84# apply the patch 85if [ "${GRPC_UNCOMMITED_PATCH_CHECKSUM_FROM_STABLE_STATUS}" != "" ] 86then 87 pushd grpc >/dev/null 88 patch --quiet -p1 <"${ARCHIVES_DIR}/grpc/grpc_uncommited_${GRPC_UNCOMMITED_PATCH_CHECKSUM_FROM_STABLE_STATUS}.patch" 89 popd >/dev/null 90fi 91 92# The archive produced need to be deterministic/stable. 93# Passing the following args to tar should be enough to make them so. 94# See https://reproducible-builds.org/docs/archives/ 95DETERMINISTIC_TAR_ARGS=( 96 --sort=name 97 # use a fixed mtime timestamp for all files (2015-01-01 00:00Z works just fine) 98 --mtime="@1420070400" 99 --owner=0 100 --group=0 101 --numeric-owner 102 --pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime 103) 104 105# create archive without submodules first 106tar "${DETERMINISTIC_TAR_ARGS[@]}" -czf ${ARCHIVE_WO_SUBMODULES} grpc 107 108SUBMODULE_ARCHIVE_LIST="$(grep 'STABLE_GRPC_SUBMODULE_ARCHIVES ' bazel-out/stable-status.txt | sed 's/^STABLE_GRPC_SUBMODULE_ARCHIVES //')" 109# TODO(jtattermusch): handle spaces in submodule directory path 110for submodule_archive in ${SUBMODULE_ARCHIVE_LIST} 111do 112 archive_subdir="grpc/$(dirname ${submodule_archive})" 113 mkdir -p $archive_subdir 114 # Extract submodule archive under the correct subdirectory in grpc 115 tar -xopf "${ARCHIVES_DIR}/${submodule_archive}.${ARCHIVE_FORMAT}" -C $archive_subdir 116done 117 118# create archive with everything 119tar "${DETERMINISTIC_TAR_ARGS[@]}" -czf ${ARCHIVE_WITH_SUBMODULES} grpc 120 121# Cleanup intermediate files we created 122rm -rf "${ARCHIVES_DIR}" grpc 123