Files
kata-containers/tests/kata-doc-to-script.sh
Fabiano Fidêncio ed5732d5dd tests: Fix shellcheck issues in kata-doc-to-script.sh
Fix shellcheck warnings and notes identified by running
shellcheck --severity=style.

Signed-off-by: Fabiano Fidêncio <ffidencio@nvidia.com>
2026-04-24 08:14:07 +02:00

231 lines
5.3 KiB
Bash
Executable File

#!/bin/bash
license="
#
# Copyright (c) 2018 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0
"
set -e
[[ -n "${DEBUG}" ]] && set -x
script_name="${0##*/}"
typeset -r warning="WARNING: Do *NOT* run the generated script without reviewing it carefully first!"
# github markdown markers used to surround a code block. All text within the
# markers is rendered in a fixed font.
typeset -r bash_block_open="\`\`\`bash"
typeset -r block_open="\`\`\`"
typeset -r block_close="\`\`\`"
# GitHub issue templates have a special metadata section at the top delimited
# by this string. See:
#
# https://raw.githubusercontent.com/kata-containers/.github/master/.github/ISSUE_TEMPLATE/bug_report.md
typeset -r metadata_block='---'
# Used to delimit inline code blocks
typeset -r backtick="\`"
# convention used in all documentation to represent a non-privileged users
# shell prompt. All lines starting with this value inside a code block are
# commands the user should run.
typeset -r code_prompt="\$ "
# files are expected to match this regular expression
typeset -r extension_regex="\.md$"
strict="no"
require_commands="no"
check_only="no"
invert="no"
verbose="no"
usage()
{
cat <<EOF
Usage: ${script_name} [options] <markdown-file> [<script-file> [<description>]]
This script will convert a github-flavoured markdown document file into a
bash(1) script to stdout by extracting the bash code blocks.
Options:
-c : check the file but don't create the script (sets exit code).
-h : show this usage.
-i : invert output (remove code blocks and inline code, displaying the
remaining parts of the document). Incompatible with '-c'.
-r : require atleast one command block to be found.
-s : strict mode - perform extra checks.
-v : verbose mode.
Example usage:
$ ${script_name} foo.md foo.md.sh
Notes:
- If a description is specified, it will be added to the script as a
comment.
- <script-file> may be specified as '-' meaning send output to stdout.
Limitations:
- The script is unable to handle embedded code blocks like this:
\`\`\`
\`\`\`bash
\$ echo code in an embedded set of backticks
\`\`\`
\`\`\`
To overcome this issue, ensure that the outer set of backticks are replaced
with an HTML PRE tag:
<pre>
\`\`\`bash
\$ echo code in an embedded set of backticks
\`\`\`
</pre>
This will both render correctly on GitHub and allow this script to remove
the code block.
Note: this solves one problem but introduces another - this script will not
remove the HTML tags.
${warning}
EOF
exit 0
}
die()
{
local msg="$*"
echo "ERROR: ${msg}" >&2
exit 1
}
script_header()
{
local -r description="$1"
cat <<-EOF
#!/bin/bash
${license}
#----------------------------------------------
# WARNING: Script auto-generated from '${file}'.
#
# ${warning}
#----------------------------------------------
#----------------------------------------------
# Description: ${description}
#----------------------------------------------
# fail the entire script if any simple command fails
set -e
EOF
}
# Convert the specified github-flavoured markdown format file
# into a bash script by extracting the bash blocks.
doc_to_script()
{
file="$1"
outfile="$2"
description="$3"
invert="$4"
[[ -n "${file}" ]] || die "need file"
[[ "${check_only}" = "no" ]] && [[ -z "${outfile}" ]] && die "need output file"
[[ "${outfile}" = '-' ]] && outfile="/dev/stdout"
if [[ "${invert}" = "yes" ]]
then
# First, remove code blocks.
# Next, remove inline code in backticks.
# Finally, remove a metadata block as used in GitHub issue
# templates.
sed -e "/^[ \>]*${block_open}/,/^[ \>]*${block_close}/d" \
-e "s/${backtick}[^${backtick}]*${backtick}//g" \
-e "/^${metadata_block}$/,/^${metadata_block}$/d" \
< "${file}" > "${outfile}"
return
fi
all=$(mktemp)
body=$(mktemp)
sed -n "/^ *${bash_block_open}/,/^ *${block_close}/ p" < "${file}" |\
sed -e "/^ *${block_close}/ d" \
-e "s/^ *${code_prompt}//g" \
-e 's/^ *//g' > "${body}"
[[ "${require_commands}" = "yes" ]] && [[ ! -s "${body}" ]] && die "no commands found in file '${file}'"
script_header "${description}" > "${all}"
cat "${body}" >> "${all}"
# sanity check
[[ "${check_only}" = "yes" ]] && redirect="1>/dev/null 2>/dev/null"
# $redirect is intentionally unquoted; it contains redirections interpreted by eval
# shellcheck disable=SC2086
{ local ret; eval bash -n "${all}" ${redirect}; ret=$?; } || true
[[ "${ret}" -ne 0 ]] && die "shell code in file '${file}' is not valid"
# create output file
[[ "${check_only}" = "no" ]] && cp "${all}" "${outfile}"
# clean up
rm -f "${body}" "${all}"
}
main()
{
while getopts "chirsv" opt
do
case ${opt} in
c) check_only="yes" ;;
h) usage ;;
i) invert="yes" ;;
r) require_commands="yes" ;;
s) strict="yes" ;;
v) verbose="yes" ;;
*) die "invalid option: -${OPTARG}" ;;
esac
done
shift $((OPTIND - 1))
file="$1"
outfile="$2"
description="$3"
[[ -n "${file}" ]] || die "need file"
[[ "${verbose}" = "yes" ]] && echo "INFO: processing file '${file}'"
if [[ "${strict}" = "yes" ]]
then
echo "${file}"|grep -q "${extension_regex}" ||\
die "file '${file}' doesn't match pattern '${extension_regex}'"
fi
doc_to_script "${file}" "${outfile}" "${description}" "${invert}"
}
main "$@"