Skip to content
Merged
192 changes: 119 additions & 73 deletions bin/zopen-build
Original file line number Diff line number Diff line change
Expand Up @@ -2450,89 +2450,126 @@ install()
cp "${ZOPEN_INSTALL_DIR}/.builddeps" "${ZOPEN_ROOT}/install/"

asciiecho "${LOG_PFX}" "${ZOPEN_INSTALL_DIR}/.buildtimestamp"

generateMetadataJSON
else
printHeader "Skipping Install"
fi
printElapsedTime verbose "install" "${installStartTime}"
}

if ${generatePax}; then
printHeader "Generating pax.Z from ${ZOPEN_INSTALL_DIR}"
if ! runAndLog "${ZOPEN_PAX_CMD}"; then
printError "Could not generate pax \"${paxFileName}\""
fi
set_active_version()
{
PROJECT_NAME="$(getProjectName "${ZOPEN_NAME}")"
mergeIntoSystem "${PROJECT_NAME}" "${ZOPEN_INSTALL_DIR}" "${ZOPEN_ROOTFS}"
mkdir -p "${ZOPEN_ROOTFS}/etc/profiled/${PROJECT_NAME}"
cat << EOF > "${ZOPEN_ROOTFS}/etc/profiled/${PROJECT_NAME}/dotenv"
curdir=\$(pwd)
cd "${ZOPEN_INSTALL_DIR}" >/dev/null 2>&1
if [ -f ".appenv" ]; then
. ./.appenv
fi
cd \$curdir >/dev/null 2>&1
EOF
printInfo "- Sourcing environment to run any setup"
(cd "${ZOPEN_INSTALL_DIR}" && ./setup.sh)
printVerbose "Marking this version as installed"
touch "${ZOPEN_INSTALL_DIR}/.active"
}

create_pax()
{
printHeader "Generating pax.Z from ${ZOPEN_INSTALL_DIR}"
if ! runAndLog "${ZOPEN_PAX_CMD}"; then
printError "Could not generate pax \"${paxFileName}\""
fi
}

create_rpm()
{
if [ -f "${paxFileName}" ]; then
printHeader "Generating RPM from ${ZOPEN_INSTALL_DIR}"

# Extract package name using same logic as metadata.json
rpm_name=$(getProjectName "${ZOPEN_NAME}")

# Read version and release from install directory files
rpm_version=$(cat "${ZOPEN_INSTALL_DIR}/.version")
Comment thread
sachintu47 marked this conversation as resolved.
build_timestamp=$(cat "${ZOPEN_INSTALL_DIR}/.buildtimestamp")

# Convert timestamp format for RPM (underscore to dot)
# 20250205_142114 → 20250205.142114
rpm_release=$(echo ${build_timestamp} | tr '_' '.')

# Filter out 'meta' from runtime dependencies
rpm_deps=$(echo "${ZOPEN_RUNTIME_DEPS}" | xargs -n1 | grep -v "^meta$" | sort -u | xargs)
cmd="\"${MYDIR}/zopen-pax2rpm\" \"${paxFileName}\" --name \"${rpm_name}\" --version \"${rpm_version}\" --release \"${rpm_release}\" --summary \"${ZOPEN_NAME} package\" --build-binary --buildroot \"${ZOPEN_ROOT}/rpmbuild\""
if [ -n "${rpm_deps}" ]; then
cmd="${cmd} --requires \"${rpm_deps}\""
fi
if ! runAndLog "${cmd}"; then
printError "Could not generate RPM from \"${paxFileName}\""
fi
else
printError "Pax file ${paxFileName} not found. Ensure --generate-pax is also used."
Comment thread
sachintu47 marked this conversation as resolved.
fi
}

finalize_pax_metadata()
{
pax_size=$(getPathSizeInBytes "${paxFileName}")
md5sum=$(md5sum "${paxFileName}" | awk '{print $1}')

#If signPax is true, rest of variables check is done before setDepsEnv
if [ "${signPax}" = "true" ]; then
signPaxFile
public_key=$(jq -Rs . < ${ZOPEN_GPG_PUBLIC_KEY_FILE})
Comment thread
sachintu47 marked this conversation as resolved.
fi

if [[ -n "${SIGNATURE}" ]]; then
jq --arg pax "${ZOPEN_NAME}.${LOG_PFX}.zos.pax.Z" \
--arg pax_size "$pax_size" \
--arg md5 "$md5sum" \
--arg signature "$SIGNATURE" \
--arg public_key "$public_key" \
'.product |= . + { "pax": $pax, "pax_size": $pax_size, "md5": $md5, "signature": $signature, "public_key": $public_key }' \
"${ZOPEN_ROOT}/install/metadata.json" > "${ZOPEN_ROOT}/install/metadata.json.tmp"
else
jq '.product |= . + { "pax": "'${ZOPEN_NAME}.${LOG_PFX}.zos.pax.Z'", "pax_size": "'${pax_size}'", "md5": "'${md5sum}'" }' "${ZOPEN_ROOT}/install/metadata.json" > "${ZOPEN_ROOT}/install/metadata.json.tmp"
Comment thread
sachintu47 marked this conversation as resolved.
fi
mv "${ZOPEN_ROOT}/install/metadata.json.tmp" "${ZOPEN_ROOT}/install/metadata.json"
Comment thread
sachintu47 marked this conversation as resolved.
}

package()
{
packageStartTime=${SECONDS}
if [ -n "${ZOPEN_INSTALL_CMD}" ]; then
#TODO: Hack so that we can use coreutils md5sum without impacting builds
ZOPEN_DEPS="coreutils jq"
if [ "${signPax}" = "true" ] && ( [ -z "${ZOPEN_GPG_SECRET_KEY_FILE}" ] || [ -z "${ZOPEN_GPG_SECRET_KEY_PASSPHRASE_FILE}" ] || [ -z "${ZOPEN_GPG_PUBLIC_KEY_FILE}" ] || [ ! -r "${ZOPEN_GPG_SECRET_KEY_FILE}" ] || [ ! -r "${ZOPEN_GPG_SECRET_KEY_PASSPHRASE_FILE}" ] || [ ! -r "${ZOPEN_GPG_PUBLIC_KEY_FILE}" ] ); then
printError "GPG keyring environment variables are not set! You can omit the --sign-pax option to bypass this"
else
ZOPEN_DEPS="${ZOPEN_DEPS} gpg"
Comment thread
sachintu47 marked this conversation as resolved.
fi

if ${generateRPM}; then
if [ -f "${paxFileName}" ]; then
printHeader "Generating RPM from ${ZOPEN_INSTALL_DIR}"
rpm_deps=$(echo "${ZOPEN_RUNTIME_DEPS}" | xargs -n1 | sort -u | xargs)
cmd="PATH=\"${ZOPEN_ROOTFS}/usr/local/bin:${PATH}\" \"${MYDIR}/zopen-pax2rpm\" \"${paxFileName}\" --summary \"${ZOPEN_NAME} package\" --build --buildroot \"${ZOPEN_ROOT}/rpmbuild\""
if [ -n "${rpm_deps}" ]; then
cmd="${cmd} --requires \"${rpm_deps}\""
fi
if ! runAndLog "${cmd}"; then
printError "Could not generate RPM from \"${paxFileName}\""
fi
else
printError "Pax file ${paxFileName} not found. Ensure --generate-pax is also used."
fi
ZOPEN_DEPS="${ZOPEN_DEPS} rpm"
fi

if ${generatePax}; then
#TODO: Hack so that we can use coreutils md5sum without impacting builds
ZOPEN_DEPS="${ZOPEN_DEPS} coreutils jq"
if [ "${signPax}" = "true" ] && ( [ -z "${ZOPEN_GPG_SECRET_KEY_FILE}" ] || [ -z "${ZOPEN_GPG_SECRET_KEY_PASSPHRASE_FILE}" ] || [ -z "${ZOPEN_GPG_PUBLIC_KEY_FILE}" ] || [ ! -r "${ZOPEN_GPG_SECRET_KEY_FILE}" ] || [ ! -r "${ZOPEN_GPG_SECRET_KEY_PASSPHRASE_FILE}" ] || [ ! -r "${ZOPEN_GPG_PUBLIC_KEY_FILE}" ] ); then
printError "GPG keyring environment variables are not set! You can omit the --sign-pax option to bypass this"
else
ZOPEN_DEPS="${ZOPEN_DEPS} gpg"
fi

setDepsEnv

pax_size=$(getPathSizeInBytes "${paxFileName}")
md5sum=$(md5sum "${paxFileName}" | awk '{print $1}')

#If signPax is true, rest of variables check is done before setDepsEnv
if [ "${signPax}" = "true" ]; then
signPaxFile
public_key=$(jq -Rs . < ${ZOPEN_GPG_PUBLIC_KEY_FILE})
fi
setDepsEnv
create_pax

if [[ -n "${SIGNATURE}" ]]; then
cat ${ZOPEN_INSTALL_DIR}/metadata.json
jq --arg pax "${ZOPEN_NAME}.${LOG_PFX}.zos.pax.Z" \
--arg pax_size "$pax_size" \
--arg md5 "$md5sum" \
--arg signature "$SIGNATURE" \
--arg public_key "$public_key" \
'.product |= . + { "pax": $pax, "pax_size": $pax_size, "md5": $md5, "signature": $signature, "public_key": $public_key }' \
"${ZOPEN_ROOT}/install/metadata.json" > "${ZOPEN_ROOT}/install/metadata.json.tmp"
else
jq '.product |= . + { "pax": "'${ZOPEN_NAME}.${LOG_PFX}.zos.pax.Z'", "pax_size": "'${pax_size}'", "md5": "'${md5sum}'" }' "${ZOPEN_ROOT}/install/metadata.json" > "${ZOPEN_ROOT}/install/metadata.json.tmp"
fi
mv "${ZOPEN_ROOT}/install/metadata.json.tmp" "${ZOPEN_ROOT}/install/metadata.json"
if ${generateRPM}; then
create_rpm
fi

if ${setActive}; then
PROJECT_NAME="$(echo ${ZOPEN_NAME} | cut -d'-' -f1)"
mergeIntoSystem "${PROJECT_NAME}" "${ZOPEN_INSTALL_DIR}" "${ZOPEN_ROOTFS}"
mkdir -p "${ZOPEN_ROOTFS}/etc/profiled/${name}"
cat << EOF > "${ZOPEN_ROOTFS}/etc/profiled/${name}/dotenv"
curdir=\$(pwd)
cd "${ZOPEN_INSTALL_DIR}" >/dev/null 2>&1
if [ -f ".appenv" ]; then
. ./.appenv
fi
cd \$curdir >/dev/null 2>&1
EOF
printInfo "- Sourcing environment to run any setup"
cd "${ZOPEN_INSTALL_DIR}" && ./setup.sh
printVerbose "Marking this version as installed"
touch "${ZOPEN_INSTALL_DIR}/.active"
if ${generatePax}; then
finalize_pax_metadata
fi
generateOCI ${ZOPEN_NAME}
else
printHeader "Skipping Install"
printHeader "Skipping Package"
fi
printElapsedTime verbose "install" "${installStartTime}"
printElapsedTime verbose "package" "${packageStartTime}"
}

#
Expand Down Expand Up @@ -2683,9 +2720,6 @@ resolveCommands()

generateOCI()
{
if ! ${publishOCI}; then
return 0
fi
printHeader "Generating OCI Image"
package=$1
name=$(echo ${package} | cut -d "-" -f 1)
Expand Down Expand Up @@ -3083,6 +3117,18 @@ if ! install; then
exit 4
fi

if ${generatePax} || ${generateRPM}; then
Comment thread
sachintu47 marked this conversation as resolved.
package
fi

if ${publishOCI}; then
generateOCI ${ZOPEN_NAME}
Comment thread
sachintu47 marked this conversation as resolved.
fi

if ${setActive}; then
set_active_version
fi

if command -V "${ZOPEN_PRE_TERMINATE_CODE}" > /dev/null 2>&1; then
printVerbose "Running ${ZOPEN_PRE_TERMINATE_CODE}"
if ! "${ZOPEN_PRE_TERMINATE_CODE}" "${ZOPEN_INSTALL_DIR}"; then
Expand Down
38 changes: 29 additions & 9 deletions bin/zopen-pax2rpm
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ PACKAGER_EMAIL="${CURRENT_USER}@$(hostname 2>/dev/null || echo "localhost")"

# Build flag
BUILD_RPM=false
BUILD_BINARY_ONLY=false
BUILDROOT="${HOME}/rpmbuild"
VALIDATE_SPEC=false
DRY_RUN=false
Expand Down Expand Up @@ -66,7 +67,8 @@ Options:
--url <url> Project URL (default: none)
--requires <deps> Package dependencies (e.g., "oef >= 1.1.0")
--output <file> Output spec file (default: <name>.spec)
--build Build the RPM after generating spec file
--build Build the RPM after generating spec file (binary + source)
--build-binary Build binary RPM only (faster, no source RPM)
Comment thread
sachintu47 marked this conversation as resolved.
Comment thread
sachintu47 marked this conversation as resolved.
--buildroot <dir> RPM build root directory (default: ~/rpmbuild)
--validate Validate spec file after generation (checks syntax and runs rpmlint)
--dry-run Show what would be done without actually doing it
Expand Down Expand Up @@ -682,10 +684,21 @@ source_name=$(basename "$pax_file")

# Build the RPM
echo ""
echo "Running rpmbuild --define \"_topdir $buildroot\" -ba $spec_file"
echo ""
if [ "$BUILD_BINARY_ONLY" = true ]; then
echo "Running rpmbuild --define \"_topdir $buildroot\" -bb $spec_file"
echo ""
rpmbuild_result=$(rpmbuild --define "_topdir $buildroot" -bb "$spec_file" 2>&1)
rpmbuild_exit=$?
echo "$rpmbuild_result"
else
echo "Running rpmbuild --define \"_topdir $buildroot\" -ba $spec_file"
echo ""
rpmbuild_result=$(rpmbuild --define "_topdir $buildroot" -ba "$spec_file" 2>&1)
rpmbuild_exit=$?
echo "$rpmbuild_result"
fi

if rpmbuild --define "_topdir $buildroot" -ba "$spec_file"; then
if [ $rpmbuild_exit -eq 0 ]; then
echo ""
echo "=========================================="
echo "✓ RPM build completed successfully!"
Expand All @@ -697,11 +710,13 @@ source_name=$(basename "$pax_file")
find "$buildroot/RPMS" -name "*.rpm" -type f 2>/dev/null | while read rpm; do
echo " - $rpm"
done
echo ""
echo "Source RPMs:"
find "$buildroot/SRPMS" -name "*.rpm" -type f 2>/dev/null | while read rpm; do
echo " - $rpm"
done
if [ "$BUILD_BINARY_ONLY" != true ]; then
echo ""
echo "Source RPMs:"
find "$buildroot/SRPMS" -name "*.rpm" -type f 2>/dev/null | while read rpm; do
echo " - $rpm"
done
fi
echo ""
return 0
else
Expand Down Expand Up @@ -820,6 +835,11 @@ main() {
BUILD_RPM=true
shift
;;
--build-binary)
BUILD_RPM=true
BUILD_BINARY_ONLY=true
shift
;;
--buildroot)
[ -n "$2" ] || { echo "Error: --buildroot requires a value" >&2; usage; }
BUILDROOT="$2"
Expand Down
13 changes: 10 additions & 3 deletions cicd/publish.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ NUM_RPMS=${#RPM_FILES[@]}

# --- INFO ---
BUILD_STATUS=$(find . -path "*/install/test.status" -exec cat {} + 2>/dev/null || echo "Unknown")
DEPENDENCIES=$(find . -path "*/install/.runtimedeps" -exec cat {} + 2>/dev/null || echo "None")
RUNTIME_DEPS=$(find . -path "*/install/.runtimedeps" -exec cat {} + 2>/dev/null || echo "None")
BUILD_DEPS=$(find . -path "*/install/.builddeps" -exec cat {} + 2>/dev/null || echo "None")
VERSION=$(find . -path "*/install/.version" -exec cat {} + 2>/dev/null || echo "unknown")

unset http_proxy https_proxy
Expand All @@ -69,8 +70,14 @@ fi

echo "$RELEASE_NOTES" > CHANGELOG.md

DESCRIPTION="${PORT_DESCRIPTION}<br/><b>Status:</b> ${BUILD_STATUS}<br/>"
DESCRIPTION+="<b>Dependencies:</b> ${DEPENDENCIES}<br/>"
DESCRIPTION="${PORT_DESCRIPTION}<br/>"
DESCRIPTION+="<b>Version:</b> ${VERSION}<br/>"
DESCRIPTION+="<b>Test Status:</b> ${BUILD_STATUS}<br/>"
DESCRIPTION+="<b>Runtime Dependencies:</b> ${RUNTIME_DEPS}<br/>"
DESCRIPTION+="<b>Build Dependencies:</b> ${BUILD_DEPS}<br/>"
URL_LINE="https://github.com/${GITHUB_ORGANIZATION}/${GITHUB_REPO}/releases/download/${TAG}/${PAX_BASENAME}"
DESCRIPTION+="<br/><b>Command to download and install on z/OS (if you have curl)</b> <pre>curl -o ${PAX_BASENAME} -L ${URL_LINE} && pax -rf ${PAX_BASENAME} && cd ${PORT_NAME} && . ./setup.sh</pre>"
Comment thread
sachintu47 marked this conversation as resolved.
Comment thread
sachintu47 marked this conversation as resolved.
DESCRIPTION+="<br/><b>Or use:</b> <pre>zopen install ${PORT_NAME}</pre>"
DESCRIPTION+=$'\n\n'"$RELEASE_NOTES"

# --- TOOL CHECK ---
Expand Down
Loading