Skip to content

Commit ff76817

Browse files
fix: address RC2 vote feedback (#745)
* fix: add __init__.py to tests/ so pytest discovery works * fix: add ASF license header to tutorial.md * fix: update .rat-excludes for RC2 feedback - Fix patterns for burr/examples/ symlink duplicates (use .* prefix) - Add .github/ templates (YAML/MD with frontmatter) - Add image file extensions (.png, .gif, .ico, .jpg) * fix: include hello-world-counter in release artifacts The tracking server imports burr.examples.hello-world-counter.server (added in #675) but the release config still had it in the exclude list. Move it from exclude to include so the wheel ships with the module the server needs, preventing ModuleNotFoundError when running burr from a fresh install. Also bumps REQUIRED_EXAMPLES in scripts/apache_release.py and updates tests/test_release_config.py accordingly. * fix: use sys.executable for uvicorn subprocess to fix venv isolation The CLI spawned uvicorn as a bare command, which resolves via PATH. For users with pyenv installed, ~/.pyenv/shims/ is in PATH ahead of any venv's bin/, so bare `uvicorn` always hits a pyenv shim that routes to a pyenv environment — never the venv the user is running burr from. This means a fresh `pip install` into a non-pyenv venv fails to start the server. Using sys.executable -m uvicorn ensures uvicorn runs under the same Python interpreter that is running burr, regardless of PATH. * chore: add --skip-signing flag and CI smoke-test helper Preparation for the release-validation CI workflow. apache_release.py: - Add --skip-signing to archive/sdist/wheel/all subcommands - Split _sign_artifact into checksum (always) and GPG sign (skippable) - Drop gpg from required tools when --skip-signing is set ci_smoke_server.py: - Installs a built wheel into a fresh venv outside the source tree - Imports burr.tracking.server.run (catches missing-example bugs like #675) - Starts the burr server on a free port with a dedicated data dir - Runs a tracked app, verifies the server observes the project * ci: drop svn requirement from 'all' command when --no-upload is set CI runners don't have svn installed. The 'all' subcommand listed svn as a required tool unconditionally, but svn is only used during the upload step. Skip the requirement when --no-upload is passed. * ci: add release validation workflow Build the full release pipeline on every PR, plus RAT license check and an end-to-end smoke install of the wheel outside the source tree. This catches the failure modes that have broken recent RCs: - build-artifacts: runs apache_release.py all --skip-signing --no-upload, verifies the 3 artifacts exist, runs Apache RAT without --report-only so license violations fail the job. - install-and-smoke: on 3.10/3.11/3.12, installs the wheel into a fresh venv and runs scripts/ci_smoke_server.py. That helper imports the server module, boots the server, runs a tracked app, and asserts the server sees the project — so a missing example (like PR #675's hello-world-counter) would fail here. Only "build-artifacts" and "install-and-smoke (3.12)" are required checks in .asf.yaml; 3.10 and 3.11 are informational. * fix: rewrite .rat-excludes with basename patterns that actually work RAT's -E regex doesn't reliably match through path separators or symlinked directories. The previous patterns like 'examples/deep-researcher/prompts.py' never excluded anything because RAT effectively matches against basenames. We never noticed because all prior RAT runs used --report-only mode. Switch to basename patterns. The .tsx files are uniquely named, so basename matching is precise. prompts.py only exists once. utils.py matches 5 different files (all our own ASF code with headers); the practical risk of skipping their checks is low. Update the leading comment in .rat-excludes to document the constraint so future authors don't repeat the mistake. * chore: add .claude/ to .gitignore * fix: address review feedback (paths-ignore, basename collisions, count) - Workflow: drop '**/*.md' from paths-ignore. It would suppress runs whenever a bundled .md file (like the deployment tutorial.md) changes — exactly the case that triggered RC2 feedback. - .rat-excludes: document the basename collisions for utils.py and button.tsx so the next maintainer doesn't think they're unique. - test_release_config.py: fix '4 examples' string that should have been bumped to 5 when hello-world-counter was added. * fix: use os.path.lexists in _prepare_wheel_contents to handle broken symlinks On CI runners, burr/examples is a relative symlink ('../examples') that may not resolve from the process's working directory — os.path.exists returns False for a broken link while the link itself is still present on disk. That made _prepare_wheel_contents skip the removal branch and then fail on os.makedirs with 'File exists: burr/examples'. Switch to os.path.lexists, which returns True for any directory entry including broken symlinks, so the cleanup branch always runs when the link is present.
1 parent 0bf59dc commit ff76817

11 files changed

Lines changed: 587 additions & 50 deletions

File tree

.asf.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,9 @@ github:
6363
# strict means "Require branches to be up to date before merging".
6464
strict: false
6565
# contexts are the names of checks that must pass
66-
# contexts:
66+
contexts:
67+
- "Release Validation / build-artifacts"
68+
- "Release Validation / install-and-smoke (3.12)"
6769
required_pull_request_reviews:
6870
dismiss_stale_reviews: false
6971
require_code_owner_reviews: false
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
#<!--
2+
# Licensed to the Apache Software Foundation (ASF) under one
3+
# or more contributor license agreements. See the NOTICE file
4+
# distributed with this work for additional information
5+
# regarding copyright ownership. The ASF licenses this file
6+
# to you under the Apache License, Version 2.0 (the
7+
# "License"); you may not use this file except in compliance
8+
# with the License. You may obtain a copy of the License at
9+
#
10+
# http://www.apache.org/licenses/LICENSE-2.0
11+
#
12+
# Unless required by applicable law or agreed to in writing,
13+
# software distributed under the License is distributed on an
14+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
# KIND, either express or implied. See the License for the
16+
# specific language governing permissions and limitations
17+
# under the License.
18+
#-->
19+
# Validates the Apache release pipeline on every PR: builds the real release
20+
# artifacts (git archive, sdist, wheel) using the release script with
21+
# --skip-signing, runs Apache RAT on the source tarball, then installs the
22+
# wheel into a fresh venv outside the source tree and smoke-tests the server.
23+
#
24+
# This is designed to catch the class of bugs that have broken recent RCs:
25+
# license/header issues (RAT), examples missing from the wheel (smoke test),
26+
# and general "voter tries to install this and it breaks" failures.
27+
28+
name: Release Validation
29+
30+
on:
31+
push:
32+
branches:
33+
- main
34+
tags:
35+
- 'v*.*.*-incubating-RC*'
36+
pull_request:
37+
types: [opened, synchronize, reopened]
38+
paths-ignore:
39+
- 'docs/**'
40+
- 'website/**'
41+
# Note: do NOT use '**/*.md' here. Some bundled examples ship .md files
42+
# (e.g. examples/deployment/aws/terraform/tutorial.md) and a missing
43+
# ASF header on those would cause a real RAT failure we want to catch.
44+
workflow_dispatch:
45+
46+
concurrency:
47+
group: release-validation-${{ github.ref }}
48+
cancel-in-progress: true
49+
50+
permissions:
51+
contents: read
52+
53+
jobs:
54+
build-artifacts:
55+
name: build-artifacts
56+
runs-on: ubuntu-latest
57+
timeout-minutes: 20
58+
outputs:
59+
version: ${{ steps.version.outputs.version }}
60+
steps:
61+
- uses: actions/checkout@v4
62+
63+
- uses: actions/setup-python@v4
64+
with:
65+
python-version: '3.12'
66+
cache: pip
67+
68+
- uses: actions/setup-node@v4
69+
with:
70+
node-version: '20'
71+
cache: npm
72+
cache-dependency-path: telemetry/ui/package-lock.json
73+
74+
- uses: actions/setup-java@v4
75+
with:
76+
distribution: temurin
77+
java-version: '17'
78+
79+
- name: Install system deps
80+
run: sudo apt-get install -y --no-install-recommends graphviz
81+
82+
- name: Install Python build deps
83+
run: pip install flit twine
84+
85+
- name: Cache Apache RAT
86+
id: cache-rat
87+
uses: actions/cache@v4
88+
with:
89+
path: ~/.cache/apache-rat
90+
key: apache-rat-0.16.1
91+
92+
- name: Download Apache RAT if not cached
93+
if: steps.cache-rat.outputs.cache-hit != 'true'
94+
run: |
95+
mkdir -p ~/.cache/apache-rat
96+
curl -fL -o ~/.cache/apache-rat/apache-rat-0.16.1.jar \
97+
https://repo1.maven.org/maven2/org/apache/rat/apache-rat/0.16.1/apache-rat-0.16.1.jar
98+
99+
- name: Extract version
100+
id: version
101+
run: |
102+
VERSION=$(python -c 'import re; print(re.search(r"version\s*=\s*\"([^\"]+)\"", open("pyproject.toml").read()).group(1))')
103+
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
104+
echo "BURR_VERSION=$VERSION" >> "$GITHUB_ENV"
105+
106+
- name: Build release artifacts (no signing, no upload)
107+
run: |
108+
python scripts/apache_release.py all "$BURR_VERSION" 0 ci-runner \
109+
--skip-signing --no-upload
110+
111+
- name: Verify all 3 artifacts exist
112+
run: |
113+
test -f "dist/apache-burr-${BURR_VERSION}-incubating-src.tar.gz"
114+
test -f "dist/apache-burr-${BURR_VERSION}-incubating-sdist.tar.gz"
115+
test -f "dist/apache_burr-${BURR_VERSION}-py3-none-any.whl"
116+
117+
- name: Run Apache RAT on source and sdist tarballs
118+
run: |
119+
python scripts/verify_apache_artifacts.py licenses \
120+
--rat-jar ~/.cache/apache-rat/apache-rat-0.16.1.jar \
121+
--artifacts-dir dist
122+
123+
- name: Upload release artifacts
124+
uses: actions/upload-artifact@v4
125+
with:
126+
name: release-artifacts
127+
path: |
128+
dist/*.tar.gz
129+
dist/*.whl
130+
dist/*.sha512
131+
dist/rat-report-*.xml
132+
dist/rat-report-*.txt
133+
retention-days: 14
134+
135+
install-and-smoke:
136+
name: install-and-smoke
137+
needs: build-artifacts
138+
runs-on: ubuntu-latest
139+
timeout-minutes: 10
140+
strategy:
141+
fail-fast: false
142+
matrix:
143+
# 3.9 is skipped because burr/cli/__main__.py uses PEP 604 union syntax
144+
# (dict | None) which requires Python 3.10+. Tracked separately.
145+
python-version: ['3.10', '3.11', '3.12']
146+
steps:
147+
- uses: actions/checkout@v4
148+
149+
- name: Set up Python ${{ matrix.python-version }}
150+
uses: actions/setup-python@v4
151+
with:
152+
python-version: ${{ matrix.python-version }}
153+
154+
- name: Download release artifacts
155+
uses: actions/download-artifact@v4
156+
with:
157+
name: release-artifacts
158+
path: dist
159+
160+
- name: Run smoke test
161+
env:
162+
BURR_VERSION: ${{ needs.build-artifacts.outputs.version }}
163+
run: |
164+
python scripts/ci_smoke_server.py \
165+
--wheel "dist/apache_burr-${BURR_VERSION}-py3-none-any.whl"
166+
167+
- name: Upload smoke workspace on failure
168+
if: failure()
169+
uses: actions/upload-artifact@v4
170+
with:
171+
name: smoke-workspace-${{ matrix.python-version }}
172+
path: /tmp/burr-smoke-*
173+
retention-days: 7
174+
if-no-files-found: ignore

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,3 +201,6 @@ examples/deployment/aws/terraform/*.tfstate
201201
examples/deployment/aws/terraform/*.tfstate.*
202202
examples/deployment/aws/terraform/.terraform.tfstate.lock.info
203203
examples/deployment/aws/terraform/*.tfplan
204+
205+
# Claude Code session data
206+
.claude/

.rat-excludes

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
# Apache RAT exclude patterns.
2+
#
3+
# IMPORTANT: RAT's -E flag matches each pattern as a regex, but only
4+
# reliably matches against the file basename. Path-style patterns like
5+
# 'examples/foo/bar.py' don't work, especially through symlinked dirs
6+
# (burr/examples is a symlink to ../examples in the source tree).
7+
# Use basename patterns. Be aware that broad basenames like 'utils.py'
8+
# will skip license checks on every utils.py in the repo.
9+
110
# Python marker file
211
.*py\.typed
312

@@ -25,13 +34,45 @@ robots\.txt
2534
# JSON config files (cannot contain comments)
2635
.*\.json
2736

28-
# Third-party MIT-licensed files (attributed in LICENSE)
29-
examples/deep-researcher/prompts\.py
30-
examples/deep-researcher/utils\.py
31-
website/src/components/ui/.*\.tsx
37+
# YAML config files in .github/ (templates with frontmatter, headers impractical)
38+
labeler\.yml
39+
config\.yml
40+
bug_report\.md
41+
feature_request\.md
42+
PULL_REQUEST_TEMPLATE\.md
43+
44+
# Third-party MIT-licensed files (attributed in LICENSE).
45+
# Most names are unique within the repo so basename matching is safe.
46+
# Known collisions:
47+
# - utils.py: also matches our own ASF code in burr/tracking/, etc.
48+
# (4 other utils.py files; all currently have ASF headers)
49+
# - button.tsx: also matches telemetry/ui/src/components/common/button.tsx
50+
# (our own ASF code with header)
51+
# A future regression in any of those collision targets would silently pass
52+
# RAT. Tracked as a follow-up to rename or restructure.
53+
prompts\.py
54+
utils\.py
55+
animated-beam\.tsx
56+
animated-shiny-text\.tsx
57+
blur-fade\.tsx
58+
border-beam\.tsx
59+
button\.tsx
60+
dot-pattern\.tsx
61+
icon-cloud\.tsx
62+
magic-card\.tsx
63+
marquee\.tsx
64+
number-ticker\.tsx
65+
safari\.tsx
66+
shimmer-button\.tsx
67+
68+
# Tutorial markdown for the AWS terraform deployment example
69+
tutorial\.md
3270

3371
# SVG files (third-party logos and graphics, headers impractical)
3472
.*\.svg
3573

36-
# Examples pattern (legacy - keeping for compatibility)
37-
apache_burr-.*/burr/examples
74+
# Image files (binary, cannot contain headers)
75+
.*\.png
76+
.*\.gif
77+
.*\.ico
78+
.*\.jpg

burr/cli/__main__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ def _run_server(
168168
# TODO: Implement server running logic here
169169
# Example: Start a web server, configure ports, etc.
170170
logger.info(f"Starting server on port {port}")
171-
cmd = f"uvicorn burr.tracking.server.run:app --port {port} --host {host}"
171+
cmd = f"{sys.executable} -m uvicorn burr.tracking.server.run:app --port {port} --host {host}"
172172
if dev_mode:
173173
cmd += " --reload"
174174

examples/deployment/aws/terraform/tutorial.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,22 @@
1+
<!--
2+
Licensed to the Apache Software Foundation (ASF) under one
3+
or more contributor license agreements. See the NOTICE file
4+
distributed with this work for additional information
5+
regarding copyright ownership. The ASF licenses this file
6+
to you under the Apache License, Version 2.0 (the
7+
"License"); you may not use this file except in compliance
8+
with the License. You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing,
13+
software distributed under the License is distributed on an
14+
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
KIND, either express or implied. See the License for the
16+
specific language governing permissions and limitations
17+
under the License.
18+
-->
19+
120
# Apache Burr AWS Tracking Infrastructure Tutorial
221

322
This tutorial explains how to deploy Apache Burr tracking infrastructure on AWS using Terraform. All Terraform code lives in `examples/deployment/aws/terraform/`. It covers deployment with S3 only (polling mode), with S3 and SQS (event-driven mode), and local development without AWS.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,7 @@ include = [
265265
"examples/multi-modal-chatbot/**",
266266
"examples/streaming-fastapi/**",
267267
"examples/deep-researcher/**",
268+
"examples/hello-world-counter/**",
268269
]
269270
exclude = [
270271
"telemetry/ui/node_modules/**",
@@ -295,7 +296,6 @@ exclude = [
295296
"examples/deployment/**",
296297
"examples/hamilton-integration/**",
297298
"examples/haystack-integration/**",
298-
"examples/hello-world-counter/**",
299299
"examples/image-telephone/**",
300300
"examples/instructor-gemini-flash/**",
301301
"examples/integrations/**",

0 commit comments

Comments
 (0)