diff --git a/.github/workflows/files-changed.yml b/.github/workflows/files-changed.yml index 2975a0cfcbf..a7b116fec79 100644 --- a/.github/workflows/files-changed.yml +++ b/.github/workflows/files-changed.yml @@ -25,6 +25,8 @@ on: value: ${{ jobs.detect.outputs.json }} e2e: value: ${{ jobs.detect.outputs.e2e }} + shell: + value: ${{ jobs.detect.outputs.shell }} permissions: contents: read @@ -45,6 +47,7 @@ jobs: yaml: ${{ steps.changes.outputs.yaml }} json: ${{ steps.changes.outputs.json }} e2e: ${{ steps.changes.outputs.e2e }} + shell: ${{ steps.changes.outputs.shell }} steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1 @@ -124,3 +127,7 @@ jobs: - "tests/e2e/**" - "tools/test-e2e.sh" - "playwright.config.ts" + + shell: + - "**/*.sh" + - ".shellcheckrc" diff --git a/.github/workflows/pull-compliance.yml b/.github/workflows/pull-compliance.yml index 9ccfc76315e..801966e1444 100644 --- a/.github/workflows/pull-compliance.yml +++ b/.github/workflows/pull-compliance.yml @@ -54,6 +54,9 @@ jobs: - if: needs.files-changed.outputs.actions == 'true' run: make lint-actions + - if: needs.files-changed.outputs.shell == 'true' + run: make lint-shell + checks-backend: if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true' needs: files-changed diff --git a/.shellcheckrc b/.shellcheckrc new file mode 100644 index 00000000000..a012fba96e5 --- /dev/null +++ b/.shellcheckrc @@ -0,0 +1 @@ +disable=SC1091,SC2001,SC2002,SC2016,SC2028,SC2046,SC2124,SC2128,SC2129,SC2154,SC2155,SC2164,SC2181,SC2207 diff --git a/Makefile b/Makefile index 94f07a44125..52a266fa39b 100644 --- a/Makefile +++ b/Makefile @@ -20,6 +20,9 @@ SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.33.2 # renova XGO_PACKAGE ?= src.techknowlogick.com/xgo@v1.9.0 # renovate: datasource=go GOVULNCHECK_PACKAGE ?= golang.org/x/vuln/cmd/govulncheck@v1.3.0 # renovate: datasource=go ACTIONLINT_PACKAGE ?= github.com/rhysd/actionlint/cmd/actionlint@v1.7.12 # renovate: datasource=go +SHELLCHECK_IMAGE ?= docker.io/koalaman/shellcheck:v0.11.0@sha256:61862eba1fcf09a484ebcc6feea46f1782532571a34ed51fedf90dd25f925a8d # renovate: datasource=docker + +CONTAINER_RUNTIME ?= $(shell hash docker >/dev/null 2>&1 && echo docker || echo podman) HAS_GO := $(shell hash $(GO) > /dev/null 2>&1 && echo yes) ifeq ($(HAS_GO), yes) @@ -271,7 +274,7 @@ checks-frontend: lockfile-check svg-check ## check frontend files checks-backend: tidy-check swagger-check openapi3-check fmt-check swagger-validate security-check ## check backend files .PHONY: lint -lint: lint-frontend lint-backend lint-templates lint-swagger lint-spell lint-md lint-actions lint-json lint-yaml ## lint everything +lint: lint-frontend lint-backend lint-templates lint-swagger lint-spell lint-md lint-actions lint-json lint-yaml lint-shell ## lint everything .PHONY: lint-fix lint-fix: lint-frontend-fix lint-backend-fix lint-spell-fix ## lint everything and fix issues @@ -348,6 +351,10 @@ lint-actions: .venv ## lint action workflow files @$(GO) run $(ACTIONLINT_PACKAGE) @uv run --frozen zizmor --quiet --min-confidence=medium .github +.PHONY: lint-shell +lint-shell: ## lint shell scripts + @SHELLCHECK_IMAGE=$(SHELLCHECK_IMAGE) CONTAINER_RUNTIME=$(CONTAINER_RUNTIME) ./tools/lint-shell.sh $$(git ls-files '*.sh') + .PHONY: lint-templates lint-templates: .venv node_modules ## lint template files @node tools/lint-templates-svg.ts @@ -473,11 +480,11 @@ migrations.individual.test\#%: .PHONY: playwright playwright: deps-frontend - @./tools/test-e2e.sh install + @CONTAINER_RUNTIME=$(CONTAINER_RUNTIME) ./tools/test-e2e.sh install .PHONY: test-e2e test-e2e: playwright frontend backend - @EXECUTABLE=$(EXECUTABLE) ./tools/test-e2e.sh run $(GITEA_TEST_E2E_FLAGS) + @CONTAINER_RUNTIME=$(CONTAINER_RUNTIME) EXECUTABLE=$(EXECUTABLE) ./tools/test-e2e.sh run $(GITEA_TEST_E2E_FLAGS) .PHONY: build build: frontend backend ## build everything diff --git a/contrib/upgrade.sh b/contrib/upgrade.sh index 2593d245093..71d0435d146 100755 --- a/contrib/upgrade.sh +++ b/contrib/upgrade.sh @@ -126,6 +126,7 @@ giteacmd manager flush-queues echo "Stopping gitea at $(date)" $service_stop echo "Creating backup in $giteahome" +# shellcheck disable=SC2086 # flag string giteacmd dump $backupopts echo "Updating binary at $giteabin" cp -f "$giteabin" "$giteabin.bak" && mv -f "$binname" "$giteabin" diff --git a/docker/rootless/usr/local/bin/docker-entrypoint.sh b/docker/rootless/usr/local/bin/docker-entrypoint.sh index ca509214bff..4ffc4ff3a11 100755 --- a/docker/rootless/usr/local/bin/docker-entrypoint.sh +++ b/docker/rootless/usr/local/bin/docker-entrypoint.sh @@ -13,5 +13,5 @@ fi if [ $# -gt 0 ]; then exec "$@" else - exec /usr/local/bin/gitea -c ${GITEA_APP_INI} web + exec /usr/local/bin/gitea -c "${GITEA_APP_INI}" web fi diff --git a/docker/rootless/usr/local/bin/docker-setup.sh b/docker/rootless/usr/local/bin/docker-setup.sh index feab02a3793..3320d69dde8 100755 --- a/docker/rootless/usr/local/bin/docker-setup.sh +++ b/docker/rootless/usr/local/bin/docker-setup.sh @@ -1,23 +1,23 @@ #!/bin/bash # Prepare git folder -mkdir -p ${HOME} && chmod 0700 ${HOME} -if [ ! -w ${HOME} ]; then echo "${HOME} is not writable"; exit 1; fi +mkdir -p "${HOME}" && chmod 0700 "${HOME}" +if [ ! -w "${HOME}" ]; then echo "${HOME} is not writable"; exit 1; fi # Prepare custom folder -mkdir -p ${GITEA_CUSTOM} && chmod 0700 ${GITEA_CUSTOM} +mkdir -p "${GITEA_CUSTOM}" && chmod 0700 "${GITEA_CUSTOM}" # Prepare temp folder -mkdir -p ${GITEA_TEMP} && chmod 0700 ${GITEA_TEMP} -if [ ! -w ${GITEA_TEMP} ]; then echo "${GITEA_TEMP} is not writable"; exit 1; fi +mkdir -p "${GITEA_TEMP}" && chmod 0700 "${GITEA_TEMP}" +if [ ! -w "${GITEA_TEMP}" ]; then echo "${GITEA_TEMP} is not writable"; exit 1; fi #Prepare config file -if [ ! -f ${GITEA_APP_INI} ]; then +if [ ! -f "${GITEA_APP_INI}" ]; then #Prepare config file folder - GITEA_APP_INI_DIR=$(dirname ${GITEA_APP_INI}) - mkdir -p ${GITEA_APP_INI_DIR} && chmod 0700 ${GITEA_APP_INI_DIR} - if [ ! -w ${GITEA_APP_INI_DIR} ]; then echo "${GITEA_APP_INI_DIR} is not writable"; exit 1; fi + GITEA_APP_INI_DIR=$(dirname "${GITEA_APP_INI}") + mkdir -p "${GITEA_APP_INI_DIR}" && chmod 0700 "${GITEA_APP_INI_DIR}" + if [ ! -w "${GITEA_APP_INI_DIR}" ]; then echo "${GITEA_APP_INI_DIR} is not writable"; exit 1; fi # Set INSTALL_LOCK to true only if SECRET_KEY is not empty and # INSTALL_LOCK is empty @@ -34,7 +34,7 @@ if [ ! -f ${GITEA_APP_INI} ]; then ROOT_URL=${ROOT_URL:-""} \ DISABLE_SSH=${DISABLE_SSH:-"false"} \ SSH_PORT=${SSH_PORT:-"2222"} \ - SSH_LISTEN_PORT=${SSH_LISTEN_PORT:-$SSH_PORT} \ + SSH_LISTEN_PORT=${SSH_LISTEN_PORT:-} \ DB_TYPE=${DB_TYPE:-"sqlite3"} \ DB_HOST=${DB_HOST:-"localhost:3306"} \ DB_NAME=${DB_NAME:-"gitea"} \ @@ -44,8 +44,8 @@ if [ ! -f ${GITEA_APP_INI} ]; then DISABLE_REGISTRATION=${DISABLE_REGISTRATION:-"false"} \ REQUIRE_SIGNIN_VIEW=${REQUIRE_SIGNIN_VIEW:-"false"} \ SECRET_KEY=${SECRET_KEY:-""} \ - envsubst < /etc/templates/app.ini > ${GITEA_APP_INI} + envsubst < /etc/templates/app.ini > "${GITEA_APP_INI}" fi # Replace app.ini settings with env variables in the form GITEA__SECTION_NAME__KEY_NAME -environment-to-ini --config ${GITEA_APP_INI} +environment-to-ini --config "${GITEA_APP_INI}" diff --git a/renovate.json5 b/renovate.json5 index c5d712dc0ab..bf913011fbe 100644 --- a/renovate.json5 +++ b/renovate.json5 @@ -18,6 +18,7 @@ "managerFilePatterns": ["/(^|/)Makefile$/"], "matchStrings": [ "[A-Z_]+_PACKAGE\\s*\\?=\\s*(?[^@\\s]+?)(?:/cmd/[^@/\\s]+)?@(?\\S+)\\s+# renovate: datasource=(?\\S+)", + "[A-Z_]+_IMAGE\\s*\\?=\\s*(?[^:\\s]+):(?[^@\\s]+)@(?sha256:[a-f0-9]+)\\s+# renovate: datasource=(?\\S+)", ], }, ], diff --git a/snap/part-gitea-build.sh b/snap/part-gitea-build.sh index 8388c16e06e..005162488fa 100755 --- a/snap/part-gitea-build.sh +++ b/snap/part-gitea-build.sh @@ -1,7 +1,7 @@ #!/bin/sh set -e -if [ ! -f go.mod -o ! -d snap ]; then +if [ ! -f go.mod ] || [ ! -d snap ]; then echo "This script should be run from the root of the gitea repository" exit 1 fi diff --git a/snap/part-gitea-pull.sh b/snap/part-gitea-pull.sh index 0d117bb4d1d..83fde11a129 100755 --- a/snap/part-gitea-pull.sh +++ b/snap/part-gitea-pull.sh @@ -1,7 +1,7 @@ #!/bin/sh set -e -if [ ! -f go.mod -o ! -d snap ]; then +if [ ! -f go.mod ] || [ ! -d snap ]; then echo "This script should be run from the root of the gitea repository" exit 1 fi diff --git a/tools/lint-shell.sh b/tools/lint-shell.sh new file mode 100755 index 00000000000..dac838e8338 --- /dev/null +++ b/tools/lint-shell.sh @@ -0,0 +1,11 @@ +#!/bin/bash +set -euo pipefail + +CONTAINER_RUNTIME="${CONTAINER_RUNTIME:-docker}" +VERSION=$(echo "$SHELLCHECK_IMAGE" | sed -E 's/.*:v([0-9.]+)@.*/\1/') + +if hash shellcheck 2>/dev/null && shellcheck --version | grep -qx "version: $VERSION"; then + exec shellcheck --color=always "$@" +else + exec "$CONTAINER_RUNTIME" run --rm -v "$PWD":/mnt -w /mnt "$SHELLCHECK_IMAGE" --color=always "$@" +fi diff --git a/tools/test-e2e.sh b/tools/test-e2e.sh index d6c053ff1f5..be3e848ee1d 100755 --- a/tools/test-e2e.sh +++ b/tools/test-e2e.sh @@ -71,8 +71,10 @@ if [ "$CMD" = "install" ]; then if [ "$PLAYWRIGHT_MODE" = "local" ]; then # on GitHub Actions VMs, playwright's system deps are pre-installed if [ -z "${GITHUB_ACTIONS:-}" ]; then + # shellcheck disable=SC2086 # flag string pnpm exec playwright install --with-deps chromium firefox ${PLAYWRIGHT_FLAGS:-} else + # shellcheck disable=SC2086 # flag string pnpm exec playwright install chromium firefox ${PLAYWRIGHT_FLAGS:-} fi else