safeuploads 0.1.2__tar.gz → 1.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. safeuploads-1.0.1/.forgejo/scripts/check_conventional_commits.py +163 -0
  2. safeuploads-1.0.1/.forgejo/workflows/conventional-commits.yml +44 -0
  3. safeuploads-1.0.1/.forgejo/workflows/docs.yml +51 -0
  4. safeuploads-1.0.1/.forgejo/workflows/fuzz.yml +44 -0
  5. safeuploads-1.0.1/.forgejo/workflows/lint-and-test.yml +86 -0
  6. safeuploads-1.0.1/.forgejo/workflows/publish.yml +63 -0
  7. safeuploads-1.0.1/.forgejo/workflows/renovate.yml +37 -0
  8. safeuploads-1.0.1/.github/agents/se-gitops-ci-specialist.agent.md +244 -0
  9. safeuploads-1.0.1/.github/agents/se-security-reviewer.agent.md +161 -0
  10. safeuploads-1.0.1/.github/agents/test-implementor.agent.md +168 -0
  11. safeuploads-1.0.1/.github/agents/test-reviewer.agent.md +113 -0
  12. safeuploads-1.0.1/.github/copilot-instructions.md +93 -0
  13. safeuploads-1.0.1/.github/instructions/agents.instructions.md +991 -0
  14. safeuploads-1.0.1/.github/instructions/github-actions-ci-cd-best-practices.instructions.md +607 -0
  15. safeuploads-1.0.1/.github/instructions/instructions.instructions.md +256 -0
  16. safeuploads-1.0.1/.github/instructions/prompt.instructions.md +88 -0
  17. safeuploads-1.0.1/.github/instructions/python.instructions.md +140 -0
  18. safeuploads-1.0.1/.github/instructions/security-and-owasp.instructions.md +51 -0
  19. safeuploads-1.0.1/.github/workflows/fuzz.yml +51 -0
  20. safeuploads-1.0.1/.github/workflows/lint&test.yml +96 -0
  21. safeuploads-1.0.1/.github/workflows/publish.yml +67 -0
  22. safeuploads-1.0.1/.gitignore +23 -0
  23. safeuploads-1.0.1/CODE_OF_CONDUCT.md +128 -0
  24. safeuploads-1.0.1/CONTRIBUTING.md +82 -0
  25. safeuploads-1.0.1/PKG-INFO +149 -0
  26. safeuploads-1.0.1/README.md +135 -0
  27. safeuploads-1.0.1/SECURITY.md +17 -0
  28. safeuploads-1.0.1/docs/api.md +6 -0
  29. safeuploads-1.0.1/docs/index.md +143 -0
  30. safeuploads-1.0.1/docs/rate-limiting.md +285 -0
  31. safeuploads-1.0.1/docs/security/architecture.md +370 -0
  32. safeuploads-1.0.1/docs/security/integration-checklist.md +143 -0
  33. safeuploads-1.0.1/docs/security/threat-model.md +315 -0
  34. safeuploads-1.0.1/examples/README.md +279 -0
  35. safeuploads-1.0.1/examples/fastapi_example.py +342 -0
  36. safeuploads-1.0.1/mkdocs.yml +34 -0
  37. safeuploads-1.0.1/pyproject.toml +117 -0
  38. safeuploads-1.0.1/renovate.json +35 -0
  39. {safeuploads-0.1.2 → safeuploads-1.0.1}/safeuploads/__init__.py +58 -24
  40. safeuploads-1.0.1/safeuploads/audit.py +296 -0
  41. {safeuploads-0.1.2 → safeuploads-1.0.1}/safeuploads/config.py +332 -115
  42. {safeuploads-0.1.2 → safeuploads-1.0.1}/safeuploads/enums.py +73 -1
  43. {safeuploads-0.1.2 → safeuploads-1.0.1}/safeuploads/exceptions.py +56 -5
  44. safeuploads-1.0.1/safeuploads/file_validator.py +1028 -0
  45. {safeuploads-0.1.2 → safeuploads-1.0.1}/safeuploads/inspectors/__init__.py +7 -1
  46. safeuploads-1.0.1/safeuploads/inspectors/content_inspector.py +237 -0
  47. safeuploads-1.0.1/safeuploads/inspectors/gzip_inspector.py +189 -0
  48. safeuploads-1.0.1/safeuploads/inspectors/zip_inspector.py +670 -0
  49. safeuploads-1.0.1/safeuploads/protocols.py +101 -0
  50. safeuploads-1.0.1/safeuploads/utils.py +176 -0
  51. {safeuploads-0.1.2 → safeuploads-1.0.1}/safeuploads/validators/__init__.py +4 -2
  52. {safeuploads-0.1.2 → safeuploads-1.0.1}/safeuploads/validators/base.py +1 -4
  53. safeuploads-1.0.1/safeuploads/validators/compression_validator.py +433 -0
  54. {safeuploads-0.1.2 → safeuploads-1.0.1}/safeuploads/validators/extension_validator.py +24 -8
  55. {safeuploads-0.1.2 → safeuploads-1.0.1}/safeuploads/validators/unicode_validator.py +38 -15
  56. {safeuploads-0.1.2 → safeuploads-1.0.1}/safeuploads/validators/windows_validator.py +17 -6
  57. safeuploads-1.0.1/safeuploads/validators/xml_validator.py +95 -0
  58. safeuploads-1.0.1/tests/__init__.py +1 -0
  59. safeuploads-1.0.1/tests/conftest.py +188 -0
  60. safeuploads-1.0.1/tests/fuzz/__init__.py +1 -0
  61. safeuploads-1.0.1/tests/fuzz/test_fuzz_config.py +94 -0
  62. safeuploads-1.0.1/tests/fuzz/test_fuzz_filenames.py +108 -0
  63. safeuploads-1.0.1/tests/fuzz/test_fuzz_images.py +115 -0
  64. safeuploads-1.0.1/tests/fuzz/test_fuzz_zip.py +116 -0
  65. safeuploads-1.0.1/tests/inspectors/__init__.py +1 -0
  66. safeuploads-1.0.1/tests/inspectors/test_content_inspector.py +204 -0
  67. safeuploads-1.0.1/tests/inspectors/test_gzip_inspector.py +255 -0
  68. safeuploads-1.0.1/tests/inspectors/test_zip_inspector.py +1191 -0
  69. safeuploads-1.0.1/tests/test_audit.py +472 -0
  70. safeuploads-1.0.1/tests/test_config.py +321 -0
  71. safeuploads-1.0.1/tests/test_config_validation.py +899 -0
  72. safeuploads-1.0.1/tests/test_enums.py +474 -0
  73. safeuploads-1.0.1/tests/test_exceptions.py +522 -0
  74. safeuploads-1.0.1/tests/test_file_validator.py +1291 -0
  75. safeuploads-1.0.1/tests/test_performance.py +552 -0
  76. safeuploads-1.0.1/tests/test_utils.py +214 -0
  77. safeuploads-1.0.1/tests/test_validate_activity_file.py +303 -0
  78. safeuploads-1.0.1/tests/test_validate_gzip_file.py +238 -0
  79. safeuploads-1.0.1/tests/validators/__init__.py +1 -0
  80. safeuploads-1.0.1/tests/validators/test_compression_validator.py +773 -0
  81. safeuploads-1.0.1/tests/validators/test_extension_validator.py +207 -0
  82. safeuploads-1.0.1/tests/validators/test_unicode_validator.py +209 -0
  83. safeuploads-1.0.1/tests/validators/test_windows_validator.py +225 -0
  84. safeuploads-1.0.1/tests/validators/test_xml_validator.py +175 -0
  85. safeuploads-1.0.1/uv.lock +422 -0
  86. safeuploads-0.1.2/PKG-INFO +0 -170
  87. safeuploads-0.1.2/README.md +0 -147
  88. safeuploads-0.1.2/pyproject.toml +0 -65
  89. safeuploads-0.1.2/safeuploads/file_validator.py +0 -525
  90. safeuploads-0.1.2/safeuploads/inspectors/zip_inspector.py +0 -419
  91. safeuploads-0.1.2/safeuploads/protocols.py +0 -51
  92. safeuploads-0.1.2/safeuploads/validators/compression_validator.py +0 -286
  93. {safeuploads-0.1.2 → safeuploads-1.0.1}/LICENSE.md +0 -0
@@ -0,0 +1,163 @@
1
+ #!/usr/bin/env python3
2
+ """Validate that messages follow the Conventional Commits 1.0.0 specification.
3
+
4
+ Reads one or more messages (either from CLI arguments or, when ``--stdin`` is
5
+ passed, one message per line from standard input) and exits non-zero if any of
6
+ them is invalid.
7
+
8
+ Spec reference: https://www.conventionalcommits.org/en/v1.0.0/
9
+
10
+ Usage::
11
+
12
+ check_conventional_commits.py "feat(api): add endpoint"
13
+ git log --format=%s base..head | check_conventional_commits.py --stdin
14
+
15
+ Designed to run with the Python interpreter already available on the Forgejo
16
+ runner image. Uses only the standard library so there is no third-party
17
+ supply-chain surface.
18
+ """
19
+
20
+ from __future__ import annotations
21
+
22
+ import argparse
23
+ import re
24
+ import sys
25
+ from collections.abc import Iterable
26
+
27
+ # Allowed types. This whitelist is a *project policy* layered on top of the
28
+ # Conventional Commits 1.0.0 spec (the spec recommends but does not mandate a
29
+ # fixed set of types). Keep this list in sync with the project's commit
30
+ # conventions documented in ``.github/copilot-instructions.md``.
31
+ #
32
+ # Per the spec, types are matched case-insensitively.
33
+ ALLOWED_TYPES: tuple[str, ...] = (
34
+ "build",
35
+ "chore",
36
+ "ci",
37
+ "docs",
38
+ "feat",
39
+ "fix",
40
+ "perf",
41
+ "refactor",
42
+ "revert",
43
+ "style",
44
+ "test",
45
+ )
46
+
47
+ # Subject pattern: ``type(scope)!: description``. Scope and ``!`` are optional.
48
+ # Per CC 1.0.0:
49
+ # - the type is a noun (matched case-insensitively against ALLOWED_TYPES);
50
+ # - the scope is any noun describing a section of the codebase, enclosed in
51
+ # parentheses, so we accept any non-empty string that is not a closing
52
+ # parenthesis;
53
+ # - the description is free-form text.
54
+ _HEADER_RE = re.compile(
55
+ r"""
56
+ ^
57
+ (?P<type>[A-Za-z]+)
58
+ (?:\((?P<scope>[^)]+)\))?
59
+ (?P<breaking>!)?
60
+ :\
61
+ (?P<description>.+?)
62
+ \s*$
63
+ """,
64
+ re.VERBOSE,
65
+ )
66
+
67
+
68
+ def _validate_message(message: str) -> list[str]:
69
+ """Return a list of validation errors for ``message`` (empty if valid)."""
70
+ errors: list[str] = []
71
+
72
+ # Conventional Commits only constrains the first line (the header).
73
+ header = message.splitlines()[0] if message else ""
74
+
75
+ if not header.strip():
76
+ return ["message is empty"]
77
+
78
+ match = _HEADER_RE.match(header)
79
+ if match is None:
80
+ errors.append(
81
+ "header does not match '<type>(<scope>)!: <description>' "
82
+ "(see https://www.conventionalcommits.org/en/v1.0.0/)"
83
+ )
84
+ return errors
85
+
86
+ commit_type = match.group("type")
87
+
88
+ # Project policy: restrict to a known set of types. Types are matched
89
+ # case-insensitively per the Conventional Commits spec.
90
+ if commit_type.lower() not in ALLOWED_TYPES:
91
+ errors.append(
92
+ f"type '{commit_type}' is not allowed; "
93
+ f"use one of: {', '.join(ALLOWED_TYPES)}"
94
+ )
95
+
96
+ return errors
97
+
98
+
99
+ def _safe_log_value(value: str) -> str:
100
+ """Return ``value`` escaped for safe CI log output."""
101
+ return value.encode("unicode_escape").decode("ascii")
102
+
103
+
104
+ def _iter_messages(args: argparse.Namespace) -> Iterable[str]:
105
+ if args.stdin:
106
+ for line in sys.stdin:
107
+ stripped = line.rstrip("\n")
108
+ if stripped:
109
+ yield stripped
110
+ else:
111
+ yield from args.messages
112
+
113
+
114
+ def main(argv: list[str] | None = None) -> int:
115
+ parser = argparse.ArgumentParser(
116
+ description="Validate Conventional Commits headers.",
117
+ )
118
+ parser.add_argument(
119
+ "messages",
120
+ nargs="*",
121
+ help="One or more commit messages (or PR titles) to validate.",
122
+ )
123
+ parser.add_argument(
124
+ "--stdin",
125
+ action="store_true",
126
+ help="Read messages from standard input, one per line.",
127
+ )
128
+ args = parser.parse_args(argv)
129
+
130
+ if not args.stdin and not args.messages:
131
+ parser.error("provide at least one message or use --stdin")
132
+
133
+ failures = 0
134
+ checked = 0
135
+ for message in _iter_messages(args):
136
+ checked += 1
137
+ errors = _validate_message(message)
138
+ safe_message = _safe_log_value(message)
139
+ if errors:
140
+ failures += 1
141
+ print(f"INVALID: {safe_message}", file=sys.stderr)
142
+ for err in errors:
143
+ print(f" - {err}", file=sys.stderr)
144
+ else:
145
+ print(f"OK: {safe_message}")
146
+
147
+ if checked == 0:
148
+ print("No messages to validate.", file=sys.stderr)
149
+ return 1
150
+
151
+ if failures:
152
+ print(
153
+ f"\n{failures} of {checked} message(s) failed Conventional Commits "
154
+ "validation.",
155
+ file=sys.stderr,
156
+ )
157
+ return 1
158
+
159
+ return 0
160
+
161
+
162
+ if __name__ == "__main__":
163
+ sys.exit(main())
@@ -0,0 +1,44 @@
1
+ name: Conventional Commits
2
+
3
+ on:
4
+ pull_request:
5
+ types: [opened, edited, synchronize, reopened]
6
+
7
+ permissions:
8
+ contents: read
9
+ pull-requests: read
10
+
11
+ concurrency:
12
+ group: ${{ forgejo.workflow }}-${{ forgejo.event.pull_request.number }}
13
+ cancel-in-progress: true
14
+
15
+ jobs:
16
+ validate:
17
+ runs-on: codeberg-small
18
+
19
+ steps:
20
+ - name: Checkout code
21
+ uses: https://data.forgejo.org/actions/checkout@v6
22
+ with:
23
+ fetch-depth: 0
24
+
25
+ - name: Validate PR title
26
+ # The PR title is passed through an environment variable to prevent
27
+ # shell injection via crafted titles (see security-and-owasp guidelines).
28
+ env:
29
+ PR_TITLE: ${{ forgejo.event.pull_request.title }}
30
+ run: |
31
+ python3 .forgejo/scripts/check_conventional_commits.py "$PR_TITLE"
32
+
33
+ - name: Validate commits in PR
34
+ # Validates every commit subject between the PR base and head. Use the
35
+ # base/head SHAs from the event payload so we don't depend on the local
36
+ # checkout ref layout.
37
+ env:
38
+ BASE_SHA: ${{ forgejo.event.pull_request.base.sha }}
39
+ HEAD_SHA: ${{ forgejo.event.pull_request.head.sha }}
40
+ run: |
41
+ set -euo pipefail
42
+ git fetch --no-tags origin "$BASE_SHA" "$HEAD_SHA"
43
+ git log --format=%s "$BASE_SHA".."$HEAD_SHA" \
44
+ | python3 .forgejo/scripts/check_conventional_commits.py --stdin
@@ -0,0 +1,51 @@
1
+ name: Deploy documentation
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ push:
6
+ branches:
7
+ - main
8
+ - master
9
+ paths:
10
+ - 'docs/**'
11
+ - 'mkdocs.yml'
12
+ - 'safeuploads/**/*.py'
13
+ - '.forgejo/workflows/docs.yml'
14
+
15
+ permissions:
16
+ contents: write
17
+
18
+ concurrency:
19
+ group: ${{ forgejo.workflow }}-${{ forgejo.ref }}
20
+ cancel-in-progress: true
21
+
22
+ jobs:
23
+
24
+ deploy:
25
+
26
+ runs-on: codeberg-small
27
+
28
+ steps:
29
+ - name: Checkout code
30
+ uses: https://data.forgejo.org/actions/checkout@v4
31
+ with:
32
+ fetch-depth: 0
33
+
34
+ - name: Set up Python
35
+ uses: https://data.forgejo.org/actions/setup-python@v5
36
+ with:
37
+ python-version: '3.13'
38
+ cache: pip
39
+
40
+ - name: Install documentation dependencies
41
+ run: pip install mkdocs-material mkdocstrings[python]
42
+
43
+ - name: Build documentation
44
+ run: mkdocs build --site-dir site
45
+
46
+ - name: Deploy documentation to Codeberg Pages
47
+ uses: https://codeberg.org/git-pages/action@v2
48
+ with:
49
+ site: https://${{ forge.repository_owner }}.codeberg.page/${{ forge.event.repository.name }}/
50
+ token: ${{ forge.token }}
51
+ source: site/
@@ -0,0 +1,44 @@
1
+ name: Scheduled Fuzz
2
+
3
+ on:
4
+ schedule:
5
+ # Every Sunday at 03:00 UTC
6
+ - cron: "0 3 * * 0"
7
+ workflow_dispatch:
8
+
9
+ # Cancel in-progress runs for the same branch to avoid wasted
10
+ # runner minutes.
11
+ concurrency:
12
+ group: ${{ forge.workflow }}-${{ forge.ref }}
13
+ cancel-in-progress: true
14
+
15
+ jobs:
16
+ fuzz:
17
+ name: Fuzz
18
+ runs-on: codeberg-medium-lazy
19
+
20
+ steps:
21
+ - name: Checkout repository
22
+ uses: https://data.forgejo.org/actions/checkout@v4
23
+
24
+ - name: Install system dependencies
25
+ run: sudo apt-get update && sudo apt-get install -y libmagic1
26
+
27
+ - name: Set up Python 3.13
28
+ uses: https://data.forgejo.org/actions/setup-python@v5
29
+ with:
30
+ python-version: "3.13"
31
+
32
+ - name: Install uv
33
+ run: pip install uv
34
+
35
+ - name: Install dependencies
36
+ run: uv sync --frozen --dev
37
+
38
+ - name: Run fuzz tests
39
+ run: >
40
+ uv run pytest -m fuzz
41
+ --hypothesis-seed=0
42
+ -x
43
+ --tb=short
44
+ -q
@@ -0,0 +1,86 @@
1
+ name: Lint & Test
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ # Cancel in-progress runs for the same branch/PR to avoid wasted
10
+ # runner minutes and race conditions on shared resources.
11
+ concurrency:
12
+ group: ${{ forge.workflow }}-${{ forge.ref }}
13
+ cancel-in-progress: true
14
+
15
+ jobs:
16
+ # ----------------------------------------------------------------
17
+ # Lint
18
+ # Runs ruff on all Python sources. Fails fast so test job is only
19
+ # triggered when the code is clean.
20
+ # ----------------------------------------------------------------
21
+ lint:
22
+ name: Lint
23
+ runs-on: codeberg-tiny
24
+
25
+ steps:
26
+ - name: Checkout repository
27
+ uses: https://data.forgejo.org/actions/checkout@v4
28
+
29
+ - name: Set up Python 3.13
30
+ uses: https://data.forgejo.org/actions/setup-python@v5
31
+ with:
32
+ python-version: "3.13"
33
+
34
+ - name: Install uv
35
+ run: pip install uv
36
+
37
+ - name: Install dependencies
38
+ run: uv sync --frozen --dev
39
+
40
+ - name: Lint with ruff
41
+ run: uv run ruff check safeuploads tests examples
42
+
43
+ - name: Check formatting with ruff
44
+ run: uv run ruff format --check safeuploads tests examples
45
+
46
+ # ----------------------------------------------------------------
47
+ # Test
48
+ # Runs the full pytest suite with coverage. Only runs after lint
49
+ # passes so we don't waste runner minutes on broken code.
50
+ # ----------------------------------------------------------------
51
+ test:
52
+ name: Test
53
+ runs-on: codeberg-medium
54
+ needs: lint
55
+
56
+ steps:
57
+ - name: Checkout repository
58
+ uses: https://data.forgejo.org/actions/checkout@v4
59
+
60
+ - name: Install system dependencies
61
+ run: sudo apt-get update && sudo apt-get install -y libmagic1
62
+
63
+ - name: Set up Python 3.13
64
+ uses: https://data.forgejo.org/actions/setup-python@v5
65
+ with:
66
+ python-version: "3.13"
67
+
68
+ - name: Install uv
69
+ run: pip install uv
70
+
71
+ - name: Install dependencies
72
+ run: uv sync --frozen --dev
73
+
74
+ - name: Audit Python dependencies
75
+ run: uvx pip-audit --require-hashes --disable-pip -r <(uv export --frozen --no-header --no-emit-project --no-dev)
76
+
77
+ - name: Run tests with coverage
78
+ run: uv run pytest --cov-fail-under=90
79
+
80
+ - name: Upload coverage report
81
+ uses: https://data.forgejo.org/forgejo/upload-artifact@v4
82
+ if: always()
83
+ with:
84
+ name: safeuploads-coverage
85
+ path: .coverage
86
+ retention-days: 7
@@ -0,0 +1,63 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ inputs:
6
+ confirm:
7
+ description: "Type the package version to confirm publish"
8
+ required: true
9
+ type: string
10
+
11
+ # Only one publish at a time.
12
+ concurrency:
13
+ group: publish
14
+ cancel-in-progress: false
15
+
16
+ jobs:
17
+ publish:
18
+ name: Build & Publish
19
+ runs-on: codeberg-medium
20
+
21
+ steps:
22
+ - name: Checkout repository
23
+ uses: https://data.forgejo.org/actions/checkout@v4
24
+
25
+ - name: Verify version matches input
26
+ run: |
27
+ PKG_VERSION=$(python3 -c "
28
+ import tomllib, pathlib
29
+ data = tomllib.loads(
30
+ pathlib.Path('pyproject.toml').read_text()
31
+ )
32
+ print(data['project']['version'])
33
+ ")
34
+ if [ "$PKG_VERSION" != "${{ inputs.confirm }}" ]; then
35
+ echo "::error::Input version ${{ inputs.confirm }} does not match pyproject.toml version $PKG_VERSION"
36
+ exit 1
37
+ fi
38
+ echo "Publishing version $PKG_VERSION"
39
+
40
+ - name: Install system dependencies
41
+ run: sudo apt-get update && sudo apt-get install -y libmagic1
42
+
43
+ - name: Set up Python 3.13
44
+ uses: https://data.forgejo.org/actions/setup-python@v5
45
+ with:
46
+ python-version: "3.13"
47
+
48
+ - name: Install uv
49
+ run: pip install uv
50
+
51
+ - name: Install dependencies
52
+ run: uv sync --frozen --dev
53
+
54
+ - name: Run tests before publish
55
+ run: uv run pytest --cov-fail-under=90
56
+
57
+ - name: Build package
58
+ run: uv build
59
+
60
+ - name: Publish to PyPI
61
+ env:
62
+ UV_PUBLISH_TOKEN: ${{ secrets.PYPI_API_TOKEN }}
63
+ run: uv publish
@@ -0,0 +1,37 @@
1
+ name: Dependency updates
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ schedule:
6
+ - cron: '0 4 * * 0'
7
+
8
+ permissions:
9
+ contents: write
10
+ pull-requests: write
11
+ issues: write
12
+
13
+ concurrency:
14
+ group: ${{ forgejo.workflow }}-${{ forgejo.ref }}
15
+ cancel-in-progress: false
16
+
17
+ jobs:
18
+
19
+ renovate:
20
+
21
+ runs-on: codeberg-small
22
+
23
+ steps:
24
+ - name: Checkout code
25
+ uses: https://data.forgejo.org/actions/checkout@v4
26
+ with:
27
+ fetch-depth: 1
28
+
29
+ - name: Run Renovate
30
+ uses: docker://ghcr.io/renovatebot/renovate:latest
31
+ env:
32
+ LOG_LEVEL: info
33
+ RENOVATE_CONFIG_FILE: renovate.json
34
+ RENOVATE_ENDPOINT: https://codeberg.org/api/v1/
35
+ RENOVATE_PLATFORM: gitea
36
+ RENOVATE_REPOSITORIES: ${{ forgejo.repository }}
37
+ RENOVATE_TOKEN: ${{ secrets.RENOVATE_TOKEN }}