diff --git a/lib/functions/cli/cli-oras.sh b/lib/functions/cli/cli-oras.sh new file mode 100644 index 0000000000..1aa180a6f9 --- /dev/null +++ b/lib/functions/cli/cli-oras.sh @@ -0,0 +1,30 @@ +function cli_oras_pre_run() { + : # Empty, no need to do anything. +} + +function cli_oras_run() { + case "${ORAS_OPERATION}" in + upload) + display_alert "Uploading using ORAS" "OCI_TARGET: '${OCI_TARGET}' UPLOAD_FILE='${UPLOAD_FILE}'" "info" + display_alert "OCI_TARGET" "${OCI_TARGET}" "info" + display_alert "UPLOAD_FILE" "${UPLOAD_FILE}" "info" + # if OCI_TARGET is not set, exit_with_error + if [[ -z "${OCI_TARGET}" ]]; then + exit_with_error "OCI_TARGET is not set" + fi + if [[ -z "${UPLOAD_FILE}" ]]; then + exit_with_error "UPLOAD_FILE is not set" + fi + if [[ ! -f "${UPLOAD_FILE}" ]]; then + exit_with_error "File to upload not found '${UPLOAD_FILE}'" + fi + # This will download & install ORAS and run it. + oras_push_artifact_file "${OCI_TARGET}" "${UPLOAD_FILE}" + ;; + + *) + exit_with_error "Unknown ORAS_OPERATION '${ORAS_OPERATION}'" + ;; + esac + return 0 +} diff --git a/lib/functions/cli/cli-requirements.sh b/lib/functions/cli/cli-requirements.sh index 478e444c92..5dc202b4e6 100644 --- a/lib/functions/cli/cli-requirements.sh +++ b/lib/functions/cli/cli-requirements.sh @@ -23,5 +23,7 @@ function cli_requirements_run() { LOG_SECTION="install_host_dependencies" do_with_logging install_host_dependencies "for requirements command" + # @TODO: get stuff like shellcheck, shfmt, and ORAS in here. Deploy them somewhere not-in-./cache, so it's baked into Docker image. + display_alert "Done with" "@host dependencies" "cachehit" } diff --git a/lib/functions/cli/cli-rootfs.sh b/lib/functions/cli/cli-rootfs.sh index 13ebb77236..55b6473f1e 100644 --- a/lib/functions/cli/cli-rootfs.sh +++ b/lib/functions/cli/cli-rootfs.sh @@ -43,6 +43,14 @@ function cli_rootfs_run() { exit_with_error "Param 'ARCH' is set to '${ARCH}' after config, but different from wanted '${__wanted_rootfs_arch}'" fi + declare -g ROOT_FS_CREATE_VERSION + if [[ -z ${ROOT_FS_CREATE_VERSION} ]]; then + ROOT_FS_CREATE_VERSION="$(date --utc +"%Y%m%d")" + display_alert "ROOT_FS_CREATE_VERSION is not set, defaulting to current date" "ROOT_FS_CREATE_VERSION=${ROOT_FS_CREATE_VERSION}" "warn" + else + display_alert "ROOT_FS_CREATE_VERSION is set" "ROOT_FS_CREATE_VERSION=${ROOT_FS_CREATE_VERSION}" "info" + fi + # default build, but only invoke specific rootfs functions needed. It has its own logging sections. do_with_default_build cli_rootfs_only_in_default_build < /dev/null # no stdin for this, so it bombs if tries to be interactive. @@ -54,11 +62,16 @@ function cli_rootfs_run() { # This is run inside do_with_default_build(), above. function cli_rootfs_only_in_default_build() { + declare -g rootfs_cache_id="none_yet" + LOG_SECTION="prepare_rootfs_build_params_and_trap" do_with_logging prepare_rootfs_build_params_and_trap - LOG_SECTION="calculate_rootfs_cache_id" do_with_logging calculate_rootfs_cache_id + LOG_SECTION="calculate_rootfs_cache_id" do_with_logging calculate_rootfs_cache_id # sets rootfs_cache_id - display_alert "Going to build rootfs" "packages_hash: '${packages_hash:-}' cache_type: '${cache_type:-}'" "info" + # Set a GHA output variable for the cache ID, so it can be used in other steps. + github_actions_add_output rootfs_cache_id "${rootfs_cache_id}-${ROOT_FS_CREATE_VERSION}" # this is contrived... but it works. + + display_alert "Going to build rootfs" "packages_hash: '${packages_hash:-}' cache_type: '${cache_type:-}' rootfs_cache_id: '${rootfs_cache_id}'" "info" # "rootfs" CLI skips over a lot goes straight to create the rootfs. It doesn't check cache etc. LOG_SECTION="create_new_rootfs_cache" do_with_logging create_new_rootfs_cache diff --git a/lib/functions/cli/commands.sh b/lib/functions/cli/commands.sh index e37311fb4d..10ee06aae8 100644 --- a/lib/functions/cli/commands.sh +++ b/lib/functions/cli/commands.sh @@ -22,7 +22,7 @@ function armbian_register_commands() { ["build"]="standard_build" # implemented in cli_standard_build_pre_run and cli_standard_build_run ["distccd"]="distccd" # implemented in cli_distccd_pre_run and cli_distccd_run - ["rootfs"]="rootfs" # implemented in cli_rootfs_pre_run and cli_rootfs_run + ["rootfs"]="rootfs" # implemented in cli_rootfs_pre_run and cli_rootfs_run ["rootfs-cache"]="rootfs" # idem, alias # shortcuts, see vars set below. the use legacy single build, and try to control it via variables @@ -30,6 +30,8 @@ function armbian_register_commands() { ["u-boot"]="standard_build" ["uboot"]="standard_build" + # external tooling, made easy. + ["oras-upload"]="oras" # implemented in cli_oras_pre_run and cli_oras_run; up/down/info are the same, see vars below ["undecided"]="undecided" # implemented in cli_undecided_pre_run and cli_undecided_run - relaunches either build or docker ) @@ -50,6 +52,8 @@ function armbian_register_commands() { ["u-boot"]="KERNEL_ONLY='yes' JUST_UBOOT='yes' UBOOT_IGNORE_DEB='yes'" ["uboot"]="KERNEL_ONLY='yes' JUST_UBOOT='yes' UBOOT_IGNORE_DEB='yes'" + ["oras-upload"]="ORAS_OPERATION='upload'" + ["undecided"]="UNDECIDED='yes'" ) # Override the LOG_CLI_ID to change the log file name. diff --git a/lib/functions/general/github-actions.sh b/lib/functions/general/github-actions.sh new file mode 100644 index 0000000000..93ded24d54 --- /dev/null +++ b/lib/functions/general/github-actions.sh @@ -0,0 +1,18 @@ +function github_actions_add_output() { + # if CI is not GitHub Actions, do nothing + if [[ "${CI}" != "true" ]] && [[ "${GITHUB_ACTIONS}" != "true" ]]; then + display_alert "Not running in GitHub Actions, not adding output" "'${*}'" "debug" + return 0 + fi + + if [[ ! -f "${GITHUB_OUTPUT}" ]]; then + exit_with_error "GITHUB_OUTPUT file not found '${GITHUB_OUTPUT}'" + fi + + local output_name="$1" + shift + local output_value="$*" + + echo "${output_name}=${output_value}" >> "${GITHUB_OUTPUT}" + display_alert "Added GHA output" "'${output_name}'='${output_value}'" "info" +} diff --git a/lib/functions/host/docker.sh b/lib/functions/host/docker.sh index 757ed21011..a7625d1935 100755 --- a/lib/functions/host/docker.sh +++ b/lib/functions/host/docker.sh @@ -348,6 +348,17 @@ function docker_cli_prepare_launch() { "--env" "CI=${CI}" ) + # If running on GitHub Actions, mount & forward some paths, so they're accessible inside Docker. + if [[ "${CI}" == "true" ]] && [[ "${GITHUB_ACTIONS}" == "true" ]]; then + display_alert "Passing down to Docker" "GITHUB_OUTPUT: '${GITHUB_OUTPUT}'" "info" + DOCKER_ARGS+=("--mount" "type=bind,source=${GITHUB_OUTPUT},target=${GITHUB_OUTPUT}") + DOCKER_ARGS+=("--env" "GITHUB_OUTPUT=${GITHUB_OUTPUT}") + + display_alert "Passing down to Docker" "GITHUB_STEP_SUMMARY: '${GITHUB_STEP_SUMMARY}'" "info" + DOCKER_ARGS+=("--mount" "type=bind,source=${GITHUB_STEP_SUMMARY},target=${GITHUB_STEP_SUMMARY}") + DOCKER_ARGS+=("--env" "GITHUB_STEP_SUMMARY=${GITHUB_STEP_SUMMARY}") + fi + # This will receive the mountpoint as $1 and the mountpoint vars in the environment. function prepare_docker_args_for_mountpoint() { local MOUNT_DIR="$1" diff --git a/lib/functions/logging/trap-logging.sh b/lib/functions/logging/trap-logging.sh index 39061f01f0..e0c163a449 100644 --- a/lib/functions/logging/trap-logging.sh +++ b/lib/functions/logging/trap-logging.sh @@ -74,6 +74,7 @@ function trap_handler_cleanup_logging() { local target_file="${target_path}/summary-${ARMBIAN_LOG_CLI_ID}-${ARMBIAN_BUILD_UUID}.md" export_markdown_logs reset_uid_owner "${target_file}" + local markdown_log_file="${target_file}" local target_file="${target_path}/log-${ARMBIAN_LOG_CLI_ID}-${ARMBIAN_BUILD_UUID}.log.ans" export_ansi_logs @@ -81,5 +82,11 @@ function trap_handler_cleanup_logging() { # @TODO: plain-text version? just sed... + # If running in Github Actions, cat the markdown file GITHUB_STEP_SUMMARY. + if [[ "${CI}" == "true" ]] && [[ "${GITHUB_ACTIONS}" == "true" ]]; then + display_alert "Exporting Markdown logs to GitHub Actions" "GITHUB_STEP_SUMMARY: '${GITHUB_STEP_SUMMARY}'" "info" + cat "${markdown_log_file}" > "${GITHUB_STEP_SUMMARY}" || true + fi + discard_logs_tmp_dir } diff --git a/lib/functions/rootfs/create-cache.sh b/lib/functions/rootfs/create-cache.sh index d71f40062f..6c8f5f25d2 100644 --- a/lib/functions/rootfs/create-cache.sh +++ b/lib/functions/rootfs/create-cache.sh @@ -32,11 +32,16 @@ function calculate_rootfs_cache_id() { declare cache_type="cli" [[ ${BUILD_DESKTOP} == yes ]] && cache_type="xfce-desktop" - [[ -n ${DESKTOP_ENVIRONMENT} ]] && cache_type="${DESKTOP_ENVIRONMENT}" + [[ -n ${DESKTOP_ENVIRONMENT} ]] && cache_type="${DESKTOP_ENVIRONMENT}" # @TODO: this is missing "-desktop" [[ ${BUILD_MINIMAL} == yes ]] && cache_type="minimal" + + # @TODO: rpardini: allow extensions to modify cache_type, eg, "-cloud-mluc". *think* before doing this + declare -g -r cache_type="${cache_type}" - display_alert "calculate_rootfs_cache_id: done with packages-hash" "${packages_hash}" "debug" + declare -g -r rootfs_cache_id="${cache_type}-${packages_hash}" + + display_alert "calculate_rootfs_cache_id: done." "rootfs_cache_id: '${rootfs_cache_id}'" "debug" } # this gets from cache or produces a basic new rootfs, ready, but not mounted, at "$SDCARD" diff --git a/lib/library-functions.sh b/lib/library-functions.sh index 3e37ce2a07..7fb1482f42 100644 --- a/lib/library-functions.sh +++ b/lib/library-functions.sh @@ -73,6 +73,15 @@ set -o errexit ## set -e : exit the script if any statement returns a non-true # shellcheck source=lib/functions/cli/cli-jsoninfo.sh source "${SRC}"/lib/functions/cli/cli-jsoninfo.sh +# no errors tolerated. invoked before each sourced file to make sure. +#set -o pipefail # trace ERR through pipes - will be enabled "soon" +#set -o nounset ## set -u : exit the script if you try to use an uninitialised variable - one day will be enabled +set -o errtrace # trace ERR through - enabled +set -o errexit ## set -e : exit the script if any statement returns a non-true return value - enabled +### lib/functions/cli/cli-oras.sh +# shellcheck source=lib/functions/cli/cli-oras.sh +source "${SRC}"/lib/functions/cli/cli-oras.sh + # no errors tolerated. invoked before each sourced file to make sure. #set -o pipefail # trace ERR through pipes - will be enabled "soon" #set -o nounset ## set -u : exit the script if you try to use an uninitialised variable - one day will be enabled @@ -496,6 +505,15 @@ set -o errexit ## set -e : exit the script if any statement returns a non-true # shellcheck source=lib/functions/general/git.sh source "${SRC}"/lib/functions/general/git.sh +# no errors tolerated. invoked before each sourced file to make sure. +#set -o pipefail # trace ERR through pipes - will be enabled "soon" +#set -o nounset ## set -u : exit the script if you try to use an uninitialised variable - one day will be enabled +set -o errtrace # trace ERR through - enabled +set -o errexit ## set -e : exit the script if any statement returns a non-true return value - enabled +### lib/functions/general/github-actions.sh +# shellcheck source=lib/functions/general/github-actions.sh +source "${SRC}"/lib/functions/general/github-actions.sh + # no errors tolerated. invoked before each sourced file to make sure. #set -o pipefail # trace ERR through pipes - will be enabled "soon" #set -o nounset ## set -u : exit the script if you try to use an uninitialised variable - one day will be enabled