CLI tool binary, no deps & Generate manifest from existing config.yaml#50
CLI tool binary, no deps & Generate manifest from existing config.yaml#50adnanrahic wants to merge 16 commits intomainfrom
Conversation
Add the ability to generate an OCB manifest from an existing OpenTelemetry Collector config.yaml file. This feature automatically detects components (receivers, processors, exporters, extensions, connectors) and generates a minimal manifest with the correct Go module paths. Key features: - Parse collector config.yaml and extract component names - Map components to Go modules via a comprehensive registry - Include Bindplane/observIQ components by default (--no-bindplane to exclude) - Support for named instances (e.g., otlp/traces -> otlp) - Generate-only mode or generate-and-build in one step - Shell scripts for easy CLI usage - Makefile targets for convenience New files: - builder/src/config_parser.py: Parse collector config files - builder/src/component_registry.py: Component name to gomod mapping - builder/src/components.yaml: Registry of all known components - builder/src/manifest_generator.py: Generate OCB manifests - builder/src/bindplane_components.yaml: Bindplane components config - scripts/generate_manifest.sh: Generate manifest from config - scripts/build_from_config.sh: Generate and build in one step - docs/config-to-manifest.md: Feature documentation Closes #33
Add pyproject.toml, resources.py for package-relative paths, PyInstaller spec, Homebrew formula, CI workflows for multi-platform binary builds, and host-first build support. Update scripts to prefer CLI on PATH, fix test artifact path, and align docs with --artifacts usage. Co-authored-by: Cursor <cursoragent@cursor.com>
| strategy: | ||
| fail-fast: false | ||
| matrix: | ||
| include: | ||
| - runner: ubuntu-latest | ||
| os: linux | ||
| arch: amd64 | ||
| - runner: ubuntu-24.04-arm | ||
| os: linux | ||
| arch: arm64 | ||
| - runner: macos-14 | ||
| os: darwin | ||
| arch: arm64 | ||
| runs-on: ${{ matrix.runner }} | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
|
|
||
| - name: Set up Python | ||
| uses: actions/setup-python@v5 | ||
| with: | ||
| python-version: "3.12" | ||
|
|
||
| - name: Install dependencies | ||
| run: | | ||
| python -m pip install --upgrade pip | ||
| pip install . | ||
| pip install pyinstaller | ||
|
|
||
| - name: Build binary | ||
| run: | | ||
| pyinstaller --clean --noconfirm otel-distro-builder.spec | ||
| VERSION=${GITHUB_REF#refs/tags/} | ||
| mkdir -p release | ||
| cp dist/otel-distro-builder release/otel-distro-builder-${{ matrix.os }}-${{ matrix.arch }} | ||
| chmod +x release/otel-distro-builder-${{ matrix.os }}-${{ matrix.arch }} | ||
| tar -czvf "otel-distro-builder-${VERSION}-${{ matrix.os }}-${{ matrix.arch }}.tar.gz" -C release "otel-distro-builder-${{ matrix.os }}-${{ matrix.arch }}" | ||
|
|
||
| - name: Test standalone binary (no Python required) | ||
| run: | | ||
| BIN="release/otel-distro-builder-${{ matrix.os }}-${{ matrix.arch }}" | ||
| "$BIN" --help | ||
| "$BIN" --version | ||
| "$BIN" --from-config builder/tests/configs/otelcol/simple.yaml --generate-only -o /tmp/gen.yaml | ||
| test -s /tmp/gen.yaml | ||
|
|
||
| - name: Upload artifact | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: binary-${{ matrix.os }}-${{ matrix.arch }} | ||
| path: "otel-distro-builder-*.tar.gz" | ||
|
|
||
| test-standalone-no-python: |
Check warning
Code scanning / CodeQL
Workflow does not contain permissions Medium
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI about 23 hours ago
- In general, to fix this class of problem you add an explicit
permissionsblock either at the workflow root (applies to all jobs) or per job, giving only the scopes and access levels needed (e.g.,contents: read). Jobs that need broader permissions (like publishing a release) can override with their ownpermissionsblocks. - For this workflow, the
upload-to-releasejob already haspermissions: contents: write, which is appropriate. The other jobs (build-binaryandtest-standalone-no-python) only need to read the repository contents and use artifacts; they do not push commits or modify issues, so they can safely run withcontents: read. The least intrusive and clearest fix is to add a workflow-levelpermissions:block settingcontents: read. This will apply to all jobs by default, while the existingpermissionsblock inupload-to-releasewill override it for that job, preserving its necessary write access. - Concretely, in
.github/workflows/build-cli-binaries.yml, insert apermissions:section near the top of the file, after thename:declaration and beforeon:. No imports or additional methods are needed; this is purely a YAML configuration change for the workflow.
| @@ -5,6 +5,9 @@ | ||
|
|
||
| name: Build CLI Binaries | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| on: | ||
| push: | ||
| tags: |
| runs-on: ubuntu-latest | ||
| needs: build-binary | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
|
|
||
| - name: Download linux/amd64 binary | ||
| uses: actions/download-artifact@v4 | ||
| with: | ||
| name: binary-linux-amd64 | ||
|
|
||
| - name: Extract and run binary (no Python in this job) | ||
| run: | | ||
| tar -xzf binary-linux-amd64/otel-distro-builder-*.tar.gz | ||
| BIN=$(find . -maxdepth 1 -type f -name 'otel-distro-builder-*' | head -1) | ||
| chmod +x "$BIN" | ||
| "$BIN" --help | ||
| "$BIN" --version | ||
| "$BIN" --from-config builder/tests/configs/otelcol/simple.yaml --generate-only -o /tmp/out.yaml | ||
| test -s /tmp/out.yaml | ||
| echo "Standalone binary works with no Python dependency." | ||
|
|
||
| upload-to-release: |
Check warning
Code scanning / CodeQL
Workflow does not contain permissions Medium
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI about 23 hours ago
To fix the problem, explicitly declare a minimal permissions block for the test-standalone-no-python job so it does not inherit broader default permissions. This job only needs to download an artifact and read repository contents at most, so contents: read is sufficient.
Concretely, in .github/workflows/build-cli-binaries.yml, under the test-standalone-no-python job (around line 91), add a permissions: section at the same indentation level as runs-on and needs. The block should specify contents: read. No additional imports or methods are needed; this is a pure YAML configuration change and does not alter existing functional behavior of the workflow.
| @@ -92,6 +92,8 @@ | ||
| # Prove the binary works with no Python on PATH (Go only needed for full builds). | ||
| runs-on: ubuntu-latest | ||
| needs: build-binary | ||
| permissions: | ||
| contents: read | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
|
|
…rmula Add test_resources.py covering path resolution in dev, frozen (PyInstaller), and frozen-fallback contexts, plus lru_cache behavior. Add --version/-V and _get_version tests to test_main.py. Fix Homebrew formula test expecting wrong exit code (1) for --help (argparse exits 0). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The CLI defines --output-manifest but all CI workflows and the Makefile test-standalone-binary target used the non-existent -o shorthand, causing argparse to exit with code 2. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
test_simple_build and test_contrib_build hardcoded LINUX_ARM64_ARTIFACTS, but the Docker container builds for the host architecture. On CI (ubuntu-latest = amd64) this produced amd64 artifacts, causing the assertion to fail. Now dynamically selects the expected artifact list based on the host arch. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add cli_entry.py launcher so frozen binary runs builder.src.main as a package, fixing 'attempted relative import with no known parent package' - Update otel-distro-builder.spec to use cli_entry.py and repo root pathex - build.py: guard psutil Process.io_counters() (not available on macOS) - build.py: on darwin, use resource.getrusage() ru_inblock/ru_oublock (512-byte blocks) for approximate disk read/write in build metrics Co-authored-by: Cursor <cursoragent@cursor.com>
- goreleaser_downloader: download goreleaser OSS and syft when not on PATH; use tools_dir and prepend to PATH so goreleaser finds syft for SBOMs - build.py: resolve goreleaser and syft, inject tools_dir into subprocess PATH - build-cli-binaries.yml: add windows/amd64 matrix; Unix/Windows build and test steps; upload .zip for Windows, .tar.gz for Unix; release globs both - ocb_downloader, goreleaser_downloader: use platform.system/machine for Windows compatibility (os.uname not available on Windows) - build.py: show 'N/A (unavailable on macOS)' for disk I/O when on darwin (kernel does not populate getrusage block I/O) - otel-distro-builder.spec: add goreleaser_downloader to hiddenimports Co-authored-by: Cursor <cursoragent@cursor.com>
- goreleaser_downloader: use _ for unused os.walk() variable (fix W0612) - build.py, tests: black/isort formatting Co-authored-by: Cursor <cursoragent@cursor.com>
- README.md: update docker run/pull examples and references - docs/config-to-manifest.md: update image tag references Co-authored-by: Cursor <cursoragent@cursor.com>
CLI tool binary, no deps & Generate manifest from existing
config.yamlContext
feature/config-to-manifest. Includes all code from feat: generate manifest from existing collector config.yaml #49. Merging this will close both [Feature Request] Build distro with an existingconfig.yamlfile #33 and [Feature Request] Package otel-distro-builder as installable CLI (no Docker required) #51 . Deleting feat: generate manifest from existing collector config.yaml #49 in favor of this.Summary
Implements the "Package Python app as CLI" plan: the builder is now an installable CLI (
otel-distro-builder) that runs on the host with no Docker required. For full distribution builds, Go is the only required dependency; OCB is downloaded by the CLI. Manifest generation (--from-config,--generate-only) has no runtime dependencies when using the standalone binary or pip install.Changes
Packaging & CLI
pyproject.tomlat repo root: installable packageotel-distro-builderwithconsole_scriptsentry, dependencies frombuilder/requirements.txt, and package data (templates,versions.yaml,components.yaml,bindplane_components.yaml).builder/src/resources.pyusesimportlib.resourcesandsys._MEIPASS(PyInstaller) so templates and YAML resolve correctly when installed or frozen. All references inversion.py,main.py,build.py,component_registry.py,manifest_generator.pyuse these helpers.BUILD_DIR = "/build". Build and artifact directories are host paths (e.g.--artifacts ./artifacts);BuildContexttakes abuild_dirargument. Default artifacts dir is./artifacts(cwd-based).Standalone binary & release
otel-distro-builder.specproduces a one-file binary;make build-clibuilds it locally. Optional dependency:pip install pyinstaller..github/workflows/build-cli-binaries.ymlon tagv*builds binaries for linux/amd64, linux/arm64 (ubuntu-24.04-arm), and darwin/arm64, runs in-job tests and a no-Python job to validate the binary, then uploads tarballs to the release.release.ymlbuilds the Python package and attachesdist/*to the release; binary workflow attaches platform tarballs.Homebrew & docs
Formula/otel-distro-builder.rbwith version and OS/arch-specific URLs (sha256 placeholders; update on first release).Scripts & tests
generate_manifest.shandrun_local_build.shpreferotel-distro-builderon PATH, thenpython -m builder.src.main, with host paths. Docker remains optional.otel-distro-builder --helpand a generate-only smoke test.script-test,build-cli,test-standalone-binary(validates binary with no Python at runtime).Config-to-manifest (from existing branch)
--from-config,--output-manifest,--generate-only,--no-bindplane, etc., withcomponents.yaml/bindplane_components.yaml, and scripts/docs aligned.Testing
make unit-test— 108 unit tests passedmake script-test— script smoke tests (generate_manifest, run_local_build, build_from_config) passedmake test-standalone-binary— run aftermake build-clito confirm the binary works with no Python at runtimeNotes
ubuntu-24.04-armis used for linux/arm64. If your GitHub plan doesn't include ARM runners, remove that matrix entry frombuild-cli-binaries.yml.Formula/otel-distro-builder.rbwith realsha256values after the first release that publishes binary tarballs.Checklist
Made with Cursor