lint: add shellcheck/shfmt rules to AGENTS.md, format compile.sh and pullsrc.sh

This commit is contained in:
boypt
2026-08-16 11:21:01 +08:00
parent 277ccf7ec4
commit cbb519644d
3 changed files with 205 additions and 178 deletions

View File

@@ -51,6 +51,25 @@ docker run --rm -v .:/data elssh:el8
- `.github/workflows/build-images.yml` — manually triggered (`workflow_dispatch`), builds Docker images for each EL version and pushes to `ghcr.io`.
- `.github/workflows/build-rpm.yml` — runs on `v*` tags, builds RPMs inside Docker containers and creates a GitHub release.
## Linting & formatting
All shell scripts (`*.sh`) must pass `shellcheck` and `shfmt` before committing:
```bash
# Lint (warnings are errors)
shellcheck -S warning compile.sh pullsrc.sh
# Format check (must produce no diff)
shfmt -d -i 0 -bn -ci compile.sh pullsrc.sh
# Auto-fix formatting in-place
shfmt -w -i 0 -bn -ci compile.sh pullsrc.sh
```
- **shellcheck** `-S warning`: treat warnings as failures; informational/style notes may be suppressed inline with `# shellcheck disable=SCxxxx`.
- **shfmt** `-i 0 -bn -ci`: tabs for indentation (no extra indent), binary operators (`&&`, `||`, `|`) at start of next line, case body indented.
- Both tools must exit 0 before any commit touching `*.sh` files.
## Gitignore
`*-local*` is gitignored — version-local.env, editor swap files, etc. `*.tar.gz` is gitignored everywhere, including `downloads/`. Generated RPMs go to `output/` (also gitignored).

View File

@@ -11,7 +11,7 @@ trap 'echo -e "Aborted, error $? in command: $BASH_COMMAND"; trap ERR; exit 1' E
# Set magic variables for current file & dir
__dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
__file="${__dir}/$(basename "${BASH_SOURCE[0]}")"
__base="$(basename ${__file} .sh)"
__base="$(basename "${__file}" .sh)"
__root="$(cd "$(dirname "${__dir}")" && pwd)" # <-- change this as it depends on your app
arg1="${1:-}"
@@ -24,200 +24,204 @@ rpmtopdir=
# 2: build openssl statically
CHECKEXISTS() {
if [[ ! -f $__dir/downloads/$1 ]];then
echo "$1 not found, run 'pullsrc.sh', or manually put it in the downloads dir."
exit 1
fi
if [[ ! -f $__dir/downloads/$1 ]]; then
echo "$1 not found, run 'pullsrc.sh', or manually put it in the downloads dir."
exit 1
fi
}
GUESS_DIST() {
# will not work if rpm cmd not exists
if ! type -p rpm > /dev/null;then
echo 'unknown' && return 0
fi
# will not work if rpm cmd not exists
if ! type -p rpm >/dev/null; then
echo 'unknown' && return 0
fi
local dist=$(rpm --eval '%{?dist}' | tr -d '.')
local dist
dist=$(rpm --eval '%{?dist}' | tr -d '.')
# fallback to el7
[[ $dist == "el9" ]] && dist="el7"
[[ $dist == "el8" ]] && dist="el7"
[[ $dist == "an8" ]] && dist="el7" # Anolis 8
[[ $dist == "an7" ]] && dist="el7" # Anolis 7
[[ $dist == uel* ]] && dist="el7" # UOS20+
# fallback to el7
[[ $dist == "el9" ]] && dist="el7"
[[ $dist == "el8" ]] && dist="el7"
[[ $dist == "an8" ]] && dist="el7" # Anolis 8
[[ $dist == "an7" ]] && dist="el7" # Anolis 7
[[ $dist == uel* ]] && dist="el7" # UOS20+
[[ -n $dist ]] && echo $dist && return 0
[[ -n $dist ]] && echo $dist && return 0
local glibcver=$(ldd --version | head -n1 | grep -Eo '[0-9]+' | tr -d '\n')
local glibcver
glibcver=$(ldd --version | head -n1 | grep -Eo '[0-9]+' | tr -d '\n')
# centos 5 uses glibc 2.5
[[ $glibcver -eq 25 ]] && echo 'el5' && return 0
# centos 5 uses glibc 2.5
[[ $glibcver -eq 25 ]] && echo 'el5' && return 0
# centos 6 uses glibc 2.12
[[ $glibcver -eq 212 ]] && echo 'el6' && return 0
# centos 6 uses glibc 2.12
[[ $glibcver -eq 212 ]] && echo 'el6' && return 0
# centos 7 uses glibc 2.17
[[ $glibcver -eq 217 ]] && echo 'el7' && return 0
# centos 7 uses glibc 2.17
[[ $glibcver -eq 217 ]] && echo 'el7' && return 0
# centos 8 uses glibc 2.28, also map to el7
[[ $glibcver -eq 228 ]] && echo 'el7' && return 0
# centos 8 uses glibc 2.28, also map to el7
[[ $glibcver -eq 228 ]] && echo 'el7' && return 0
# some centos-like dists ships higher version of glibc, fallback to el7
[[ $glibcver -gt 217 ]] && echo 'el7' && return 0
# some centos-like dists ships higher version of glibc, fallback to el7
[[ $glibcver -gt 217 ]] && echo 'el7' && return 0
}
TOPDIR_SELECT() {
local DISTVER=$(GUESS_DIST)
case $DISTVER in
el7)
rpmtopdir=el7
if [[ -z ${WITH_OPENSSL+x} ]]; then
local opensslver=$(rpm -q openssl --qf "%{VERSION}" 2>/dev/null | cut -d. -f1)
[[ $opensslver -ge 3 ]] && WITH_OPENSSL=1 || WITH_OPENSSL=2
fi
;;
el6)
rpmtopdir=el6
WITH_OPENSSL=${WITH_OPENSSL:-2}
;;
el5)
rpmtopdir=el5
WITH_OPENSSL=${WITH_OPENSSL:-2}
;;
*)
echo "Distro undefined, please specify manually: el5 el6 el7"
echo -e "\nCurrent OS:"
[[ -f /etc/os-release ]] && cat /etc/os-release
[[ -f /etc/redhat-release ]] && cat /etc/redhat-release
[[ -f /etc/system-release ]] && cat /etc/system-release
echo -e "Current OS vendor: $(rpm --eval '%{?_vendor}') \n"
return 1
;;
esac
local DISTVER
DISTVER=$(GUESS_DIST)
case $DISTVER in
el7)
rpmtopdir=el7
if [[ -z ${WITH_OPENSSL+x} ]]; then
local opensslver
opensslver=$(rpm -q openssl --qf "%{VERSION}" 2>/dev/null | cut -d. -f1)
[[ $opensslver -ge 3 ]] && WITH_OPENSSL=1 || WITH_OPENSSL=2
fi
;;
el6)
rpmtopdir=el6
WITH_OPENSSL=${WITH_OPENSSL:-2}
;;
el5)
rpmtopdir=el5
WITH_OPENSSL=${WITH_OPENSSL:-2}
;;
*)
echo "Distro undefined, please specify manually: el5 el6 el7"
echo -e "\nCurrent OS:"
[[ -f /etc/os-release ]] && cat /etc/os-release
[[ -f /etc/redhat-release ]] && cat /etc/redhat-release
[[ -f /etc/system-release ]] && cat /etc/system-release
echo -e "Current OS vendor: $(rpm --eval '%{?_vendor}') \n"
return 1
;;
esac
}
BUILD_RPM() {
source version.env
[[ -f version-local.env ]] && source version-local.env
# shellcheck disable=SC1091
source version.env
# shellcheck disable=SC1091
[[ -f version-local.env ]] && source version-local.env
local SOURCES=( $OPENSSHSRC \
$OPENSSLSRC \
$ASKPASSSRC \
)
# UOS20 build: prefix PKGREL with "uos20." so the resulting RPMs are
# distinguishable from the standard build (e.g. PKGREL `1` becomes
# `uos20.1`, not `uos201`), and pass `uos20 1` to the spec to enable
# the kernel-panic patch.
# NOTE: RPM does not allow '-' in the Release field (it is the
# Version/Release delimiter), so '.' is used as the separator.
local _pkgrel="${PKGREL:-1}"
if [[ ${UOS20:-0} == 1 ]]; then
_pkgrel="uos20.${_pkgrel}"
fi
local RPMBUILDOPTS=( \
--define "with_openssl ${WITH_OPENSSL:-2}" \
--define "opensslver ${OPENSSLVER}" \
--define "opensshver ${OPENSSHVER}" \
--define "opensshpkgrel ${_pkgrel}" \
--define 'debug_package %{nil}' \
--define 'no_gtk2 1' \
--define 'skip_gnome_askpass 1' \
--define 'skip_x11_askpass 1' \
)
[[ ${UOS20:-0} == 1 ]] && RPMBUILDOPTS+=('--define' 'uos20 1')
local SOURCES=("$OPENSSHSRC"
"$OPENSSLSRC"
"$ASKPASSSRC"
)
# UOS20 build: prefix PKGREL with "uos20." so the resulting RPMs are
# distinguishable from the standard build (e.g. PKGREL `1` becomes
# `uos20.1`, not `uos201`), and pass `uos20 1` to the spec to enable
# the kernel-panic patch.
# NOTE: RPM does not allow '-' in the Release field (it is the
# Version/Release delimiter), so '.' is used as the separator.
local _pkgrel="${PKGREL:-1}"
if [[ ${UOS20:-0} == 1 ]]; then
_pkgrel="uos20.${_pkgrel}"
fi
local RPMBUILDOPTS=(
--define "with_openssl ${WITH_OPENSSL:-2}"
--define "opensslver ${OPENSSLVER}"
--define "opensshver ${OPENSSHVER}"
--define "opensshpkgrel ${_pkgrel}"
--define 'debug_package %{nil}'
--define 'no_gtk2 1'
--define 'skip_gnome_askpass 1'
--define 'skip_x11_askpass 1'
)
[[ ${UOS20:-0} == 1 ]] && RPMBUILDOPTS+=('--define' 'uos20 1')
# EL5 dist fixes
if [[ $rpmtopdir == *el5 ]]; then
SOURCES+=($PERLSRC)
# EL5 dist fixes
if [[ $rpmtopdir == *el5 ]]; then
SOURCES+=("$PERLSRC")
# Hack: fake the perl src when perl is ready already(docker images)
[[ $(perl -e 'print $] >= 5.010 ? 1 : 0') -eq 1 ]] && \
touch ./downloads/$PERLSRC
RPMBUILDOPTS+=('--define' "perlver ${PERLVER}" '--define' 'dist .el5')
export CC=gcc44
fi
# Hack: fake the perl src when perl is ready already(docker images)
[[ $(perl -e 'print $] >= 5.010 ? 1 : 0') -eq 1 ]] \
&& touch ./downloads/"$PERLSRC"
# add dist variable if not defined
[[ $rpmtopdir == *el7 ]] && [[ -z $(rpm --eval '%{?dist}') ]] && \
RPMBUILDOPTS+=('--define' "dist .$(rpm -q glibc | rev | cut -d. -f2 | rev)")
RPMBUILDOPTS+=('--define' "perlver ${PERLVER}" '--define' 'dist .el5')
export CC=gcc44
fi
pushd $rpmtopdir
RPMBUILDOPTS+=('--define' "_topdir $PWD")
for fn in ${SOURCES[@]}; do
CHECKEXISTS $fn && \
install -v -m666 $__dir/downloads/$fn ./SOURCES/
done
# add dist variable if not defined
[[ $rpmtopdir == *el7 ]] && [[ -z $(rpm --eval '%{?dist}') ]] \
&& RPMBUILDOPTS+=('--define' "dist .$(rpm -q glibc | rev | cut -d. -f2 | rev)")
if [[ ${M32:-0} != 0 ]]; then
local SETARCH="setarch i386"
RPMBUILDOPTS+=('--target' i686)
export CFLAGS="${CFLAGS:-} -m32" LDFLAGS="${LDFLAGS:-} -m32"
fi
pushd $rpmtopdir
RPMBUILDOPTS+=('--define' "_topdir $PWD")
for fn in "${SOURCES[@]}"; do
CHECKEXISTS "$fn" \
&& install -v -m666 "$__dir"/downloads/"$fn" ./SOURCES/
done
${SETARCH:-} \
rpmbuild -bb ./SPECS/${SPECFILE:-openssh.spec} "${RPMBUILDOPTS[@]}"
if [[ $? -ne 0 ]]; then
echo "Error: rpmbuild failed with exit code $?"
exit 1
fi
if [[ ${M32:-0} != 0 ]]; then
local SETARCH="setarch i386"
RPMBUILDOPTS+=('--target' i686)
export CFLAGS="${CFLAGS:-} -m32" LDFLAGS="${LDFLAGS:-} -m32"
fi
mkdir -p $__dir/output
find ./RPMS -type f -name '*.rpm' -exec install -v -m644 {} $__dir/output/ \;
popd
if ! ${SETARCH:-} rpmbuild -bb ./SPECS/"${SPECFILE:-openssh.spec}" "${RPMBUILDOPTS[@]}"; then
echo "Error: rpmbuild failed with exit code $?"
exit 1
fi
mkdir -p "$__dir"/output
find ./RPMS -type f -name '*.rpm' -exec install -v -m644 {} "$__dir"/output/ \;
popd
}
LIST_RPMDIR(){
local RPMDIR=$__dir/${rpmtopdir}/RPMS/$(rpm --eval '%{_arch}')
[[ -d $RPMDIR ]] && echo $RPMDIR
LIST_RPMDIR() {
local RPMDIR
RPMDIR=$__dir/${rpmtopdir}/RPMS/$(rpm --eval '%{_arch}')
[[ -d $RPMDIR ]] && echo "$RPMDIR"
}
LIST_RPMS() {
local RPMDIR=$(LIST_RPMDIR)
[[ -d $RPMDIR ]] && find $RPMDIR -type f -name '*.rpm'
local RPMDIR
RPMDIR=$(LIST_RPMDIR)
[[ -d $RPMDIR ]] && find "$RPMDIR" -type f -name '*.rpm'
}
# sub cmds
case $arg1 in
GETEL)
GUESS_DIST
exit 0
;;
GETRPM)
TOPDIR_SELECT
LIST_RPMS
exit 0
;;
RPMDIR)
TOPDIR_SELECT
LIST_RPMDIR
exit 0
;;
*)
if [[ -n $arg1 && ! -d $arg1 ]]; then
echo -e "Subcmd: $arg1 not found.\n GETEL, GETRPM, RPMDIR"
exit 1
fi
;;
GETEL)
GUESS_DIST
exit 0
;;
GETRPM)
TOPDIR_SELECT
LIST_RPMS
exit 0
;;
RPMDIR)
TOPDIR_SELECT
LIST_RPMDIR
exit 0
;;
*)
if [[ -n $arg1 && ! -d $arg1 ]]; then
echo -e "Subcmd: $arg1 not found.\n GETEL, GETRPM, RPMDIR"
exit 1
fi
;;
esac
# manual specified dist
if [[ -n $arg1 && -d $arg1 ]]; then
rpmtopdir=$arg1
BUILD_RPM
exit 0
rpmtopdir=$arg1
BUILD_RPM
exit 0
fi
# auto select dist
TOPDIR_SELECT
if [[ ! -d $rpmtopdir ]]; then
echo "This script works only in el5/el6/el7"
echo "eg: ${0} el7"
exit 1
if [[ ! -d $rpmtopdir ]]; then
echo "This script works only in el5/el6/el7"
echo "eg: ${0} el7"
exit 1
fi
if [[ -d $rpmtopdir ]]; then
BUILD_RPM
BUILD_RPM
fi

View File

@@ -11,7 +11,7 @@ trap 'echo -e "Aborted, error $? in command: $BASH_COMMAND"; trap ERR; exit 1' E
# Set magic variables for current file & dir
__dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
__file="${__dir}/$(basename "${BASH_SOURCE[0]}")"
__base="$(basename ${__file} .sh)"
__base="$(basename "${__file}" .sh)"
__root="$(cd "$(dirname "${__dir}")" && pwd)" # <-- change this as it depends on your app
arg1="${1:-}"
@@ -20,57 +20,61 @@ arg1="${1:-}"
# allow command fail:
# fail_command || true
# shellcheck disable=SC1091
source version.env
# shellcheck disable=SC1091
[[ -f version-local.env ]] && source version-local.env
OPENSSHMIR=https://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable
OPENSSLMIR=https://www.openssl.org/source/
# shellcheck disable=SC2153
OPENSSLMIR=${GH_PROXY:-}https://github.com/openssl/openssl/releases/download/openssl-${OPENSSLVER}/
ASKPASSMIR=https://src.fedoraproject.org/repo/pkgs/openssh/x11-ssh-askpass-1.2.4.1.tar.gz/8f2e41f3f7eaa8543a2440454637f3c3
PERLMIR=https://www.cpan.org/src/5.0
LATEST_OPENSSH() {
curl -s "$OPENSSHMIR/" 2>/dev/null | \
grep -o 'openssh-[0-9.]*p[0-9]*\.tar\.gz' | \
sed 's/openssh-//; s/\.tar\.gz//' | \
sort -Vu | tail -1 || true
curl -s "$OPENSSHMIR/" 2>/dev/null \
| grep -o 'openssh-[0-9.]*p[0-9]*\.tar\.gz' \
| sed 's/openssh-//; s/\.tar\.gz//' \
| sort -Vu | tail -1 || true
}
if [[ $arg1 == "--latest" ]]; then
latest=$(LATEST_OPENSSH)
current="${OPENSSHVER}"
echo "Current version: $current"
echo "Latest version: $latest"
if [[ "$latest" == "$current" ]]; then
echo "Already up to date."
else
echo "NEW VERSION AVAILABLE: $latest"
fi
exit 0
latest=$(LATEST_OPENSSH)
# shellcheck disable=SC2153
current="${OPENSSHVER}"
echo "Current version: $current"
echo "Latest version: $latest"
if [[ "$latest" == "$current" ]]; then
echo "Already up to date."
else
echo "NEW VERSION AVAILABLE: $latest"
fi
exit 0
fi
mkdir -p downloads
pushd downloads
if [[ ! -f $OPENSSLSRC && ${DOCKERBUILD:-0} == 0 ]]; then
echo "Get:" $OPENSSLMIR/$OPENSSLSRC
wget --no-check-certificate $OPENSSLMIR/$OPENSSLSRC || \
echo "!!! Please download $OPENSSLSRC in $PWD by yourself."
echo "Get:" "$OPENSSLMIR"/"$OPENSSLSRC"
wget --no-check-certificate "$OPENSSLMIR"/"$OPENSSLSRC" \
|| echo "!!! Please download $OPENSSLSRC in $PWD by yourself."
fi
if [[ ! -f $OPENSSHSRC && ${DOCKERBUILD:-0} == 0 ]]; then
echo Get: $OPENSSHMIR/$OPENSSHSRC
wget --no-check-certificate $OPENSSHMIR/$OPENSSHSRC || \
echo "!!! Please download $OPENSSHSRC in $PWD by yourself."
echo Get: "$OPENSSHMIR"/"$OPENSSHSRC"
wget --no-check-certificate "$OPENSSHMIR"/"$OPENSSHSRC" \
|| echo "!!! Please download $OPENSSHSRC in $PWD by yourself."
fi
if [[ ! -f $ASKPASSSRC && ${DOCKERBUILD:-0} == 0 ]]; then
echo Get: $ASKPASSMIR/$ASKPASSSRC
wget --no-check-certificate $ASKPASSMIR/$ASKPASSSRC || \
echo "!!! Please download $ASKPASSSRC in $PWD by yourself."
echo Get: "$ASKPASSMIR"/"$ASKPASSSRC"
wget --no-check-certificate "$ASKPASSMIR"/"$ASKPASSSRC" \
|| echo "!!! Please download $ASKPASSSRC in $PWD by yourself."
fi
if [[ $($__dir/compile.sh GETEL) == "el5" && ${DOCKERBUILD:-0} == 1 && ! -f $PERLSRC ]]; then
echo Get: $PERLMIR/$PERLSRC
wget --no-check-certificate $PERLMIR/$PERLSRC || \
echo "!!! Please download $PERLSRC in $PWD by yourself."
if [[ $("$__dir"/compile.sh GETEL) == "el5" && ${DOCKERBUILD:-0} == 1 && ! -f $PERLSRC ]]; then
echo Get: "$PERLMIR"/"$PERLSRC"
wget --no-check-certificate "$PERLMIR"/"$PERLSRC" \
|| echo "!!! Please download $PERLSRC in $PWD by yourself."
fi