qurl-python 0.2.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.
- qurl_python-0.2.1/.github/ISSUE_TEMPLATE/bug_report.yml +90 -0
- qurl_python-0.2.1/.github/ISSUE_TEMPLATE/config.yml +11 -0
- qurl_python-0.2.1/.github/ISSUE_TEMPLATE/feature_request.yml +48 -0
- qurl_python-0.2.1/.github/PULL_REQUEST_TEMPLATE.md +11 -0
- qurl_python-0.2.1/.github/dependabot.yml +10 -0
- qurl_python-0.2.1/.github/workflows/ci.yml +72 -0
- qurl_python-0.2.1/.github/workflows/claude-code-review.yml +43 -0
- qurl_python-0.2.1/.github/workflows/claude.yml +39 -0
- qurl_python-0.2.1/.github/workflows/codeql.yml +45 -0
- qurl_python-0.2.1/.github/workflows/dependency-age-check-actions.yml +54 -0
- qurl_python-0.2.1/.github/workflows/dependency-age-check-pip.yml +53 -0
- qurl_python-0.2.1/.github/workflows/dependency-review.yml +19 -0
- qurl_python-0.2.1/.github/workflows/issue-priority.yml +53 -0
- qurl_python-0.2.1/.github/workflows/pr-title.yml +40 -0
- qurl_python-0.2.1/.github/workflows/release-please.yml +73 -0
- qurl_python-0.2.1/.github/workflows/secrets-scan.yml +21 -0
- qurl_python-0.2.1/.github/workflows/validate-issue-templates.yml +38 -0
- qurl_python-0.2.1/.gitignore +9 -0
- qurl_python-0.2.1/.release-please-manifest.json +1 -0
- qurl_python-0.2.1/CHANGELOG.md +42 -0
- qurl_python-0.2.1/CLAUDE.md +33 -0
- qurl_python-0.2.1/CONTRIBUTING.md +45 -0
- qurl_python-0.2.1/LICENSE +21 -0
- qurl_python-0.2.1/PKG-INFO +282 -0
- qurl_python-0.2.1/README.md +249 -0
- qurl_python-0.2.1/SECURITY.md +17 -0
- qurl_python-0.2.1/pyproject.toml +68 -0
- qurl_python-0.2.1/release-please-config.json +12 -0
- qurl_python-0.2.1/src/layerv_qurl/__init__.py +161 -0
- qurl_python-0.2.1/src/layerv_qurl/_utils.py +1414 -0
- qurl_python-0.2.1/src/layerv_qurl/async_client.py +1512 -0
- qurl_python-0.2.1/src/layerv_qurl/client.py +1533 -0
- qurl_python-0.2.1/src/layerv_qurl/errors.py +152 -0
- qurl_python-0.2.1/src/layerv_qurl/langchain.py +159 -0
- qurl_python-0.2.1/src/layerv_qurl/py.typed +0 -0
- qurl_python-0.2.1/src/layerv_qurl/types.py +690 -0
- qurl_python-0.2.1/tests/__init__.py +0 -0
- qurl_python-0.2.1/tests/test_client.py +5439 -0
- qurl_python-0.2.1/tests/test_langchain.py +187 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
name: Bug Report
|
|
2
|
+
description: Report a bug to help us improve. Do NOT use this for security vulnerabilities — see SECURITY.md.
|
|
3
|
+
title: "[BUG] "
|
|
4
|
+
labels: ["bug"]
|
|
5
|
+
body:
|
|
6
|
+
- type: markdown
|
|
7
|
+
attributes:
|
|
8
|
+
value: |
|
|
9
|
+
> **Security vulnerabilities: stop.** Report privately via [GitHub Security Advisory](https://github.com/layervai/qurl-python/security/advisories/new) or email `security@layerv.ai`. Do NOT open a public issue. See `SECURITY.md`.
|
|
10
|
+
- type: dropdown
|
|
11
|
+
id: priority
|
|
12
|
+
attributes:
|
|
13
|
+
label: Priority
|
|
14
|
+
description: |
|
|
15
|
+
- **critical** — production outage potential, data loss risk, live-customer breakage
|
|
16
|
+
- **high** — significant user impact, blocker for other work, correctness bug in shipped feature
|
|
17
|
+
- **medium** — standard bug, non-urgent
|
|
18
|
+
- **low** — polish, minor fix, tech debt
|
|
19
|
+
options:
|
|
20
|
+
- critical
|
|
21
|
+
- high
|
|
22
|
+
- medium
|
|
23
|
+
- low
|
|
24
|
+
validations:
|
|
25
|
+
required: true
|
|
26
|
+
- type: textarea
|
|
27
|
+
id: description
|
|
28
|
+
attributes:
|
|
29
|
+
label: Description
|
|
30
|
+
description: A clear description of the bug.
|
|
31
|
+
validations:
|
|
32
|
+
required: true
|
|
33
|
+
- type: textarea
|
|
34
|
+
id: reproduction
|
|
35
|
+
attributes:
|
|
36
|
+
label: Steps to Reproduce
|
|
37
|
+
description: Include a minimal code snippet if you can.
|
|
38
|
+
placeholder: |
|
|
39
|
+
1.
|
|
40
|
+
2.
|
|
41
|
+
3.
|
|
42
|
+
validations:
|
|
43
|
+
required: true
|
|
44
|
+
- type: textarea
|
|
45
|
+
id: expected
|
|
46
|
+
attributes:
|
|
47
|
+
label: Expected Behavior
|
|
48
|
+
validations:
|
|
49
|
+
required: true
|
|
50
|
+
- type: textarea
|
|
51
|
+
id: actual
|
|
52
|
+
attributes:
|
|
53
|
+
label: Actual Behavior
|
|
54
|
+
validations:
|
|
55
|
+
required: true
|
|
56
|
+
- type: input
|
|
57
|
+
id: version
|
|
58
|
+
attributes:
|
|
59
|
+
label: Package version
|
|
60
|
+
description: The installed `qurl-python` version. Run `pip show qurl-python` or check `requirements.txt` / `pyproject.toml`.
|
|
61
|
+
placeholder: e.g. 0.3.x
|
|
62
|
+
validations:
|
|
63
|
+
required: true
|
|
64
|
+
- type: input
|
|
65
|
+
id: python_version
|
|
66
|
+
attributes:
|
|
67
|
+
label: Python version
|
|
68
|
+
description: Runtime version where the bug occurred.
|
|
69
|
+
placeholder: e.g. 3.12.x (paste from `python --version`)
|
|
70
|
+
validations:
|
|
71
|
+
required: true
|
|
72
|
+
- type: input
|
|
73
|
+
id: os
|
|
74
|
+
attributes:
|
|
75
|
+
label: OS
|
|
76
|
+
placeholder: e.g. macOS 15, Ubuntu 24.04, Windows 11
|
|
77
|
+
- type: textarea
|
|
78
|
+
id: logs
|
|
79
|
+
attributes:
|
|
80
|
+
label: Logs / Error output
|
|
81
|
+
description: |
|
|
82
|
+
Paste the exception traceback and relevant surrounding context.
|
|
83
|
+
**Redact before pasting:** bearer tokens, API keys (`lv_live_…`), and customer identifiers.
|
|
84
|
+
# No `render:` — `render: shell` shell-highlights content, which
|
|
85
|
+
# miscolors Python tracebacks and JSON-structured log lines.
|
|
86
|
+
- type: textarea
|
|
87
|
+
id: context
|
|
88
|
+
attributes:
|
|
89
|
+
label: Additional Context
|
|
90
|
+
description: Screenshots, related issues, prior discussion, anything else worth knowing.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# `blank_issues_enabled: false` forces reporters through the bug-report
|
|
2
|
+
# or feature-request forms, which carry a required Priority dropdown.
|
|
3
|
+
# GitHub blocks blank-issue creation at the UI before any workflow
|
|
4
|
+
# runs — the enforcement fail path is for issues that DO materialize
|
|
5
|
+
# (e.g. API-filed) without a priority label. Better to prevent the
|
|
6
|
+
# blank-issue state than to rely on surfacing it after creation.
|
|
7
|
+
blank_issues_enabled: false
|
|
8
|
+
contact_links:
|
|
9
|
+
- name: Report a security vulnerability
|
|
10
|
+
url: https://github.com/layervai/qurl-python/security/advisories/new
|
|
11
|
+
about: Do NOT open a public bug report for security issues. Private disclosure via GitHub Security Advisory. See SECURITY.md.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
name: Feature Request
|
|
2
|
+
description: Suggest an idea for this SDK
|
|
3
|
+
title: "[FEATURE] "
|
|
4
|
+
labels: ["enhancement"]
|
|
5
|
+
body:
|
|
6
|
+
- type: dropdown
|
|
7
|
+
id: priority
|
|
8
|
+
attributes:
|
|
9
|
+
label: Priority
|
|
10
|
+
# Rubric wording is feature-shaped (describes ABSENCE, not
|
|
11
|
+
# failure) — distinct from bug_report.yml where critical
|
|
12
|
+
# describes harm from an existing defect. Keeping the four
|
|
13
|
+
# level names in lockstep across both forms; only the
|
|
14
|
+
# descriptions differ.
|
|
15
|
+
description: |
|
|
16
|
+
- **critical** — unblocks a committed delivery, closes a compliance/security gap, required for a live customer
|
|
17
|
+
- **high** — significant user value, blocks meaningful follow-on work
|
|
18
|
+
- **medium** — standard improvement, non-urgent
|
|
19
|
+
- **low** — polish, speculative, future
|
|
20
|
+
options:
|
|
21
|
+
- critical
|
|
22
|
+
- high
|
|
23
|
+
- medium
|
|
24
|
+
- low
|
|
25
|
+
validations:
|
|
26
|
+
required: true
|
|
27
|
+
- type: textarea
|
|
28
|
+
id: problem
|
|
29
|
+
attributes:
|
|
30
|
+
label: Problem Statement
|
|
31
|
+
description: What problem would this feature solve?
|
|
32
|
+
validations:
|
|
33
|
+
required: true
|
|
34
|
+
- type: textarea
|
|
35
|
+
id: solution
|
|
36
|
+
attributes:
|
|
37
|
+
label: Proposed Solution
|
|
38
|
+
validations:
|
|
39
|
+
required: true
|
|
40
|
+
- type: textarea
|
|
41
|
+
id: alternatives
|
|
42
|
+
attributes:
|
|
43
|
+
label: Alternatives Considered
|
|
44
|
+
- type: textarea
|
|
45
|
+
id: context
|
|
46
|
+
attributes:
|
|
47
|
+
label: Additional Context
|
|
48
|
+
description: Mockups, related issues, links to prior discussion.
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
strategy:
|
|
13
|
+
# Don't cancel sibling matrix legs if one fails — we want full
|
|
14
|
+
# visibility into which Python versions broke.
|
|
15
|
+
fail-fast: false
|
|
16
|
+
matrix:
|
|
17
|
+
python-version: ["3.10", "3.12", "3.13"]
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
|
20
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
21
|
+
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
|
22
|
+
with:
|
|
23
|
+
python-version: ${{ matrix.python-version }}
|
|
24
|
+
- name: Install dependencies
|
|
25
|
+
run: pip install -e ".[dev,langchain]"
|
|
26
|
+
- name: Lint
|
|
27
|
+
run: ruff check
|
|
28
|
+
- name: Test
|
|
29
|
+
run: pytest tests/ -v
|
|
30
|
+
|
|
31
|
+
# ============================================================================
|
|
32
|
+
# TYPE CHECK - Dedicated mypy job
|
|
33
|
+
# ============================================================================
|
|
34
|
+
# Runs in its own job so the gate can't silently vanish if the test
|
|
35
|
+
# matrix is restructured. Pins to the minimum supported Python version
|
|
36
|
+
# (matching `python_version` in pyproject.toml) so the strictness stays
|
|
37
|
+
# aligned with what the SDK promises to consumers.
|
|
38
|
+
type-check:
|
|
39
|
+
name: Type check (mypy)
|
|
40
|
+
runs-on: ubuntu-latest
|
|
41
|
+
steps:
|
|
42
|
+
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
|
43
|
+
- name: Set up Python 3.10
|
|
44
|
+
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
|
45
|
+
with:
|
|
46
|
+
python-version: "3.10"
|
|
47
|
+
- name: Install dependencies
|
|
48
|
+
# Use the full dev+langchain extras so mypy sees the optional
|
|
49
|
+
# langchain integration's real types. Without langchain-core
|
|
50
|
+
# installed, mypy reports spurious errors about missing modules
|
|
51
|
+
# and unused type-ignore comments in src/layerv_qurl/langchain.py.
|
|
52
|
+
run: pip install -e ".[dev,langchain]"
|
|
53
|
+
- name: Run mypy
|
|
54
|
+
run: mypy src/
|
|
55
|
+
|
|
56
|
+
# Slack build-completion card. Thin shim over the fleet-shared reusable
|
|
57
|
+
# in layervai/ops-routines-workflows (public mirror of private
|
|
58
|
+
# layervai/ops-routines); the curl/jq Block Kit payload builder and the
|
|
59
|
+
# gate-result aggregation live there now. Adding/removing a gate is a
|
|
60
|
+
# one-line edit to `needs:` + `gates:` here — no aggregation if-chain.
|
|
61
|
+
notify:
|
|
62
|
+
name: Notify
|
|
63
|
+
needs: [test, type-check]
|
|
64
|
+
if: always() && github.event_name != 'pull_request'
|
|
65
|
+
permissions: {}
|
|
66
|
+
uses: layervai/ops-routines-workflows/.github/workflows/notify.yml@1536c698add5777aa08c781bc674d1eba469b32d # v0.9.0
|
|
67
|
+
with:
|
|
68
|
+
header: "qURL Python SDK Build"
|
|
69
|
+
gates: '{"Tests": "${{ needs.test.result }}", "Type check": "${{ needs.type-check.result }}"}'
|
|
70
|
+
extra_fields: '{"Python": "3.10, 3.12, 3.13"}'
|
|
71
|
+
secrets:
|
|
72
|
+
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
name: Claude Code Review
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
types: [opened, synchronize]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
claude-review:
|
|
9
|
+
if: github.actor != 'dependabot[bot]'
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
timeout-minutes: 14
|
|
12
|
+
permissions:
|
|
13
|
+
contents: read
|
|
14
|
+
pull-requests: read
|
|
15
|
+
issues: read
|
|
16
|
+
id-token: write
|
|
17
|
+
|
|
18
|
+
steps:
|
|
19
|
+
- name: Checkout repository
|
|
20
|
+
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
|
21
|
+
with:
|
|
22
|
+
fetch-depth: 1
|
|
23
|
+
|
|
24
|
+
- name: Run Claude Code Review
|
|
25
|
+
uses: anthropics/claude-code-action@9dd8b95a392eb34b6f5fb56cf5a64cb735912d4b # v1.0.150
|
|
26
|
+
with:
|
|
27
|
+
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
|
|
28
|
+
prompt: |
|
|
29
|
+
REPO: ${{ github.repository }}
|
|
30
|
+
PR NUMBER: ${{ github.event.pull_request.number }}
|
|
31
|
+
|
|
32
|
+
Please review this pull request and provide feedback on:
|
|
33
|
+
- Code quality and best practices
|
|
34
|
+
- Potential bugs or issues
|
|
35
|
+
- Performance considerations
|
|
36
|
+
- Security concerns
|
|
37
|
+
- Test coverage
|
|
38
|
+
|
|
39
|
+
Use the repository's CLAUDE.md for guidance on style and conventions. Be constructive and helpful in your feedback.
|
|
40
|
+
|
|
41
|
+
Use `gh pr comment` with your Bash tool to leave your review as a comment on the PR.
|
|
42
|
+
|
|
43
|
+
claude_args: '--model claude-opus-4-8 --allowed-tools "Bash(gh issue view:*),Bash(gh search:*),Bash(gh issue list:*),Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh pr list:*)"'
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
name: Claude Code
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
issue_comment:
|
|
5
|
+
types: [created]
|
|
6
|
+
pull_request_review_comment:
|
|
7
|
+
types: [created]
|
|
8
|
+
issues:
|
|
9
|
+
types: [opened, assigned]
|
|
10
|
+
pull_request_review:
|
|
11
|
+
types: [submitted]
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
claude:
|
|
15
|
+
if: |
|
|
16
|
+
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
|
|
17
|
+
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
|
|
18
|
+
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
|
|
19
|
+
(github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
permissions:
|
|
22
|
+
contents: read
|
|
23
|
+
pull-requests: read
|
|
24
|
+
issues: read
|
|
25
|
+
id-token: write
|
|
26
|
+
actions: read
|
|
27
|
+
|
|
28
|
+
steps:
|
|
29
|
+
- name: Checkout repository
|
|
30
|
+
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
|
31
|
+
with:
|
|
32
|
+
fetch-depth: 1
|
|
33
|
+
|
|
34
|
+
- name: Run Claude Code
|
|
35
|
+
id: claude
|
|
36
|
+
uses: anthropics/claude-code-action@9dd8b95a392eb34b6f5fb56cf5a64cb735912d4b # v1
|
|
37
|
+
with:
|
|
38
|
+
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
|
|
39
|
+
claude_args: '--model claude-opus-4-8'
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
name: CodeQL
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
schedule:
|
|
9
|
+
- cron: '0 6 * * 1' # Weekly on Monday at 6 AM UTC
|
|
10
|
+
|
|
11
|
+
permissions:
|
|
12
|
+
actions: read
|
|
13
|
+
contents: read
|
|
14
|
+
security-events: write
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
analyze:
|
|
18
|
+
name: Analyze
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
timeout-minutes: 30
|
|
21
|
+
|
|
22
|
+
strategy:
|
|
23
|
+
fail-fast: false
|
|
24
|
+
matrix:
|
|
25
|
+
include:
|
|
26
|
+
- language: python
|
|
27
|
+
build-mode: none
|
|
28
|
+
- language: actions
|
|
29
|
+
build-mode: none
|
|
30
|
+
|
|
31
|
+
steps:
|
|
32
|
+
- name: Checkout repository
|
|
33
|
+
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
|
34
|
+
|
|
35
|
+
- name: Initialize CodeQL
|
|
36
|
+
uses: github/codeql-action/init@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4
|
|
37
|
+
with:
|
|
38
|
+
languages: ${{ matrix.language }}
|
|
39
|
+
build-mode: ${{ matrix.build-mode }}
|
|
40
|
+
queries: security-and-quality
|
|
41
|
+
|
|
42
|
+
- name: Perform CodeQL Analysis
|
|
43
|
+
uses: github/codeql-action/analyze@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4
|
|
44
|
+
with:
|
|
45
|
+
category: "/language:${{ matrix.language }}"
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Dependency Age Check (GitHub Actions pins)
|
|
2
|
+
# Thin shim calling shared reusable workflow.
|
|
3
|
+
# Source: https://github.com/layervai/ops-routines/blob/main/.github/workflows/age-check-actions.yml
|
|
4
|
+
# Implementation: https://github.com/layervai/ops-routines/blob/main/lib/age-check-actions.sh
|
|
5
|
+
name: Dependency Age Check (Actions)
|
|
6
|
+
|
|
7
|
+
# Fires on every PR (no path filter) so the status check always reports.
|
|
8
|
+
# This lets branch protection require it without the path-filtered-
|
|
9
|
+
# required-check footgun. The reusable's script exits 0 quickly when
|
|
10
|
+
# no workflow/composite-action changes are in the diff.
|
|
11
|
+
on:
|
|
12
|
+
pull_request:
|
|
13
|
+
workflow_dispatch:
|
|
14
|
+
|
|
15
|
+
# Cancel superseded runs on the same PR branch — the reusable workflow
|
|
16
|
+
# makes sequential registry calls; no reason to let two race for an
|
|
17
|
+
# outdated diff.
|
|
18
|
+
concurrency:
|
|
19
|
+
group: dep-age-actions-${{ github.head_ref || github.ref_name }}
|
|
20
|
+
cancel-in-progress: true
|
|
21
|
+
|
|
22
|
+
permissions:
|
|
23
|
+
contents: read
|
|
24
|
+
|
|
25
|
+
jobs:
|
|
26
|
+
age-check:
|
|
27
|
+
# No outer `if:` for `age-check-bypass`. The required status check
|
|
28
|
+
# is `age-check / Check GitHub Actions pin ages` (caller-job /
|
|
29
|
+
# reusable-inner-job). Skipping here means the reusable never runs
|
|
30
|
+
# and the inner job never reports → required check stuck at
|
|
31
|
+
# "Expected — Waiting" forever. The reusable's inner `if:` handles
|
|
32
|
+
# bypass and reports SKIPPED, which satisfies the required check.
|
|
33
|
+
# Note: `timeout-minutes` is intentionally NOT set here. Per GH
|
|
34
|
+
# docs (https://docs.github.com/en/actions/using-workflows/reusing-workflows#supported-keywords-for-jobs-that-call-a-reusable-workflow)
|
|
35
|
+
# only if/name/needs/permissions/secrets/strategy/uses/with/concurrency
|
|
36
|
+
# are valid on a job that calls a reusable workflow. The reusable
|
|
37
|
+
# workflow itself sets `timeout-minutes: 5` internally.
|
|
38
|
+
uses: layervai/ops-routines-workflows/.github/workflows/age-check-actions.yml@9b72a931d25f18a3a713006963072296a0b28134 # v0.8.0
|
|
39
|
+
with:
|
|
40
|
+
min_age_days: 7
|
|
41
|
+
# Post a sticky PR comment when an age-check fails, listing each
|
|
42
|
+
# pin with its eligible-after date and days remaining. The PR
|
|
43
|
+
# author / reviewer sees the retry-after date inline on the PR
|
|
44
|
+
# instead of having to click into the run log to find it. Sticky
|
|
45
|
+
# comment is updated in place on re-runs and deleted on a clean
|
|
46
|
+
# pass; soft-fails to a `::notice` if the token can't write.
|
|
47
|
+
comment_on_failure: true
|
|
48
|
+
permissions:
|
|
49
|
+
contents: read
|
|
50
|
+
# Required for `comment_on_failure: true` to actually post.
|
|
51
|
+
# Dependabot PRs default to read-only and need this grant
|
|
52
|
+
# explicitly. Without it, the workflow still fails the age check
|
|
53
|
+
# correctly — only the inline comment is suppressed.
|
|
54
|
+
pull-requests: write
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Dependency Age Check (pip / Python)
|
|
2
|
+
# Thin shim calling shared reusable workflow.
|
|
3
|
+
# Source: https://github.com/layervai/ops-routines/blob/main/.github/workflows/age-check-pip.yml
|
|
4
|
+
# Implementation: https://github.com/layervai/ops-routines/blob/main/lib/age-check-pip.sh
|
|
5
|
+
name: Dependency Age Check (pip)
|
|
6
|
+
|
|
7
|
+
# Fires on every PR (no path filter) so the status check always reports.
|
|
8
|
+
# This lets branch protection require it without the path-filtered-
|
|
9
|
+
# required-check footgun. The reusable's script exits 0 quickly when
|
|
10
|
+
# no requirements/poetry.lock/pyproject.toml changes are in the diff.
|
|
11
|
+
on:
|
|
12
|
+
pull_request:
|
|
13
|
+
workflow_dispatch:
|
|
14
|
+
|
|
15
|
+
# Cancel superseded runs on the same PR branch — pypi.org calls are
|
|
16
|
+
# rate-limited and we throttle ourselves; no reason to let two race.
|
|
17
|
+
concurrency:
|
|
18
|
+
group: dep-age-pip-${{ github.head_ref || github.ref_name }}
|
|
19
|
+
cancel-in-progress: true
|
|
20
|
+
|
|
21
|
+
permissions:
|
|
22
|
+
contents: read
|
|
23
|
+
|
|
24
|
+
jobs:
|
|
25
|
+
age-check:
|
|
26
|
+
# No outer `if:` for `age-check-bypass`. The required status check
|
|
27
|
+
# is `age-check / check-pip-age` (caller-job / reusable-inner-job).
|
|
28
|
+
# Skipping here means the reusable never runs and the inner job
|
|
29
|
+
# never reports → required check stuck at "Expected — Waiting"
|
|
30
|
+
# forever. The reusable's inner `if:` handles bypass and reports
|
|
31
|
+
# SKIPPED, which satisfies the required check.
|
|
32
|
+
# Note: `timeout-minutes` is intentionally NOT set here. Per GH
|
|
33
|
+
# docs (https://docs.github.com/en/actions/using-workflows/reusing-workflows#supported-keywords-for-jobs-that-call-a-reusable-workflow)
|
|
34
|
+
# only if/name/needs/permissions/secrets/strategy/uses/with/concurrency
|
|
35
|
+
# are valid on a job that calls a reusable workflow. The reusable
|
|
36
|
+
# workflow itself sets `timeout-minutes: 5` internally.
|
|
37
|
+
uses: layervai/ops-routines-workflows/.github/workflows/age-check-pip.yml@9b72a931d25f18a3a713006963072296a0b28134 # v0.8.0
|
|
38
|
+
with:
|
|
39
|
+
min_age_days: 7
|
|
40
|
+
# Post a sticky PR comment when an age-check fails, listing each
|
|
41
|
+
# pin with its eligible-after date and days remaining. The PR
|
|
42
|
+
# author / reviewer sees the retry-after date inline on the PR
|
|
43
|
+
# instead of having to click into the run log to find it. Sticky
|
|
44
|
+
# comment is updated in place on re-runs and deleted on a clean
|
|
45
|
+
# pass; soft-fails to a `::notice` if the token can't write.
|
|
46
|
+
comment_on_failure: true
|
|
47
|
+
permissions:
|
|
48
|
+
contents: read
|
|
49
|
+
# Required for `comment_on_failure: true` to actually post.
|
|
50
|
+
# Dependabot PRs default to read-only and need this grant
|
|
51
|
+
# explicitly. Without it, the workflow still fails the age check
|
|
52
|
+
# correctly — only the inline comment is suppressed.
|
|
53
|
+
pull-requests: write
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
name: Dependency Review
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
branches: [main]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
pull-requests: write
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
review:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
16
|
+
- uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5.0.0
|
|
17
|
+
with:
|
|
18
|
+
fail-on-severity: high
|
|
19
|
+
comment-summary-in-pr: always
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Issue Priority Enforcement
|
|
2
|
+
# Thin shim calling shared reusable workflow.
|
|
3
|
+
# Source: https://github.com/layervai/ops-routines-workflows/blob/main/.github/workflows/issue-priority.yml
|
|
4
|
+
#
|
|
5
|
+
# Matching form templates live in .github/ISSUE_TEMPLATE/ alongside this
|
|
6
|
+
# file — GitHub does not allow cross-repo issue-template inheritance.
|
|
7
|
+
name: Issue priority enforcement
|
|
8
|
+
|
|
9
|
+
on:
|
|
10
|
+
issues:
|
|
11
|
+
types: [opened, reopened, edited, labeled, unlabeled]
|
|
12
|
+
|
|
13
|
+
# Coalesce bursts on the same issue. Redundant with the reusable's own
|
|
14
|
+
# concurrency group (same key shape), but mirrors the dep-age-check
|
|
15
|
+
# shim convention so a future ref bump that accidentally drops the
|
|
16
|
+
# reusable's concurrency doesn't silently remove all deduplication.
|
|
17
|
+
#
|
|
18
|
+
# `cancel-in-progress: false` — serialize rather than cancel. The
|
|
19
|
+
# reusable uses `setLabels` (atomic PUT), so mid-flight cancellation
|
|
20
|
+
# is safe today, but a future reusable that swaps labels non-
|
|
21
|
+
# atomically (remove old → add new) would be vulnerable to a
|
|
22
|
+
# cancelled run leaving an issue with no priority label, which would
|
|
23
|
+
# then trip the enforcement fail path. Runs are bounded at 2 minutes;
|
|
24
|
+
# queueing is cheap compared to the silent-drop failure mode.
|
|
25
|
+
concurrency:
|
|
26
|
+
group: ${{ github.workflow }}-${{ github.event.issue.number }}
|
|
27
|
+
cancel-in-progress: false
|
|
28
|
+
|
|
29
|
+
permissions:
|
|
30
|
+
contents: read
|
|
31
|
+
|
|
32
|
+
jobs:
|
|
33
|
+
enforce-priority:
|
|
34
|
+
# Shim-level defense-in-depth against label-event recursion. The
|
|
35
|
+
# reusable applies priority labels, which emits `labeled` events
|
|
36
|
+
# that would re-trigger this workflow. GitHub's GITHUB_TOKEN-based
|
|
37
|
+
# identity suppression handles the common case, AND the reusable
|
|
38
|
+
# guards with `if: sender.type != 'Bot'`. This outer `if:` mirrors
|
|
39
|
+
# that guard at the caller so a future ref bump that silently
|
|
40
|
+
# drops the reusable's guard (or switches it to a PAT/App token,
|
|
41
|
+
# which bypasses GITHUB_TOKEN suppression) can't fully defeat
|
|
42
|
+
# loop prevention.
|
|
43
|
+
#
|
|
44
|
+
# Side effect: issues OPENED by `github-actions[bot]` are exempt
|
|
45
|
+
# from priority enforcement at creation time. Subsequent human
|
|
46
|
+
# `edited` / `labeled` events re-engage enforcement (not sticky).
|
|
47
|
+
# Other bots (dependabot, renovate, etc.) pass this guard but the
|
|
48
|
+
# reusable's own `sender.type != 'Bot'` check short-circuits them
|
|
49
|
+
# before setFailed — net effect is a near-instant no-op run.
|
|
50
|
+
if: ${{ github.actor != 'github-actions[bot]' }}
|
|
51
|
+
uses: layervai/ops-routines-workflows/.github/workflows/issue-priority.yml@9b72a931d25f18a3a713006963072296a0b28134 # v0.8.0
|
|
52
|
+
permissions:
|
|
53
|
+
issues: write
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
name: PR Title
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
types: [opened, edited, synchronize, reopened]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
pull-requests: read
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
validate:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
steps:
|
|
14
|
+
- uses: amannn/action-semantic-pull-request@e32d7e603df1aa1ba07e981f2a23455dee596825 # v5.5.3
|
|
15
|
+
env:
|
|
16
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
17
|
+
with:
|
|
18
|
+
types: |
|
|
19
|
+
feat
|
|
20
|
+
fix
|
|
21
|
+
docs
|
|
22
|
+
style
|
|
23
|
+
refactor
|
|
24
|
+
perf
|
|
25
|
+
test
|
|
26
|
+
build
|
|
27
|
+
ci
|
|
28
|
+
chore
|
|
29
|
+
revert
|
|
30
|
+
scopes: |
|
|
31
|
+
client
|
|
32
|
+
api
|
|
33
|
+
ci
|
|
34
|
+
deps
|
|
35
|
+
docs
|
|
36
|
+
requireScope: false
|
|
37
|
+
subjectPattern: ^[a-z].*$
|
|
38
|
+
subjectPatternError: |
|
|
39
|
+
Subject must start with a lowercase letter.
|
|
40
|
+
Example: "feat(client): add batch resolve helper"
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
name: Release Please
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
inputs:
|
|
8
|
+
ref:
|
|
9
|
+
description: Git ref to build and publish
|
|
10
|
+
required: true
|
|
11
|
+
default: v0.2.0
|
|
12
|
+
|
|
13
|
+
permissions:
|
|
14
|
+
contents: write
|
|
15
|
+
pull-requests: write
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
release-please:
|
|
19
|
+
if: github.event_name == 'push'
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
outputs:
|
|
22
|
+
release_created: ${{ steps.release.outputs.release_created }}
|
|
23
|
+
tag_name: ${{ steps.release.outputs.tag_name }}
|
|
24
|
+
steps:
|
|
25
|
+
- uses: googleapis/release-please-action@45996ed1f6d02564a971a2fa1b5860e934307cf7 # v5.0.0
|
|
26
|
+
id: release
|
|
27
|
+
with:
|
|
28
|
+
config-file: release-please-config.json
|
|
29
|
+
manifest-file: .release-please-manifest.json
|
|
30
|
+
|
|
31
|
+
test:
|
|
32
|
+
needs: release-please
|
|
33
|
+
if: always() && (github.event_name == 'workflow_dispatch' || needs.release-please.outputs.release_created == 'true')
|
|
34
|
+
runs-on: ubuntu-latest
|
|
35
|
+
strategy:
|
|
36
|
+
fail-fast: true
|
|
37
|
+
matrix:
|
|
38
|
+
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
|
39
|
+
steps:
|
|
40
|
+
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
|
41
|
+
with:
|
|
42
|
+
ref: ${{ github.event_name == 'workflow_dispatch' && inputs.ref || github.sha }}
|
|
43
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
44
|
+
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
|
45
|
+
with:
|
|
46
|
+
python-version: ${{ matrix.python-version }}
|
|
47
|
+
- name: Install dependencies
|
|
48
|
+
run: pip install -e ".[dev,langchain]"
|
|
49
|
+
- name: Test
|
|
50
|
+
run: pytest tests/ -v
|
|
51
|
+
|
|
52
|
+
publish:
|
|
53
|
+
needs: [release-please, test]
|
|
54
|
+
if: always() && needs.test.result == 'success' && (github.event_name == 'workflow_dispatch' || needs.release-please.outputs.release_created == 'true')
|
|
55
|
+
runs-on: ubuntu-latest
|
|
56
|
+
environment: pypi
|
|
57
|
+
permissions:
|
|
58
|
+
contents: read
|
|
59
|
+
id-token: write
|
|
60
|
+
steps:
|
|
61
|
+
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
|
62
|
+
with:
|
|
63
|
+
ref: ${{ github.event_name == 'workflow_dispatch' && inputs.ref || github.sha }}
|
|
64
|
+
- name: Set up Python
|
|
65
|
+
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
|
66
|
+
with:
|
|
67
|
+
python-version: "3.12"
|
|
68
|
+
- name: Install build tools
|
|
69
|
+
run: pip install build
|
|
70
|
+
- name: Build
|
|
71
|
+
run: python -m build
|
|
72
|
+
- name: Publish to PyPI
|
|
73
|
+
uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0
|