Answer architecture round 1: 0 🔴, 5 🟡; a job of its own that only releases wait for, filing each vulnerability atop the plan by a pull request, a recorded decision, one gate list, and Renovate on the go run tools
This commit is contained in:
@@ -14,6 +14,7 @@ permissions:
|
|||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
name: vet + fmt + tests
|
name: vet + fmt + tests
|
||||||
|
if: github.event_name != 'schedule'
|
||||||
runs-on: ubuntu-26.04
|
runs-on: ubuntu-26.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v7
|
- uses: actions/checkout@v7
|
||||||
@@ -22,7 +23,6 @@ jobs:
|
|||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: Relevant changes
|
- name: Relevant changes
|
||||||
id: changes
|
id: changes
|
||||||
if: github.event_name != 'schedule'
|
|
||||||
run: |
|
run: |
|
||||||
if [ "$GITHUB_EVENT_NAME" = "pull_request" ]; then
|
if [ "$GITHUB_EVENT_NAME" = "pull_request" ]; then
|
||||||
git fetch --no-tags origin "$GITHUB_BASE_REF"
|
git fetch --no-tags origin "$GITHUB_BASE_REF"
|
||||||
@@ -42,7 +42,6 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
echo "base=$base" >> "$GITHUB_OUTPUT"
|
echo "base=$base" >> "$GITHUB_OUTPUT"
|
||||||
- name: CHANGELOG entry for data changes
|
- name: CHANGELOG entry for data changes
|
||||||
if: github.event_name != 'schedule'
|
|
||||||
run: |
|
run: |
|
||||||
base='${{ steps.changes.outputs.base }}'
|
base='${{ steps.changes.outputs.base }}'
|
||||||
if ! git diff --quiet "$base"...HEAD -- data testdata/shipped_shape.txt && git diff --quiet "$base"...HEAD -- CHANGELOG.md; then
|
if ! git diff --quiet "$base"...HEAD -- data testdata/shipped_shape.txt && git diff --quiet "$base"...HEAD -- CHANGELOG.md; then
|
||||||
@@ -59,11 +58,6 @@ jobs:
|
|||||||
- name: Lowest supported Go
|
- name: Lowest supported Go
|
||||||
if: ${{ !cancelled() && steps.changes.outputs.code == 'true' }}
|
if: ${{ !cancelled() && steps.changes.outputs.code == 'true' }}
|
||||||
run: docker build --build-arg GO_VERSION=1.22.12 --target portable .
|
run: docker build --build-arg GO_VERSION=1.22.12 --target portable .
|
||||||
# Runs on every event, and daily, since a vulnerability is published without a change
|
|
||||||
# here; `--no-cache-filter` keeps a cached pass from hiding one.
|
|
||||||
- name: Known vulnerabilities in this Go release and the module
|
|
||||||
if: ${{ !cancelled() }}
|
|
||||||
run: docker build --no-cache-filter vulnerabilities --target vulnerabilities .
|
|
||||||
- name: Package repositories, signed with throwaway keys
|
- name: Package repositories, signed with throwaway keys
|
||||||
if: ${{ !cancelled() && steps.changes.outputs.packaging == 'true' }}
|
if: ${{ !cancelled() && steps.changes.outputs.packaging == 'true' }}
|
||||||
run: |
|
run: |
|
||||||
@@ -72,9 +66,45 @@ jobs:
|
|||||||
docker build -f release-tooling/package-repos.Dockerfile --target checks \
|
docker build -f release-tooling/package-repos.Dockerfile --target checks \
|
||||||
--secret id=gpg,env=PACKAGES_GPG_KEY --secret id=rsa,env=PACKAGES_RSA_KEY .
|
--secret id=gpg,env=PACKAGES_GPG_KEY --secret id=rsa,env=PACKAGES_RSA_KEY .
|
||||||
|
|
||||||
|
# Not a required check: a vulnerability published in Go, or an outage of vuln.go.dev,
|
||||||
|
# holds the release but no merge.
|
||||||
|
vulnerabilities:
|
||||||
|
name: Known vulnerabilities in this Go release and the module
|
||||||
|
runs-on: ubuntu-26.04
|
||||||
|
timeout-minutes: 10
|
||||||
|
permissions:
|
||||||
|
actions: write
|
||||||
|
contents: write
|
||||||
|
pull-requests: write
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v7
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
|
- run: docker build --no-cache-filter vulnerabilities --target vulnerability-report --output "$RUNNER_TEMP/vulnerabilities" .
|
||||||
|
- name: File each one in todo.md
|
||||||
|
id: file
|
||||||
|
run: python3 release-tooling/file_vulnerabilities.py "$RUNNER_TEMP/vulnerabilities/report.json" todo.md
|
||||||
|
# A pull request the workflow's token opens starts no workflow, so this starts the tests.
|
||||||
|
- name: Propose the filed items
|
||||||
|
if: failure() && steps.file.outcome == 'failure' && github.event_name != 'pull_request'
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ github.token }}
|
||||||
|
run: |
|
||||||
|
if git diff --quiet todo.md || git ls-remote --exit-code --heads origin vulnerabilities; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
git config user.name 'github-actions[bot]'
|
||||||
|
git config user.email '41898282+github-actions[bot]@users.noreply.github.com'
|
||||||
|
git switch -c vulnerabilities
|
||||||
|
git commit -qam "File the known vulnerabilities govulncheck reports"
|
||||||
|
git push -q "https://x-access-token:${GH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" vulnerabilities
|
||||||
|
gh pr create --head vulnerabilities --title "File the known vulnerabilities govulncheck reports" \
|
||||||
|
--body "govulncheck reports known vulnerabilities in the Go release or the module, and no release is cut until they are gone. This files them atop the next release in todo.md; the fix is the bump its item names."
|
||||||
|
gh workflow run test.yml --ref vulnerabilities
|
||||||
|
|
||||||
release:
|
release:
|
||||||
name: Release from CHANGELOG.md
|
name: Release from CHANGELOG.md
|
||||||
needs: test
|
needs: [test, vulnerabilities]
|
||||||
if: github.event_name == 'push'
|
if: github.event_name == 'push'
|
||||||
runs-on: ubuntu-26.04
|
runs-on: ubuntu-26.04
|
||||||
permissions:
|
permissions:
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Rules
|
# Rules
|
||||||
|
|
||||||
- Go runs only through `docker compose run --rm <test|vet|fmt|build|cyclo|generate>`; the merge gate is `docker build .`, CI's changelog check, its known-vulnerabilities check and, for a change the README's Development section lists, its package-repository checks.
|
- Go runs only through `docker compose run --rm <test|vet|fmt|build|cyclo|generate>`; the merge gate is what the README's Development section lists.
|
||||||
- Tests first, in their own commit; the implementation follows in the next. A re-pin of seeded output or of `testdata/shipped_shape.txt` is its own commit.
|
- Tests first, in their own commit; the implementation follows in the next. A re-pin of seeded output or of `testdata/shipped_shape.txt` is its own commit.
|
||||||
- A change under `data/` or to the shape pin adds its `CHANGELOG.md` entry under `Unreleased` in the same PR, and so does a change to a flag, an exit code, an exported name, a fence, a builtin or the lowest Go; what is major is the README's Versioning table.
|
- A change under `data/` or to the shape pin adds its `CHANGELOG.md` entry under `Unreleased` in the same PR, and so does a change to a flag, an exit code, an exported name, a fence, a builtin or the lowest Go; what is major is the README's Versioning table.
|
||||||
- One-line commit messages: no ticket prefix, no repo name, no authorship trailers.
|
- One-line commit messages: no ticket prefix, no repo name, no authorship trailers.
|
||||||
@@ -124,6 +124,7 @@ In [docs/decisions.md](docs/decisions.md):
|
|||||||
- A country with no open address register covering it whole ships its places and postal codes without streets
|
- A country with no open address register covering it whole ships its places and postal codes without streets
|
||||||
- The apt, dnf and apk repositories are static files on GitHub Pages, holding the latest release only
|
- The apt, dnf and apk repositories are static files on GitHub Pages, holding the latest release only
|
||||||
- The image is pushed to GHCR and copied to Docker Hub, whose name the README shows
|
- The image is pushed to GHCR and copied to Docker Hub, whose name the README shows
|
||||||
|
- A known vulnerability in the Go release or the module blocks a release, called or not, and no merge
|
||||||
|
|
||||||
# Scoring run
|
# Scoring run
|
||||||
|
|
||||||
|
|||||||
+4
-1
@@ -14,7 +14,10 @@ RUN go vet ./... && \
|
|||||||
FROM golang:${GO_VERSION} AS vulnerabilities
|
FROM golang:${GO_VERSION} AS vulnerabilities
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY . .
|
COPY . .
|
||||||
RUN go run golang.org/x/vuln/cmd/govulncheck@v1.8.0 -scan module
|
RUN go run golang.org/x/vuln/cmd/govulncheck@v1.8.0 -scan module -format json > /report.json
|
||||||
|
|
||||||
|
FROM scratch AS vulnerability-report
|
||||||
|
COPY --from=vulnerabilities /report.json /
|
||||||
|
|
||||||
FROM python:3.14.8-slim AS release-tooling
|
FROM python:3.14.8-slim AS release-tooling
|
||||||
COPY release-tooling/ /release-tooling/
|
COPY release-tooling/ /release-tooling/
|
||||||
|
|||||||
@@ -1170,7 +1170,7 @@ internal/rows/ a table's rows: the TSV, the options proved over it, the links b
|
|||||||
data/ the shipped modules, each a Go package embedding its categories (JSON, and a TSV per table) and its manifest; and Modules, which lists them
|
data/ the shipped modules, each a Go package embedding its categories (JSON, and a TSV per table) and its manifest; and Modules, which lists them
|
||||||
data-import/ the scripts that rebuild each sourced table (see DATA-LICENSES.md), and the modules they share
|
data-import/ the scripts that rebuild each sourced table (see DATA-LICENSES.md), and the modules they share
|
||||||
docs/ the decision log, the register research behind the shipped data, the survey of other libraries, panels' scores and rulings on how readable the code is, and what each chunk cost an agent to read
|
docs/ the decision log, the register research behind the shipped data, the survey of other libraries, panels' scores and rulings on how readable the code is, and what each chunk cost an agent to read
|
||||||
release-tooling/ the release CI publishes from the changelog heading, and the binaries, packages, image and package repositories built for it
|
release-tooling/ the release CI publishes from the changelog heading, and the binaries, packages, image and package repositories built for it, and the filing of known vulnerabilities
|
||||||
testdata/ the pinned shipped shape (see Versioning)
|
testdata/ the pinned shipped shape (see Versioning)
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -1219,14 +1219,20 @@ check and the release tooling's tests:
|
|||||||
docker build . # latest
|
docker build . # latest
|
||||||
docker build --build-arg GO_VERSION=1.22.12 --target portable . # lowest supported
|
docker build --build-arg GO_VERSION=1.22.12 --target portable . # lowest supported
|
||||||
GO_VERSION=1.22.12 docker compose run --rm test # the same tests, without the image build
|
GO_VERSION=1.22.12 docker compose run --rm test # the same tests, without the image build
|
||||||
docker build --no-cache-filter vulnerabilities --target vulnerabilities . # known vulnerabilities
|
docker build --no-cache-filter vulnerabilities --target vulnerability-report --output /tmp/fejkdata-vulnerabilities .
|
||||||
|
python3 release-tooling/file_vulnerabilities.py /tmp/fejkdata-vulnerabilities/report.json todo.md
|
||||||
```
|
```
|
||||||
|
|
||||||
The last line runs `govulncheck` over the Go release the gate builds with and the module's
|
The last two lines run `govulncheck` over the Go release the gate builds with and the module's
|
||||||
requirements, and fails on any known vulnerability, whether or not fejkdata calls it: the
|
requirements, and fails on any known vulnerability, whether or not fejkdata calls it: the
|
||||||
release binaries carry that Go release, and image scanners flag it. CI runs it on every pull
|
release binaries carry that Go release, and image scanners flag it. CI runs it on every pull
|
||||||
request and push, and daily, and a release waits for it. A failure is fixed by raising
|
request and push, and daily; GitHub pauses the daily run after 60 days with no activity in
|
||||||
`GO_VERSION`, which Renovate opens a pull request for.
|
the repository. It is not part of the gate: a pull request merges while it fails, but no
|
||||||
|
release is cut. Each vulnerability it finds is filed as a `security` item atop the next
|
||||||
|
release in `todo.md`; on `main` and in the daily run CI opens a pull request from the branch
|
||||||
|
`vulnerabilities` with that item, unless the branch exists. The fix is raising
|
||||||
|
`GO_VERSION`, which Renovate opens a pull request for; a failure that names no
|
||||||
|
vulnerability is vuln.go.dev failing to answer.
|
||||||
|
|
||||||
A change to Go code, `release-tooling/`, the `Dockerfile`, `.dockerignore`, the licence
|
A change to Go code, `release-tooling/`, the `Dockerfile`, `.dockerignore`, the licence
|
||||||
files or either workflow also runs the package-repository checks. They build the release
|
files or either workflow also runs the package-repository checks. They build the release
|
||||||
|
|||||||
+16
-1
@@ -988,4 +988,19 @@ change of path. GoReleaser pushes there, and a job of its own copies the image t
|
|||||||
Hub, so a Docker Hub failure holds up no other channel. GHCR also serves CI on shared
|
Hub, so a Docker Hub failure holds up no other channel. GHCR also serves CI on shared
|
||||||
runners, which Docker Hub's per-IP limit on anonymous pulls blocks. Leaving Docker Hub
|
runners, which Docker Hub's per-IP limit on anonymous pulls blocks. Leaving Docker Hub
|
||||||
costs each user an edit of every `docker run` line and pinned script that names the bare
|
costs each user an edit of every `docker run` line and pinned script that names the bare
|
||||||
`larvit/fejkdata`.
|
`larvit/fejkdata`.
|
||||||
|
|
||||||
|
## A known vulnerability in the Go release or the module blocks a release, called or not, and no merge
|
||||||
|
|
||||||
|
2026-10-14, decided by the maintainer after Docker Hub flagged v0.1.0's image. Serves goal
|
||||||
|
1.1. `govulncheck -scan module` fails on any known vulnerability in the Go release the gate
|
||||||
|
builds with or in the module's requirements, even one fejkdata never calls: the release
|
||||||
|
binaries carry that Go release, and image scanners flag it whatever the code reaches. It
|
||||||
|
runs on every pull request and push and daily, as a job the release job needs but branch
|
||||||
|
protection does not require. A vulnerability published in Go, or an outage of vuln.go.dev,
|
||||||
|
so holds the release and leaves unrelated pull requests mergeable. Each vulnerability is
|
||||||
|
filed as a `security` item atop the next release in `todo.md`, by a pull request CI opens,
|
||||||
|
so the plan names it before anyone reads a red run. Where no Go release
|
||||||
|
fixes a vulnerability yet, govulncheck has no ignore list: the maintainer drops the job
|
||||||
|
from the release's `needs` until one does, and records why here. Valid while the binaries
|
||||||
|
are built from the gate's Go release.
|
||||||
|
|||||||
@@ -0,0 +1,121 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""File each module's known vulnerabilities as one security item atop todo.md's next release.
|
||||||
|
|
||||||
|
Usage: file_vulnerabilities.py <govulncheck -format json report> <todo.md>
|
||||||
|
Exits 1 while any vulnerability is known, filed now or before, and 0 on a clean report.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import ast
|
||||||
|
import json
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
ROW = re.compile(r"^\| (\d+) \| ([^|]+?) \| [^|]*\| \*\*", re.M)
|
||||||
|
WEIGHT = re.compile(r"^\| ([\d.]+) \| ([\d.]+) \|$", re.M)
|
||||||
|
SCORES = {"R": 1, "S": 1, "C": 1, "A": 8, "G": 8}
|
||||||
|
GOAL = "1.1"
|
||||||
|
|
||||||
|
|
||||||
|
def messages(report: str):
|
||||||
|
decoder, at = json.JSONDecoder(), 0
|
||||||
|
while at < len(report):
|
||||||
|
if report[at].isspace():
|
||||||
|
at += 1
|
||||||
|
continue
|
||||||
|
message, at = decoder.raw_decode(report, at)
|
||||||
|
yield message
|
||||||
|
|
||||||
|
|
||||||
|
def version_key(version: str):
|
||||||
|
return [int(part) for part in re.findall(r"\d+", version)]
|
||||||
|
|
||||||
|
|
||||||
|
def score(todo: str) -> str:
|
||||||
|
formula = re.search(r"`Score = (.+?)`", todo).group(1)
|
||||||
|
weights = dict(WEIGHT.findall(todo))
|
||||||
|
values = dict(SCORES, W=float(weights[GOAL]))
|
||||||
|
return f"{evaluate(ast.parse(formula, mode='eval').body, values):.1f}"
|
||||||
|
|
||||||
|
|
||||||
|
def evaluate(node, values):
|
||||||
|
match node:
|
||||||
|
case ast.Constant(value=value):
|
||||||
|
return value
|
||||||
|
case ast.Name(id=name):
|
||||||
|
return values[name]
|
||||||
|
case ast.UnaryOp(op=ast.USub(), operand=operand):
|
||||||
|
return -evaluate(operand, values)
|
||||||
|
case ast.BinOp(left=left, op=op, right=right):
|
||||||
|
a, b = evaluate(left, values), evaluate(right, values)
|
||||||
|
return {ast.Add: a + b, ast.Sub: a - b, ast.Mult: a * b, ast.Div: a / b if b else 0}[type(op)]
|
||||||
|
raise SystemExit(f"todo.md's formula holds {ast.dump(node)}, which this script cannot evaluate")
|
||||||
|
|
||||||
|
|
||||||
|
def item(module: str, found_in: str, fixed: str, osvs: list[dict]) -> tuple[str, str]:
|
||||||
|
if module == "stdlib":
|
||||||
|
tagline = f"Raise Go to {fixed.lstrip('v')}, so the release binaries carry none of its known vulnerabilities."
|
||||||
|
where = f"Go {found_in.lstrip('v')}"
|
||||||
|
else:
|
||||||
|
tagline = f"Raise `{module}` to {fixed}, so the module requires none of its known vulnerabilities."
|
||||||
|
where = f"`{module}` {found_in}"
|
||||||
|
lines = []
|
||||||
|
for osv in sorted(osvs, key=lambda o: o["id"]):
|
||||||
|
aliases = f" ({', '.join(osv['aliases'])})" if osv.get("aliases") else ""
|
||||||
|
lines.append(f"- {osv['id']}{aliases}: {osv.get('summary', '')}")
|
||||||
|
return tagline, f"govulncheck found these in {where}:\n\n" + "\n".join(lines) + "\n"
|
||||||
|
|
||||||
|
|
||||||
|
def file_items(report: str, todo: str) -> tuple[str, int]:
|
||||||
|
"""Return todo.md with an item for each module whose vulnerabilities it does not yet name, and how many are known."""
|
||||||
|
osvs, modules = {}, {}
|
||||||
|
for message in messages(report):
|
||||||
|
if "osv" in message:
|
||||||
|
osvs[message["osv"]["id"]] = message["osv"]
|
||||||
|
elif "finding" in message:
|
||||||
|
finding = message["finding"]
|
||||||
|
module, found_in = finding["trace"][0]["module"], finding["trace"][0].get("version", "")
|
||||||
|
entry = modules.setdefault(module, {"found_in": found_in, "fixed": "", "ids": set()})
|
||||||
|
entry["ids"].add(finding["osv"])
|
||||||
|
if version_key(finding.get("fixed_version", "")) > version_key(entry["fixed"]):
|
||||||
|
entry["fixed"] = finding["fixed_version"]
|
||||||
|
known = sum(len(entry["ids"]) for entry in modules.values())
|
||||||
|
for module in sorted(modules, key=lambda m: (m != "stdlib", m)):
|
||||||
|
entry = modules[module]
|
||||||
|
if all(osv in todo for osv in entry["ids"]):
|
||||||
|
continue
|
||||||
|
first = ROW.search(todo)
|
||||||
|
if first is None:
|
||||||
|
raise SystemExit("todo.md has no item to take the next release from")
|
||||||
|
next_id = int(re.search(r"`Next ID = (\d+)`", todo).group(1))
|
||||||
|
tagline, detail = item(module, entry["found_in"], entry["fixed"], [osvs.get(i, {"id": i}) for i in entry["ids"]])
|
||||||
|
scores = " | ".join(str(SCORES[k]) for k in "RSCAG")
|
||||||
|
row = f"| {next_id} | {first.group(2)} | security | **{tagline}** | {scores} | {GOAL} | {score(todo)} |\n"
|
||||||
|
todo = todo[: first.start()] + row + todo[first.start() :]
|
||||||
|
todo = todo.replace(f"`Next ID = {next_id}`", f"`Next ID = {next_id + 1}`", 1)
|
||||||
|
todo = todo.replace("## Details\n\n", f"## Details\n\n### {next_id}. {tagline}\n\n{detail}\n", 1)
|
||||||
|
return todo, known
|
||||||
|
|
||||||
|
|
||||||
|
def main(argv: list[str]) -> int:
|
||||||
|
report_path, todo_path = argv
|
||||||
|
with open(report_path, encoding="utf-8") as f:
|
||||||
|
report = f.read()
|
||||||
|
with open(todo_path, encoding="utf-8") as f:
|
||||||
|
todo = f.read()
|
||||||
|
filed, known = file_items(report, todo)
|
||||||
|
if not known:
|
||||||
|
print("No known vulnerabilities.")
|
||||||
|
return 0
|
||||||
|
if filed == todo:
|
||||||
|
print(f"{known} known vulnerabilities, already planned in todo.md.")
|
||||||
|
return 1
|
||||||
|
with open(todo_path, "w", encoding="utf-8") as f:
|
||||||
|
f.write(filed)
|
||||||
|
next_id = re.compile(r"`Next ID = (\d+)`")
|
||||||
|
ids = range(int(next_id.search(todo).group(1)), int(next_id.search(filed).group(1)))
|
||||||
|
print(f"{known} known vulnerabilities; todo.md item {', '.join(map(str, ids))} plans the fix.")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(main(sys.argv[1:]))
|
||||||
@@ -66,7 +66,7 @@ class FileItems(unittest.TestCase):
|
|||||||
todo, found = file_vulnerabilities.file_items(report(*STDLIB, osvs=OSVS), TODO)
|
todo, found = file_vulnerabilities.file_items(report(*STDLIB, osvs=OSVS), TODO)
|
||||||
self.assertEqual(found, 2)
|
self.assertEqual(found, 2)
|
||||||
self.assertIn("`Next ID = 8`", todo)
|
self.assertIn("`Next ID = 8`", todo)
|
||||||
rows = [line for line in todo.splitlines() if line.startswith("| ") and line[2].isdigit()]
|
rows = [line for line in todo.splitlines() if "| **" in line]
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
rows[0],
|
rows[0],
|
||||||
"| 7 | 0.2.0 | security | **Raise Go to 1.27.10, so the release binaries carry none of"
|
"| 7 | 0.2.0 | security | **Raise Go to 1.27.10, so the release binaries carry none of"
|
||||||
|
|||||||
@@ -23,6 +23,18 @@
|
|||||||
"matchStrings": [
|
"matchStrings": [
|
||||||
"goreleaser/goreleaser-action@\\S+\\s+with:\\s+version: (?<currentValue>\\S+)"
|
"goreleaser/goreleaser-action@\\S+\\s+with:\\s+version: (?<currentValue>\\S+)"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"customType": "regex",
|
||||||
|
"datasourceTemplate": "go",
|
||||||
|
"description": "Go tools the gate runs with go run, by their module path",
|
||||||
|
"managerFilePatterns": [
|
||||||
|
"/^Dockerfile$/",
|
||||||
|
"/^compose\\.yaml$/"
|
||||||
|
],
|
||||||
|
"matchStrings": [
|
||||||
|
"go run (?<depName>[^@\\s]+?)(/cmd/[^@\\s]+)?@(?<currentValue>v\\S+)"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"extends": [
|
"extends": [
|
||||||
|
|||||||
Reference in New Issue
Block a user