chore(deps): bump actions/stale from 10 to 11 - #1265
Merged
Conversation
|
@dependabot rebase |
Contributor
Author
|
Sorry, only users with push access can use that command. |
"""
A small tool to check shell scripts for a handful of project-specific
style issues that shellcheck doesn't cover. This file is intentionally
kept lightweight and self-fixing (via --fix) so CI can auto-correct
common problems.
Usage:
./scripts/checkstyle.py # lint repository
./scripts/checkstyle.py --fix # attempt to automatically fix
./scripts/checkstyle.py <path> ... # lint specific files
./scripts/checkstyle.py --internal-test-regex
This rewrite modernizes typing to PEP 585, fixes linter complaints
(ruff/pyflakes/isort) and replaces builtin exit() calls with sys.exit().
"""
from __future__ import annotations
import argparse
import os
import re
import sys
from pathlib import Path
from collections.abc import Callable
from typing import Any
Rule = dict[str, Any]
class c:
RED = "\033[91m"
GREEN = "\033[92m"
YELLOW = "\033[93m"
BLUE = "\033[94m"
MAGENTA = "\033[95m"
CYAN = "\033[96m"
RESET = "\033[0m"
BOLD = "\033[1m"
UNDERLINE = "\033[4m"
@staticmethod
def LINK(href: str, text: str) -> str:
# Terminal hyperlink; some terminals will ignore it which is fine.
return f"\033]8;;{href}\a{text}\033]8;;\a"
def util_get_strs(line: str, m: re.Match) -> tuple[str, str, str]:
return (line[: m.start("match")], line[m.start("match") : m.end("match")], line[m.end("match") :])
# Fixers ---------------------------------------------------------------
def no_double_backslash_fixer(line: str, m: re.Match) -> str:
prestr, midstr, poststr = util_get_strs(line, m)
return f"{prestr}{midstr[1:]}{poststr}"
def no_pwd_capture_fixer(line: str, m: re.Match) -> str:
prestr, _, poststr = util_get_strs(line, m)
return f"{prestr}$PWD{poststr}"
def no_test_double_equals_fixer(line: str, m: re.Match) -> str:
prestr, _, poststr = util_get_strs(line, m)
# Replace only the matched == with =
return f"{prestr}={poststr}"
def no_function_keyword_fixer(line: str, m: re.Match) -> str:
prestr, midstr, poststr = util_get_strs(line, m)
mid = midstr.strip()
# remove leading 'function'
if mid.startswith("function"):
mid = mid[len("function") :].strip()
# strip any trailing parentheses content; replace with 'name() '
paren_idx = mid.find("(")
name = mid if paren_idx == -1 else mid[:paren_idx]
name = name.strip()
return f"{prestr}{name}() {poststr}"
def no_verbose_redirection_fixer(line: str, m: re.Match) -> str:
prestr, _, poststr = util_get_strs(line, m)
return f"{prestr}&>/dev/null{poststr}"
# Linting --------------------------------------------------------------
def lintfile(file: Path, rules: list[Rule], options: dict[str, Any]) -> None:
content_arr = file.read_text(encoding="utf8").split("\n")
for line_i, line in enumerate(content_arr):
if "checkstyle-ignore" in line:
continue
for rule in rules:
file_name = file.name
should_run = (
("sh" in rule["fileTypes"] and file_name.endswith(".sh"))
or (
"bash" in rule["fileTypes"]
and (
file_name.endswith(".bash")
or file_name.endswith(".bats")
or file_name.startswith("git-")
)
)
)
if options.get("verbose"):
# use explicit conversion flag instead of str()
print(f"{file!s}: {should_run}")
if not should_run:
continue
m = re.search(rule["regex"], line)
if m is not None and m.group("match") is not None:
dirpath = os.path.relpath(file.resolve(), Path.cwd())
prestr = line[: m.start("match")]
midstr = line[m.start("match") : m.end("match")]
poststr = line[m.end("match") :]
print(f"{c.CYAN}{dirpath}{c.RESET}:{line_i + 1}")
print(f"{c.MAGENTA}{rule['name']}{c.RESET}: {rule['reason']}")
print(f"{prestr}{c.RED}{midstr}{c.RESET}{poststr}")
print()
if options.get("fix"):
content_arr[line_i] = rule["fixerFn"](line, m)
rule["found"] += 1
if options.get("fix"):
file.write_text("\n".join(content_arr), encoding="utf8")
# Rules ----------------------------------------------------------------
def build_rules() -> list[Rule]:
return [
{
"name": "no-pwd-capture",
"regex": r"(?P<match>\$\(\pwd\))".replace(r"\pwd", "pwd"),
"reason": "$PWD is essentially equivalent to $(pwd) without the overhead of a subshell",
"fileTypes": ["bash", "sh"],
"fixerFn": no_pwd_capture_fixer,
"testPositiveMatches": ["$(pwd)"],
"testNegativeMatches": ["$PWD"],
},
{
"name": "no-test-double-equals",
# match == inside single bracket test constructs like: [ a == b ]
"regex": r"(?P<match>==)",
"reason": "Disallow double equals in single-bracket test expressions for consistency",
"fileTypes": ["bash", "sh"],
"fixerFn": no_test_double_equals_fixer,
"testPositiveMatches": ["[ a == b ]", "[ \"${lines[0]}\" == blah ]"],
"testNegativeMatches": ["[ a = b ]", "[[ a == b ]]", "[[ a = b ]]"],
},
{
"name": "no-function-keyword",
"regex": r"^[ \t]*(?P<match>function .*?(?:\([ \t]*\))?[ \t]*)\{",
"reason": "Only allow functions declared like `fn_name() { :; }` for consistency (see " + c.LINK("https://www.shellcheck.net/wiki/SC2113", "ShellCheck SC2113") + ")",
"fileTypes": ["bash", "sh"],
"fixerFn": no_function_keyword_fixer,
"testPositiveMatches": ["function fn() { :; }", "function fn { :; }"],
"testNegativeMatches": ["fn() { :; }"],
},
{
"name": "no-verbose-redirection",
"regex": r"(?P<match>(>/dev/null 2>&1|2>/dev/null 1>&2))",
"reason": "Use `&>/dev/null` instead of `>/dev/null 2>&1` or `2>/dev/null 1>&2` for consistency",
"fileTypes": ["bash"],
"fixerFn": no_verbose_redirection_fixer,
"testPositiveMatches": ["echo woof >/dev/null 2>&1", "echo woof 2>/dev/null 1>&2"],
"testNegativeMatches": ["echo woof &>/dev/null", "echo woof >&/dev/null"],
},
]
# CLI ------------------------------------------------------------------
def main() -> None:
rules = build_rules()
for rule in rules:
rule.update({"found": 0})
parser = argparse.ArgumentParser()
parser.add_argument("files", metavar="FILES", nargs="*")
parser.add_argument("--fix", action="store_true")
parser.add_argument("--verbose", action="store_true")
parser.add_argument("--internal-test-regex", action="store_true")
args = parser.parse_args()
if args.internal_test_regex:
for rule in rules:
for positive in rule.get("testPositiveMatches", []):
m = re.search(rule["regex"], positive)
if m is None or m.group("match") is None:
print(f"{c.MAGENTA}{rule['name']}{c.RESET}: Failed {c.CYAN}positive{c.RESET} test:")
print(f"=> {positive}\n")
for negative in rule.get("testNegativeMatches", []):
m = re.search(rule["regex"], negative)
if m is not None and m.group("match") is not None:
print(f"{c.MAGENTA}{rule['name']}{c.RESET}: Failed {c.YELLOW}negative{c.RESET} test:")
print(f"=> {negative}\n")
print("Done.")
return
options = {"fix": args.fix, "verbose": args.verbose}
# gather files
files_to_check: list[Path] = []
if len(args.files) > 0:
for f in args.files:
p = Path(f)
if p.is_file():
files_to_check.append(p)
else:
for file in Path.cwd().rglob("*"):
if ".git" in str(file.absolute()):
continue
if file.is_file():
files_to_check.append(file)
for file in files_to_check:
lintfile(file, rules, options)
# print final results
print(f"{c.UNDERLINE}TOTAL ISSUES{c.RESET}")
for rule in rules:
print(f"{c.MAGENTA}{rule['name']}{c.RESET}: {rule['found']}")
grand_total = sum(rule["found"] for rule in rules)
print(f"GRAND TOTAL: {grand_total}")
print(f"{c.BOLD}{c.YELLOW}NOTE:{c.RESET} Run \"./scripts/checkstyle.py --fix\" to automatically fix all issues (may need to run multiple times)")
if grand_total == 0:
sys.exit(0)
sys.exit(2)
if __name__ == "__main__":
main() |
Bumps [actions/stale](https://github.com/actions/stale) from 10 to 11. - [Release notes](https://github.com/actions/stale/releases) - [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md) - [Commits](actions/stale@v10...v11) --- updated-dependencies: - dependency-name: actions/stale dependency-version: '11' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com>
hyperupcall
force-pushed
the
dependabot/github_actions/actions/stale-11
branch
from
September 1, 2026 19:24
dfd2d37 to
46741d1
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Bumps actions/stale from 10 to 11.
Release notes
Sourced from actions/stale's releases.
... (truncated)
Changelog
Sourced from actions/stale's changelog.
... (truncated)
Commits
4391f3dFix 24 high severity vulnerabilities by overriding brace-expansion to 5.0.8 (...eaf9131refactor: update imports to use ES module syntax and improve test structure (...Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting
@dependabot rebase.Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR:
@dependabot rebasewill rebase this PR@dependabot recreatewill recreate this PR, overwriting any edits that have been made to it@dependabot show <dependency name> ignore conditionswill show all of the ignore conditions of the specified dependency@dependabot ignore this major versionwill close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this minor versionwill close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this dependencywill close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)