From e709c8c22635197d6dba1f54bb5b686cbf444a7e Mon Sep 17 00:00:00 2001 From: Alex Lovell-Troy Date: Tue, 5 May 2026 16:46:29 +0100 Subject: [PATCH 1/3] Add build automation with Makefile and update github workflows Signed-off-by: Alex Lovell-Troy --- .fabrica.yaml | 40 +++++ .github/workflows/PRBuild.yaml | 107 +++++++++++++ .github/workflows/REUSE.yaml | 16 ++ .github/workflows/codegen-check.yaml | 35 +++++ .github/workflows/golangci-lint.yaml | 25 +++ .github/workflows/release.yaml | 82 +++++++--- .github/workflows/scorecard.yml | 82 ++++++++++ .github/workflows/stale.yml | 38 +++++ .gitignore | 4 + Makefile | 220 +++++++++++++++++++++++++++ 10 files changed, 625 insertions(+), 24 deletions(-) create mode 100644 .fabrica.yaml create mode 100644 .github/workflows/PRBuild.yaml create mode 100644 .github/workflows/REUSE.yaml create mode 100644 .github/workflows/codegen-check.yaml create mode 100644 .github/workflows/golangci-lint.yaml create mode 100644 .github/workflows/scorecard.yml create mode 100644 .github/workflows/stale.yml create mode 100644 Makefile diff --git a/.fabrica.yaml b/.fabrica.yaml new file mode 100644 index 0000000..70861ab --- /dev/null +++ b/.fabrica.yaml @@ -0,0 +1,40 @@ +# SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +# +# SPDX-License-Identifier: MIT + +project: + name: fru-tracker + module: github.com/example/fru-tracker + description: OpenCHAMI FRU tracker service with Fabrica-generated REST APIs for hardware discovery and inventory + created: 2026-02-26T11:09:26-08:00 +features: + validation: + enabled: true + mode: strict + events: + enabled: true + bus_type: memory + conditional: + enabled: true + etag_algorithm: sha256 + auth: + enabled: false + security: + authn: + enabled: false + authz: + enabled: false + mode: enforce + storage: + enabled: true + type: ent + metrics: + enabled: false +generation: + handlers: true + storage: true + client: true + openapi: true + events: true + middleware: true + reconciliation: true diff --git a/.github/workflows/PRBuild.yaml b/.github/workflows/PRBuild.yaml new file mode 100644 index 0000000..4db043c --- /dev/null +++ b/.github/workflows/PRBuild.yaml @@ -0,0 +1,107 @@ +# Copyright © 2026 OpenCHAMI a Series of LF Projects, LLC +# +# SPDX-License-Identifier: MIT + +name: Build each PR for testing and validation + +on: + pull_request: + branches: + - main + types: [opened, synchronize, reopened, edited] + workflow_dispatch: + inputs: + pr_number: + description: 'PR Number to build (optional, for manual PR builds)' + required: false + type: string + +permissions: write-all # Necessary for the generate-build-provenance action with containers + +jobs: + + build: + + + runs-on: ubuntu-latest + + steps: + - name: Set up latest stable Go + uses: actions/setup-go@v6.4.0 + with: + go-version: stable + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + with: + driver-opts: | + image=moby/buildkit:master + network=host + - name: Docker Login + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Checkout + uses: actions/checkout@v6.0.2 + with: + fetch-tags: 1 + fetch-depth: 0 + # Set environment variables required by GoReleaser + - name: Set build environment variables + run: | + echo "GIT_STATE=$(if git diff-index --quiet HEAD --; then echo 'clean'; else echo 'dirty'; fi)" >> $GITHUB_ENV + echo "BUILD_HOST=$(hostname)" >> $GITHUB_ENV + echo "GO_VERSION=$(go version | awk '{print $3}')" >> $GITHUB_ENV + echo "BUILD_USER=$(whoami)" >> $GITHUB_ENV + echo "CGO_ENABLED=0" >> $GITHUB_ENV + echo "IS_PR_BUILD=true" >> $GITHUB_ENV + + - name: Docker Login + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Create Tag for PR + if: github.event_name == 'pull_request' || (github.event_name == 'workflow_dispatch' && inputs.pr_number != '') + run: | + git config --global user.name "github-actions[bot]" + git config --global user.email "github-actions[bot]@users.noreply.github.com" + PR_NUM="${{ github.event.number }}" + if [[ "${{ inputs.pr_number }}" != "" ]]; then + PR_NUM="${{ inputs.pr_number }}" + fi + git tag -f -a pr-${PR_NUM} -m "PR Release" + + - name: Build/Push container with goreleaser + uses: goreleaser/goreleaser-action@v6 + env: + GITHUB_TOKEN: ${{ github.token }} + with: + version: '~> 2' + args: release --clean --skip=announce,validate,archive + id: goreleaser + - name: Process goreleaser output + id: process_goreleaser_output + run: | + echo "const fs = require('fs');" > process.js + echo 'const artifacts = ${{ steps.goreleaser.outputs.artifacts }}' >> process.js + echo "const firstNonNullDigest = artifacts.find(artifact => artifact.extra && artifact.extra.Digest != null)?.extra.Digest;" >> process.js + echo "console.log(firstNonNullDigest);" >> process.js + echo "fs.writeFileSync('digest.txt', firstNonNullDigest);" >> process.js + node process.js + echo "digest=$(cat digest.txt)" >> $GITHUB_OUTPUT + - name: Attest Binaries + uses: actions/attest-build-provenance@v4.1.0 + with: + subject-path: dist/**/fru-tracker* + - name: generate build provenance + uses: actions/attest-build-provenance@v4.1.0 + with: + subject-name: ghcr.io/openchami/fru-tracker + subject-digest: ${{ steps.process_goreleaser_output.outputs.digest }} + push-to-registry: true diff --git a/.github/workflows/REUSE.yaml b/.github/workflows/REUSE.yaml new file mode 100644 index 0000000..c42cb9a --- /dev/null +++ b/.github/workflows/REUSE.yaml @@ -0,0 +1,16 @@ +# Copyright © 2026 OpenCHAMI a Series of LF Projects, LLC +# SPDX-FileCopyrightText: 2020 Free Software Foundation Europe e.V. +# +# SPDX-License-Identifier: CC0-1.0 +# SPDX-License-Identifier: MIT +name: REUSE Compliance Check + +on: [push, pull_request] + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6.0.2 + - name: REUSE Compliance Check + uses: fsfe/reuse-action@v6 diff --git a/.github/workflows/codegen-check.yaml b/.github/workflows/codegen-check.yaml new file mode 100644 index 0000000..580ee79 --- /dev/null +++ b/.github/workflows/codegen-check.yaml @@ -0,0 +1,35 @@ +# SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +# +# SPDX-License-Identifier: MIT + +name: Codegen Check + +on: + pull_request: + branches: [main] + paths: + - "apis/**" + - "cmd/server/**" + - "internal/middleware/**" + - "internal/storage/**" + - "pkg/apiversion/**" + - "pkg/client/**" + - "pkg/reconcilers/**" + - "Makefile" + - ".github/workflows/codegen-check.yaml" + workflow_dispatch: + +jobs: + codegen-drift: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v6.0.2 + + - name: Set up Go + uses: actions/setup-go@v6.4.0 + with: + go-version: stable + + - name: Verify generated code is committed + run: make generate-check diff --git a/.github/workflows/golangci-lint.yaml b/.github/workflows/golangci-lint.yaml new file mode 100644 index 0000000..b242ba3 --- /dev/null +++ b/.github/workflows/golangci-lint.yaml @@ -0,0 +1,25 @@ +# Copyright © 2026 OpenCHAMI a Series of LF Projects, LLC +# +# SPDX-License-Identifier: MIT +name: golangci-lint + +on: + push: + branches: [ main ] + pull_request: + workflow_dispatch: + +jobs: + lint: + runs-on: ubuntu-latest + + steps: + - name: Set up latest stable Go + uses: actions/setup-go@v6.4.0 + with: + go-version: stable + - uses: actions/checkout@v6.0.2 + - name: Run golangci-lint + uses: golangci/golangci-lint-action@v9.2.0 + with: + version: latest diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index c338949..959c183 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -1,50 +1,84 @@ -# SPDX-FileCopyrightText: 2026 Copyright © 2026 OpenCHAMI a Series of LF Projects, LLC +# Copyright © 2026 OpenCHAMI a Series of LF Projects, LLC # # SPDX-License-Identifier: MIT -name: Release +name: Release with goreleaser on: + workflow_dispatch: push: tags: - - 'v*.*.*' + - v* -permissions: - contents: write - packages: write +permissions: write-all # Necessary for the generate-build-provenance action with containers jobs: - goreleaser: + + build: + + runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - name: Set up Go - uses: actions/setup-go@v5 + steps: + - name: Set up latest stable Go + uses: actions/setup-go@v6.4.0 with: - go-version: '1.23' - + go-version: stable - name: Set up QEMU uses: docker/setup-qemu-action@v3 - - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - - - name: Login to GitHub Container Registry + with: + driver-opts: | + image=moby/buildkit:master + network=host + - name: Docker Login uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} + - name: Checkout + uses: actions/checkout@v6.0.2 + with: + fetch-tags: 1 + fetch-depth: 0 + # Set environment variables required by GoReleaser + - name: Set build environment variables + run: | + echo "GIT_STATE=$(if git diff-index --quiet HEAD --; then echo 'clean'; else echo 'dirty'; fi)" >> $GITHUB_ENV + echo "BUILD_HOST=$(hostname)" >> $GITHUB_ENV + echo "GO_VERSION=$(go version | awk '{print $3}')" >> $GITHUB_ENV + echo "BUILD_USER=$(whoami)" >> $GITHUB_ENV + echo "CGO_ENABLED=0" >> $GITHUB_ENV + echo "IS_PR_BUILD=false" >> $GITHUB_ENV - - name: Run GoReleaser + - name: Release with goreleaser uses: goreleaser/goreleaser-action@v6 + env: + GITHUB_TOKEN: ${{ github.token }} with: - distribution: goreleaser - version: '~> v2' + version: latest args: release --clean - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + id: goreleaser + - name: Process goreleaser output + id: process_goreleaser_output + run: | + echo "const fs = require('fs');" > process.js + echo 'const artifacts = ${{ steps.goreleaser.outputs.artifacts }}' >> process.js + echo "const firstNonNullDigest = artifacts.find(artifact => artifact.extra && artifact.extra.Digest != null)?.extra.Digest;" >> process.js + echo "console.log(firstNonNullDigest);" >> process.js + echo "fs.writeFileSync('digest.txt', firstNonNullDigest);" >> process.js + node process.js + echo "digest=$(cat digest.txt)" >> $GITHUB_OUTPUT + - name: Attest Binaries + uses: actions/attest-build-provenance@v1 + with: + subject-path: dist/**/fru-tracker* + - name: generate build provenance + uses: actions/attest-build-provenance@v1 + with: + subject-name: ghcr.io/openchami/fru-tracker + subject-digest: ${{ steps.process_goreleaser_output.outputs.digest }} + push-to-registry: true + diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml new file mode 100644 index 0000000..728428f --- /dev/null +++ b/.github/workflows/scorecard.yml @@ -0,0 +1,82 @@ +# Copyright © 2026 OpenCHAMI a Series of LF Projects, LLC +# +# SPDX-License-Identifier: MIT + +# This workflow uses actions that are not certified by GitHub. They are provided +# by a third-party and are governed by separate terms of service, privacy +# policy, and support documentation. + +name: Scorecard supply-chain security +on: + # For Branch-Protection check. Only the default branch is supported. See + # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection + branch_protection_rule: + # To guarantee Maintained check is occasionally updated. See + # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained + schedule: + - cron: '39 5 * * 1' + push: + branches: [ "main" ] + +# Declare default permissions as read only. +permissions: read-all + +jobs: + analysis: + name: Scorecard analysis + runs-on: ubuntu-latest + # `publish_results: true` only works when run from the default branch. conditional can be removed if disabled. + if: github.event.repository.default_branch == github.ref_name || github.event_name == 'pull_request' + permissions: + # Needed to upload the results to code-scanning dashboard. + security-events: write + # Needed to publish results and get a badge (see publish_results below). + id-token: write + # Uncomment the permissions below if installing in a private repository. + # contents: read + # actions: read + + steps: + - name: "Checkout code" + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + + - name: "Run analysis" + uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75731b0186 # v2.4.1 + with: + results_file: results.sarif + results_format: sarif + # (Optional) "write" PAT token. Uncomment the `repo_token` line below if: + # - you want to enable the Branch-Protection check on a *public* repository, or + # - you are installing Scorecard on a *private* repository + # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action?tab=readme-ov-file#authentication-with-fine-grained-pat-optional. + # repo_token: ${{ secrets.SCORECARD_TOKEN }} + + # Public repositories: + # - Publish results to OpenSSF REST API for easy access by consumers + # - Allows the repository to include the Scorecard badge. + # - See https://github.com/ossf/scorecard-action#publishing-results. + # For private repositories: + # - `publish_results` will always be set to `false`, regardless + # of the value entered here. + publish_results: true + + # (Optional) Uncomment file_mode if you have a .gitattributes with files marked export-ignore + # file_mode: git + + # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF + # format to the repository Actions tab. + - name: "Upload artifact" + uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1 + with: + name: SARIF file + path: results.sarif + retention-days: 5 + + # Upload the results to GitHub's code scanning dashboard (optional). + # Commenting out will disable upload of results to your repo's Code Scanning dashboard + - name: "Upload to code-scanning" + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: results.sarif diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml new file mode 100644 index 0000000..5f90952 --- /dev/null +++ b/.github/workflows/stale.yml @@ -0,0 +1,38 @@ +# Copyright © 2026 OpenCHAMI a Series of LF Projects, LLC +# +# SPDX-License-Identifier: MIT + +name: Stale issues/PRs (org default) + +on: + schedule: + - cron: "23 3 * * *" # daily at 03:23 UTC + workflow_dispatch: + +permissions: + issues: write + pull-requests: write + +jobs: + run-stale: + runs-on: ubuntu-latest + steps: + - uses: actions/stale@v9 + with: + days-before-stale: 35 + days-before-close: 7 + stale-issue-label: "stale" + stale-pr-label: "stale" + exempt-issue-labels: "pinned,security,help wanted" + exempt-pr-labels: "pinned,security" + operations-per-run: 500 + remove-stale-when-updated: true + stale-issue-message: > + This issue has been automatically marked as stale due to inactivity. + Please add a comment or label to keep it open; otherwise it will close in 7 days. + close-issue-message: > + Closing due to inactivity. Feel free to reopen with new information. + stale-pr-message: > + This PR has been marked stale due to inactivity. Comment or push changes to keep it open. + close-pr-message: > + Closing due to inactivity. Please reopen when it’s ready again. \ No newline at end of file diff --git a/.gitignore b/.gitignore index cb4d0c8..67e6eaf 100644 --- a/.gitignore +++ b/.gitignore @@ -29,6 +29,10 @@ data/ *.yml !example.yaml !example.yml +!.github/workflows/*.yaml +!.github/workflows/*.yml +!.fabrica.yaml + # IDE files .vscode/ diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..6dfdbf9 --- /dev/null +++ b/Makefile @@ -0,0 +1,220 @@ +# Copyright © 2026 OpenCHAMI a Series of LF Projects, LLC +# SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +# +# SPDX-License-Identifier: MIT + +.PHONY: help build test test-integration lint clean install run docker-build docker-run release-test check-no-pkg-resources-imports generate generate-check dev + +# Variables +BINARY_NAME=fru-tracker-server +CLIENT_BINARY_NAME=fru-tracker-client +GO=go +GOFLAGS=-v +TEST_TIMEOUT ?= 5m +VERSION ?= $(shell git describe --tags --always --dirty 2>/dev/null || echo "dev") +COMMIT ?= $(shell git rev-parse --short HEAD 2>/dev/null || echo "unknown") +DATE ?= $(shell date -u +"%Y-%m-%dT%H:%M:%SZ") +LDFLAGS=-ldflags "-X main.version=$(VERSION) -X main.commit=$(COMMIT) -X main.date=$(DATE)" +FABRICA_CMD ?= go run github.com/openchami/fabrica/cmd/fabrica@latest +FABRICA_SOURCE_ARG ?= +FABRICA_ENV ?= +LOCAL_FABRICA ?= + +ifneq ($(strip $(LOCAL_FABRICA)),) +FABRICA_CMD := $(LOCAL_FABRICA)/bin/fabrica +FABRICA_SOURCE_ARG := --fabrica-source $(LOCAL_FABRICA) +FABRICA_ENV := GOTOOLCHAIN=auto +endif + +help: ## Display this help screen + @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' + + +build: generate + go build -o bin/$(BINARY_NAME) ./cmd/server/ + go build -o bin/$(CLIENT_BINARY_NAME) ./cmd/client/ + +generate: ## Regenerate Fabrica outputs +ifneq ($(strip $(LOCAL_FABRICA)),) + @if [ ! -x $(LOCAL_FABRICA)/bin/fabrica ]; then \ + echo "Local Fabrica binary not found at $(LOCAL_FABRICA)/bin/fabrica"; \ + echo "Build it with: (cd $(LOCAL_FABRICA) && go build -o bin/fabrica ./cmd/fabrica)"; \ + exit 1; \ + fi +endif + $(FABRICA_ENV) $(FABRICA_CMD) generate $(FABRICA_SOURCE_ARG) + +generate-check: ## Fail if generated files are out of sync (requires clean git tree) + @if ! git diff --quiet || ! git diff --cached --quiet; then \ + echo "Working tree must be clean before running generate-check"; \ + git --no-pager status --short; \ + exit 1; \ + fi + $(MAKE) generate LOCAL_FABRICA="$(LOCAL_FABRICA)" + @if ! git diff --quiet || ! git diff --cached --quiet; then \ + echo "Generated files are out of sync. Run 'make generate' and commit the results."; \ + git --no-pager diff --stat; \ + exit 1; \ + fi + +dev: build ## Regenerate code then build server and client binaries + +test: ## Run tests + $(GO) test $(GOFLAGS) -timeout $(TEST_TIMEOUT) -race -coverprofile=coverage.out -covermode=atomic $$(go list ./... 2>/dev/null | grep -v /demo/) + +test-integration: ## Run integration tests with explicit timeout (override with TEST_TIMEOUT=) + $(GO) test $(GOFLAGS) -timeout $(TEST_TIMEOUT) ./cmd/server -run TestDiscoverySnapshotIntegration -v + +test-coverage: test ## Run tests with coverage report + $(GO) tool cover -html=coverage.out -o coverage.html + @echo "Coverage report generated: coverage.html" + +lint: ## Run golangci-lint + golangci-lint run + +lint-fix: ## Run golangci-lint with auto-fix + golangci-lint run --fix + +clean: ## Clean build artifacts + rm -rf bin/ dist/ coverage.out coverage.html + $(GO) clean -cache + +tidy: ## Tidy go.mod + $(GO) mod tidy + +run: build ## Build and run the application + ./bin/$(BINARY_NAME) serve + +docker-build: ## Build Docker image + docker build -t fru-tracker:latest . + +docker-run: docker-build ## Build and run Docker container + docker run --rm fru-tracker:latest + +release-snapshot: ## Create a snapshot release with GoReleaser + goreleaser release --snapshot --clean + +release-test: ## Test release locally using GoReleaser snapshot (requires goreleaser) + @command -v goreleaser >/dev/null 2>&1 || { echo "goreleaser is required but not installed. Install with: 'brew install goreleaser' or 'go install github.com/goreleaser/goreleaser@latest'"; exit 1; } + @goreleaser release --snapshot --clean + +fmt: ## Format code + $(GO) fmt ./... + goimports -w . + +vet: ## Run go vet + $(GO) vet ./... + +vuln: ## Check for vulnerabilities + govulncheck ./... + +reuse: ## Check REUSE compliance + reuse lint + +reuse-spdx: ## Generate SPDX bill of materials + reuse spdx -o reuse.spdx + +reuse-install: ## Install REUSE tool + @command -v pipx >/dev/null 2>&1 || { echo "pipx is required but not installed. Install it with: python3 -m pip install --user pipx"; exit 1; } + pipx install reuse + @echo "REUSE tool installed successfully" + +reuse-annotate: ## Add REUSE headers to all files in the repository + @echo "Annotating files with REUSE headers..." + @echo "This will add SPDX headers to files that don't have them yet." +# REUSE-IgnoreStart + @read -p "Copyright holder [OpenCHAMI Contributors]: " holder; \ + holder=$${holder:-OpenCHAMI Contributors}; \ + read -p "License [MIT]: " license; \ + license=$${license:-MIT}; \ + read -p "Year [$(shell date +%Y)]: " year; \ + year=$${year:-$(shell date +%Y)}; \ + echo "Annotating with: SPDX-FileCopyrightText: $$year $$holder"; \ + echo " SPDX-License-Identifier: $$license"; \ + reuse annotate --copyright="$$holder" --license="$$license" --year="$$year" --skip-existing --recursive --skip-unrecognized . +# REUSE-IgnoreEnd + +reuse-download-license: ## Download a license file (usage: make reuse-download-license LICENSE=MIT) + @if [ -z "$(LICENSE)" ]; then \ + echo "Error: LICENSE variable is required. Usage: make reuse-download-license LICENSE=MIT"; \ + exit 1; \ + fi + reuse download $(LICENSE) + +pre-commit-install: ## Install pre-commit tool + @command -v pipx >/dev/null 2>&1 || { echo "pipx is required but not installed. Install it with: python3 -m pip install --user pipx"; exit 1; } + pipx install pre-commit + @echo "pre-commit installed successfully" + +pre-commit-setup: ## Install pre-commit hooks + @command -v pre-commit >/dev/null 2>&1 || { echo "pre-commit is not installed. Run 'make pre-commit-install' first."; exit 1; } + pre-commit install + pre-commit install --hook-type commit-msg + @echo "pre-commit hooks installed successfully" + +pre-commit-run: ## Run pre-commit hooks on all files + pre-commit run --all-files + +pre-commit-update: ## Update pre-commit hooks to latest versions + pre-commit autoupdate + +setup-dev: reuse-install pre-commit-install pre-commit-setup ## Set up development environment (install tools and hooks) + @echo "" + @echo "Development environment setup complete!" + @echo "Next steps:" + @echo " 1. Run 'make reuse-annotate' to add REUSE headers to all files" + @echo " 2. Run 'make pre-commit-run' to test pre-commit hooks" + @echo " 3. Start coding! Pre-commit hooks will run automatically on git commit" + @echo "" + @echo "Optional: Install 'act' to test GitHub Actions locally:" + @echo " brew install act" + @echo " make act-list # List available workflows" + +act-install: ## Install act (GitHub Actions local runner) via Homebrew + @command -v brew >/dev/null 2>&1 || { echo "Homebrew is required. Install from https://brew.sh"; exit 1; } + brew install act + @echo "act installed successfully" + +act-list: ## List all GitHub Actions workflows + @command -v act >/dev/null 2>&1 || { echo "act is not installed. Run 'make act-install' first."; exit 1; } + @echo "Available workflows:" + @ls -1 .github/workflows/*.yaml | sed 's/.*\// - /' + +act-test: ## Run GitHub Actions test workflow locally (ubuntu only, stable Go) + @command -v act >/dev/null 2>&1 || { echo "act is not installed. Run 'make act-install' first."; exit 1; } + @echo "Note: Testing with ubuntu-latest and stable Go version only (full matrix runs on GitHub)" + act push -W .github/workflows/test.yaml --container-architecture linux/amd64 --matrix os:ubuntu-latest --matrix go-version:stable + +act-build: ## Run GitHub Actions build workflow locally + @command -v act >/dev/null 2>&1 || { echo "act is not installed. Run 'make act-install' first."; exit 1; } + act push -W .github/workflows/build.yaml --container-architecture linux/amd64 + +act-lint: ## Run GitHub Actions golangci-lint workflow locally + @command -v act >/dev/null 2>&1 || { echo "act is not installed. Run 'make act-install' first."; exit 1; } + act push -W .github/workflows/golangci-lint.yaml --container-architecture linux/amd64 + +act-reuse: ## Run GitHub Actions REUSE workflow locally + @command -v act >/dev/null 2>&1 || { echo "act is not installed. Run 'make act-install' first."; exit 1; } + act push -W .github/workflows/reuse.yaml --container-architecture linux/amd64 + +act-vuln: ## Run GitHub Actions vulnerability check workflow locally + @command -v act >/dev/null 2>&1 || { echo "act is not installed. Run 'make act-install' first."; exit 1; } + act push -W .github/workflows/govulncheck.yaml --container-architecture linux/amd64 + +act-all: ## Run all testable workflows locally (build, test, lint, reuse, vuln) + @command -v act >/dev/null 2>&1 || { echo "act is not installed. Run 'make act-install' first."; exit 1; } + @echo "Running all testable workflows..." + @echo "\n=== Build Workflow ===" + @act -W .github/workflows/build.yaml || true + @echo "\n=== Test Workflow ===" + @act -W .github/workflows/test.yaml || true + @echo "\n=== Lint Workflow ===" + @act -W .github/workflows/golangci-lint.yaml || true + @echo "\n=== REUSE Workflow ===" + @act -W .github/workflows/reuse.yaml || true + @echo "\n=== Vulnerability Check Workflow ===" + @act -W .github/workflows/govulncheck.yaml || true + +all: clean install lint test build ## Run all checks and build + +.DEFAULT_GOAL := help \ No newline at end of file From 3634766498c17e58b9eca74a508a8881ba12f00a Mon Sep 17 00:00:00 2001 From: Alex Lovell-Troy Date: Tue, 5 May 2026 21:49:58 +0100 Subject: [PATCH 2/3] feat: Add SPDX license headers and update generated files - Added SPDX license headers to various source files, including Go files, README, and JSON files. - Updated generated files with new timestamps and license information. - Refactored integration tests to ensure proper cleanup of resources. - Improved error handling in the Redfish client. - Cleaned up unnecessary whitespace and comments in main server logic. - Updated the discovery snapshot types to include new validation rules. - Enhanced the device handlers and reconciler registration processes. Co-authored-by: Copilot Signed-off-by: Alex Lovell-Troy --- .github/workflows/release.yaml | 1 - .github/workflows/stale.yml | 2 +- .gitignore | 5 + .goreleaser.yaml | 1 - .pre-commit-config.yaml | 83 ++++++++++++ LICENSES/CC0-1.0.txt | 121 ++++++++++++++++++ LICENSES/MIT.txt | 18 +++ Makefile | 2 +- README.md | 8 +- apis.yaml | 12 ++ apis/example.fabrica.dev/v1/device_types.go | 7 +- .../v1/discoverysnapshot_types.go | 9 +- cmd/server/device_handlers_generated.go | 2 +- .../discoverysnapshot_handlers_generated.go | 2 +- cmd/server/export.go | 4 + cmd/server/import.go | 4 + cmd/server/integration_test.go | 10 +- cmd/server/main.go | 120 +++++------------ demo/README.md | 6 + demo/collector-plan.md | 8 +- demo/collector.go | 14 +- demo/main.go | 8 +- demo/models.go | 4 + fru-tracker/.gitignore | 3 + go.mod | 6 +- go.sum | 4 - go.sum.license | 3 + internal/storage/ent/annotation.go | 4 + internal/storage/ent/annotation/annotation.go | 4 + internal/storage/ent/annotation/stub.go | 4 + internal/storage/ent/annotation/where.go | 4 + internal/storage/ent/annotation_create.go | 4 + internal/storage/ent/annotation_delete.go | 4 + internal/storage/ent/annotation_query.go | 4 + internal/storage/ent/annotation_update.go | 4 + internal/storage/ent/client.go | 4 + internal/storage/ent/ent.go | 4 + internal/storage/ent/enttest/enttest.go | 4 + internal/storage/ent/hook/hook.go | 4 + internal/storage/ent/label.go | 4 + internal/storage/ent/label/label.go | 4 + internal/storage/ent/label/stub.go | 4 + internal/storage/ent/label/where.go | 4 + internal/storage/ent/label_create.go | 4 + internal/storage/ent/label_delete.go | 4 + internal/storage/ent/label_query.go | 4 + internal/storage/ent/label_update.go | 4 + internal/storage/ent/migrate/migrate.go | 4 + internal/storage/ent/migrate/schema.go | 4 + internal/storage/ent/migrate/stub.go | 4 + internal/storage/ent/mutation.go | 4 + internal/storage/ent/predicate/predicate.go | 4 + internal/storage/ent/resource.go | 4 + internal/storage/ent/resource/resource.go | 4 + internal/storage/ent/resource/stub.go | 4 + internal/storage/ent/resource/where.go | 4 + internal/storage/ent/resource_create.go | 4 + internal/storage/ent/resource_delete.go | 4 + internal/storage/ent/resource_query.go | 4 + internal/storage/ent/resource_update.go | 4 + internal/storage/ent/runtime.go | 4 + internal/storage/ent/runtime/runtime.go | 4 + internal/storage/ent/stub.go | 4 + internal/storage/ent/tx.go | 4 + internal/storage/ent_queries_generated.go | 4 + .../storage/ent_transactions_generated.go | 4 + internal/storage/storage.go | 4 + pkg/apiversion/registry_generated.go | 6 +- .../discoverysnapshot_reconciler.go | 4 + pkg/resources/register_generated.go | 11 +- upload_request.json | 2 +- upload_request.json.license | 3 + 72 files changed, 535 insertions(+), 118 deletions(-) create mode 100644 .pre-commit-config.yaml create mode 100644 LICENSES/CC0-1.0.txt create mode 100644 LICENSES/MIT.txt create mode 100644 apis.yaml create mode 100644 go.sum.license create mode 100644 upload_request.json.license diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 959c183..b407bbd 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -81,4 +81,3 @@ jobs: subject-name: ghcr.io/openchami/fru-tracker subject-digest: ${{ steps.process_goreleaser_output.outputs.digest }} push-to-registry: true - diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 5f90952..2e4247d 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -35,4 +35,4 @@ jobs: stale-pr-message: > This PR has been marked stale due to inactivity. Comment or push changes to keep it open. close-pr-message: > - Closing due to inactivity. Please reopen when it’s ready again. \ No newline at end of file + Closing due to inactivity. Please reopen when it’s ready again. diff --git a/.gitignore b/.gitignore index 67e6eaf..fad46f2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +# +# SPDX-License-Identifier: MIT # Generated by Fabrica dev # Template: init/gitignore.tmpl @@ -29,6 +32,8 @@ data/ *.yml !example.yaml !example.yml +!apis.yaml +!.pre-commit-config.yaml !.github/workflows/*.yaml !.github/workflows/*.yml !.fabrica.yaml diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 023b71e..8b8de36 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -114,4 +114,3 @@ release: footer: | --- **Full Changelog**: https://github.com/openchami/fru-tracker/compare/{{ .PreviousTag }}...{{ .Tag }} - \ No newline at end of file diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..672a3de --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,83 @@ +# SPDX-FileCopyrightText: Copyright © 2025 OpenCHAMI a Series of LF Projects, LLC +# SPDX-License-Identifier: MIT +# See https://pre-commit.com for more information +# See https://pre-commit.com/hooks.html for more hooks +repos: +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v6.0.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-yaml + - id: check-added-large-files + +- repo: https://github.com/fsfe/reuse-tool + rev: v5.1.1 + hooks: + - id: reuse-lint-file + +- repo: https://github.com/tekwizely/pre-commit-golang + # See 'pre-commit help autoupdate' + rev: v1.0.0-rc.2 + hooks: + + # Disabled go-mod-tidy in favor of custom hook below that properly excludes examples + # - id: go-mod-tidy + # exclude: '^(test/integration|examples)/' + # Disabled go-test-mod in favor of custom hook below that excludes examples + # - id: go-test-mod + # exclude: '^(test/integration|examples)/' + # Disabled go-vet-mod in favor of custom hook below that excludes examples + # - id: go-vet-mod + # exclude: '^(test/integration|examples)/' + + # + # Formatters + # + - id: go-fmt-repo + args: ["-w"] + + # + # Style Checkers + # Disabled golangci-lint-mod in favor of custom hook below that excludes examples + # - id: golangci-lint-mod + # exclude: '^(test/integration|examples)/' + +# Custom local hooks +- repo: local + hooks: + - id: go-mod-tidy-exclude-examples + name: go mod tidy (excluding examples) + # Temporarily rename examples to hide it from go mod tidy, then restore it + entry: bash -c 'if [ -d examples ]; then mv examples .examples.tmp && trap "rm -rf examples; mv .examples.tmp examples" EXIT; go mod tidy; else go mod tidy; fi' + language: system + pass_filenames: false + types: [go] + files: '^(go\.(mod|sum)|cmd/|pkg/|internal/).*' + + - id: go-vet-mod-exclude-examples + name: go vet (excluding examples) + # Temporarily rename examples to hide it from go vet, then restore it + entry: bash -c 'if [ -d examples ]; then mv examples .examples.tmp && trap "rm -rf examples; mv .examples.tmp examples" EXIT; go vet -mod=mod ./...; else go vet -mod=mod ./...; fi' + language: system + pass_filenames: false + types: [go] + files: '^(cmd/|pkg/|internal/).*\.go$' + + - id: golangci-lint-mod-exclude-examples + name: golangci-lint (excluding examples) + # Temporarily rename examples to hide it from golangci-lint, then restore it + entry: bash -c 'if [ -d examples ]; then mv examples .examples.tmp && trap "rm -rf examples; mv .examples.tmp examples" EXIT; golangci-lint run --fix=false; else golangci-lint run --fix=false; fi' + language: system + pass_filenames: false + types: [go] + files: '^(cmd/|pkg/|internal/).*\.go$' + + - id: go-test-mod-exclude-examples + name: go test (excluding examples and integration tests) + entry: bash -c 'go test -mod=readonly -race $(go list ./... 2>/dev/null | grep -v -e "/examples/" -e "/test/integration")' + language: system + pass_filenames: false + types: [go] + + # diff --git a/LICENSES/CC0-1.0.txt b/LICENSES/CC0-1.0.txt new file mode 100644 index 0000000..0e259d4 --- /dev/null +++ b/LICENSES/CC0-1.0.txt @@ -0,0 +1,121 @@ +Creative Commons Legal Code + +CC0 1.0 Universal + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS + PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM + THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED + HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without fear +of later claims of infringement build upon, modify, incorporate in other +works, reuse and redistribute as freely as possible in any form whatsoever +and for any purposes, including without limitation commercial purposes. +These owners may contribute to the Commons to promote the ideal of a free +culture and the further production of creative, cultural and scientific +works, or to gain reputation or greater distribution for their Work in +part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or she +is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under its +terms, with knowledge of his or her Copyright and Related Rights in the +Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not +limited to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, + communicate, and translate a Work; + ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or + likeness depicted in a Work; + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + v. rights protecting the extraction, dissemination, use and reuse of data + in a Work; + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation + thereof, including any amended or successor version of such + directive); and +vii. other similar, equivalent or corresponding rights throughout the + world based on applicable law or treaty, and any national + implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention +of, applicable law, Affirmer hereby overtly, fully, permanently, +irrevocably and unconditionally waives, abandons, and surrenders all of +Affirmer's Copyright and Related Rights and associated claims and causes +of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or future +medium and for any number of copies, and (iv) for any purpose whatsoever, +including without limitation commercial, advertising or promotional +purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each +member of the public at large and to the detriment of Affirmer's heirs and +successors, fully intending that such Waiver shall not be subject to +revocation, rescission, cancellation, termination, or any other legal or +equitable action to disrupt the quiet enjoyment of the Work by the public +as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason +be judged legally invalid or ineffective under applicable law, then the +Waiver shall be preserved to the maximum extent permitted taking into +account Affirmer's express Statement of Purpose. In addition, to the +extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non exclusive, +irrevocable and unconditional license to exercise Affirmer's Copyright and +Related Rights in the Work (i) in all territories worldwide, (ii) for the +maximum duration provided by applicable law or treaty (including future +time extensions), (iii) in any current or future medium and for any number +of copies, and (iv) for any purpose whatsoever, including without +limitation commercial, advertising or promotional purposes (the +"License"). The License shall be deemed effective as of the date CC0 was +applied by Affirmer to the Work. Should any part of the License for any +reason be judged legally invalid or ineffective under applicable law, such +partial invalidity or ineffectiveness shall not invalidate the remainder +of the License, and in such case Affirmer hereby affirms that he or she +will not (i) exercise any of his or her remaining Copyright and Related +Rights in the Work or (ii) assert any associated claims and causes of +action with respect to the Work, in either case contrary to Affirmer's +express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + b. Affirmer offers the Work as-is and makes no representations or + warranties of any kind concerning the Work, express, implied, + statutory or otherwise, including without limitation warranties of + title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or + the present or absence of errors, whether or not discoverable, all to + the greatest extent permissible under applicable law. + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without + limitation any person's Copyright and Related Rights in the Work. + Further, Affirmer disclaims responsibility for obtaining any necessary + consents, permissions or other rights required for any use of the + Work. + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to + this CC0 or use of the Work. diff --git a/LICENSES/MIT.txt b/LICENSES/MIT.txt new file mode 100644 index 0000000..d817195 --- /dev/null +++ b/LICENSES/MIT.txt @@ -0,0 +1,18 @@ +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the +following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial +portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO +EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/Makefile b/Makefile index 6dfdbf9..76751c1 100644 --- a/Makefile +++ b/Makefile @@ -217,4 +217,4 @@ act-all: ## Run all testable workflows locally (build, test, lint, reuse, vuln) all: clean install lint test build ## Run all checks and build -.DEFAULT_GOAL := help \ No newline at end of file +.DEFAULT_GOAL := help diff --git a/README.md b/README.md index d564346..10e71f5 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,9 @@ + + # fru-tracker YouTube Video Demo: https://www.youtube.com/watch?v=TemS6Ok1c3c @@ -159,4 +165,4 @@ The API provides a bulk endpoint via the `DiscoverySnapshot` resource. Wrap your ] } } -``` \ No newline at end of file +``` diff --git a/apis.yaml b/apis.yaml new file mode 100644 index 0000000..7db38d5 --- /dev/null +++ b/apis.yaml @@ -0,0 +1,12 @@ +# SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +# +# SPDX-License-Identifier: MIT + +groups: + - name: example.fabrica.dev + storageVersion: v1 + versions: + - v1 + resources: + - Device + - DiscoverySnapshot diff --git a/apis/example.fabrica.dev/v1/device_types.go b/apis/example.fabrica.dev/v1/device_types.go index 813f859..76b8df6 100644 --- a/apis/example.fabrica.dev/v1/device_types.go +++ b/apis/example.fabrica.dev/v1/device_types.go @@ -6,8 +6,8 @@ package v1 import ( "context" + "encoding/json" "github.com/openchami/fabrica/pkg/fabrica" - "encoding/json" ) // Device represents a device resource @@ -15,8 +15,8 @@ type Device struct { APIVersion string `json:"apiVersion"` Kind string `json:"kind"` Metadata fabrica.Metadata `json:"metadata"` - Spec DeviceSpec `json:"spec" validate:"required"` - Status DeviceStatus `json:"status,omitempty"` + Spec DeviceSpec `json:"spec" validate:"required"` + Status DeviceStatus `json:"status,omitempty"` } // DeviceSpec defines the desired state of Device @@ -52,6 +52,7 @@ func (r *Device) Validate(ctx context.Context) error { return nil } + // GetKind returns the kind of the resource func (r *Device) GetKind() string { return "Device" diff --git a/apis/example.fabrica.dev/v1/discoverysnapshot_types.go b/apis/example.fabrica.dev/v1/discoverysnapshot_types.go index 577fc12..478b01e 100644 --- a/apis/example.fabrica.dev/v1/discoverysnapshot_types.go +++ b/apis/example.fabrica.dev/v1/discoverysnapshot_types.go @@ -6,15 +6,15 @@ package v1 import ( "context" + "encoding/json" "github.com/openchami/fabrica/pkg/fabrica" - "encoding/json" ) // DiscoverySnapshot represents a discoverysnapshot resource type DiscoverySnapshot struct { - APIVersion string `json:"apiVersion"` - Kind string `json:"kind"` - Metadata fabrica.Metadata `json:"metadata"` + APIVersion string `json:"apiVersion"` + Kind string `json:"kind"` + Metadata fabrica.Metadata `json:"metadata"` Spec DiscoverySnapshotSpec `json:"spec" validate:"required"` Status DiscoverySnapshotStatus `json:"status,omitempty"` } @@ -43,6 +43,7 @@ func (r *DiscoverySnapshot) Validate(ctx context.Context) error { return nil } + // GetKind returns the kind of the resource func (r *DiscoverySnapshot) GetKind() string { return "DiscoverySnapshot" diff --git a/cmd/server/device_handlers_generated.go b/cmd/server/device_handlers_generated.go index 5a40baa..100f687 100644 --- a/cmd/server/device_handlers_generated.go +++ b/cmd/server/device_handlers_generated.go @@ -1,6 +1,6 @@ // Code generated by Fabrica dev. DO NOT EDIT. // Template: server/handlers.go.tmpl -// Generated: 2026-03-26T14:33:28-07:00 +// Generated: 2026-05-05T21:44:41+01:00 // // # Copyright © 2025 OpenCHAMI a Series of LF Projects, LLC // diff --git a/cmd/server/discoverysnapshot_handlers_generated.go b/cmd/server/discoverysnapshot_handlers_generated.go index 4f63bd5..3150ce5 100644 --- a/cmd/server/discoverysnapshot_handlers_generated.go +++ b/cmd/server/discoverysnapshot_handlers_generated.go @@ -1,6 +1,6 @@ // Code generated by Fabrica dev. DO NOT EDIT. // Template: server/handlers.go.tmpl -// Generated: 2026-03-26T14:33:28-07:00 +// Generated: 2026-05-05T21:44:41+01:00 // // # Copyright © 2025 OpenCHAMI a Series of LF Projects, LLC // diff --git a/cmd/server/export.go b/cmd/server/export.go index 3360b23..bbee3be 100644 --- a/cmd/server/export.go +++ b/cmd/server/export.go @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +// +// SPDX-License-Identifier: MIT + package main import ( diff --git a/cmd/server/import.go b/cmd/server/import.go index b3744c1..afdad3c 100644 --- a/cmd/server/import.go +++ b/cmd/server/import.go @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +// +// SPDX-License-Identifier: MIT + package main import ( diff --git a/cmd/server/integration_test.go b/cmd/server/integration_test.go index 5829300..bf419c3 100644 --- a/cmd/server/integration_test.go +++ b/cmd/server/integration_test.go @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +// +// SPDX-License-Identifier: MIT + package main import ( @@ -21,7 +25,9 @@ import ( func TestDiscoverySnapshotIntegration(t *testing.T) { // 1. Setup in-memory Ent storage for the test client := enttest.Open(t, "sqlite3", "file:ent?mode=memory&cache=shared&_fk=1") - defer client.Close() + t.Cleanup(func() { + require.NoError(t, client.Close()) + }) storage.SetEntClient(client) // 2. Register resource prefixes (required for CreateDiscoverySnapshot) @@ -35,7 +41,7 @@ func TestDiscoverySnapshotIntegration(t *testing.T) { // 4. Prepare the payload with at least one Node, one CPU, and one DIMM // Looking at apis/example.fabrica.dev/v1/device_types.go and reconcilers // DiscoverySnapshotSpec.RawData is expected to be a list of DeviceSpec - + nodeSerial := "node-001" cpuSerial := "cpu-001" dimmSerial := "dimm-001" diff --git a/cmd/server/main.go b/cmd/server/main.go index 2f28411..a2a1c11 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -1,4 +1,3 @@ - // Code generated by Fabrica dev. DO NOT EDIT. // Template: init/main.go.tmpl // Generated: 2026-02-26T11:09:26-08:00 @@ -19,38 +18,25 @@ import ( "syscall" "time" - "github.com/spf13/cobra" - "github.com/spf13/viper" + _ "github.com/example/fru-tracker/pkg/apiversion" "github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5/middleware" - _ "github.com/example/fru-tracker/pkg/apiversion" "github.com/openchami/fabrica/pkg/versioning" + "github.com/spf13/cobra" + "github.com/spf13/viper" - - - - - "github.com/example/fru-tracker/internal/storage" - - + "github.com/example/fru-tracker/internal/storage" - "github.com/example/fru-tracker/internal/storage/ent" - "github.com/example/fru-tracker/internal/storage/ent/migrate" + "github.com/example/fru-tracker/internal/storage/ent" + "github.com/example/fru-tracker/internal/storage/ent/migrate" - _ "github.com/mattn/go-sqlite3" - - - - "github.com/openchami/fabrica/pkg/events" . "github.com/example/fru-tracker/internal/middleware" - + "github.com/openchami/fabrica/pkg/events" - - "github.com/openchami/fabrica/pkg/reconcile" "github.com/example/fru-tracker/pkg/reconcilers" - + "github.com/openchami/fabrica/pkg/reconcile" ) // Config holds all configuration for the service @@ -62,23 +48,16 @@ type Config struct { WriteTimeout int `mapstructure:"write_timeout"` IdleTimeout int `mapstructure:"idle_timeout"` - // Storage Configuration - - DatabaseURL string `mapstructure:"database-url"` - - - + DatabaseURL string `mapstructure:"database-url"` - // Reconciliation Configuration ReconcileEnabled bool `mapstructure:"reconcile_enabled"` ReconcileWorkers int `mapstructure:"reconcile_workers"` - // Feature Flags - + Debug bool `mapstructure:"debug"` } @@ -90,17 +69,12 @@ func DefaultConfig() *Config { ReadTimeout: 15, WriteTimeout: 15, IdleTimeout: 60, - - - DatabaseURL: "file:./data.db?cache=shared&_fk=1", - - - - + + DatabaseURL: "file:./data.db?cache=shared&_fk=1", + ReconcileEnabled: true, ReconcileWorkers: 5, - - + Debug: false, } } @@ -144,15 +118,7 @@ func init() { serveCmd.Flags().Int("write-timeout", 15, "Write timeout in seconds") serveCmd.Flags().Int("idle-timeout", 60, "Idle timeout in seconds") - - serveCmd.Flags().String("database-url", "", "Database connection URL") - - - - - - // Bind flags to viper viper.BindPFlags(serveCmd.Flags()) @@ -160,14 +126,14 @@ func init() { // Add subcommands rootCmd.AddCommand(serveCmd) - + rootCmd.AddCommand(versionCmd) - + // Generated by Fabrica v0.4.0+: export and import commands (Ent storage only) - + rootCmd.AddCommand(newExportCommand()) rootCmd.AddCommand(newImportCommand()) - + } func initConfig() { @@ -210,9 +176,8 @@ func initConfig() { func runServer(cmd *cobra.Command, args []string) error { log.Printf("Starting fru-tracker server...") - // Initialize storage backend - + // Connect to database client, err := ent.Open("sqlite3", config.DatabaseURL) if err != nil { @@ -234,10 +199,7 @@ func runServer(cmd *cobra.Command, args []string) error { // Set Ent client for storage operations storage.SetEntClient(client) log.Printf("Ent storage initialized with sqlite3 database") - - - // Initialize event system with configuration from environment eventConfig := &events.EventConfig{ Enabled: true, @@ -263,29 +225,27 @@ func runServer(cmd *cobra.Command, args []string) error { // Initialize event bridge for condition events events.InitializeEventBridge() - // Initialize ONE event bus for handlers AND reconcilers - log.Println("Initializing single event bus...") - - eventBus := events.NewInMemoryEventBus(1000, 10) - - eventBus.Start() - defer eventBus.Close() // Defer close here, at the top level + // Initialize ONE event bus for handlers AND reconcilers + log.Println("Initializing single event bus...") + + eventBus := events.NewInMemoryEventBus(1000, 10) - // Set the global instance for handlers - // This replaces the call to InitializeEventBus() - events.SetGlobalEventBus(eventBus) - GlobalEventBus = eventBus // Set the global var from event_bus_generated.go - log.Println("Global event bus started and set.") + eventBus.Start() + defer eventBus.Close() // Defer close here, at the top level + + // Set the global instance for handlers + // This replaces the call to InitializeEventBus() + events.SetGlobalEventBus(eventBus) + GlobalEventBus = eventBus // Set the global var from event_bus_generated.go + log.Println("Global event bus started and set.") log.Printf("Event system initialized - Lifecycle: %v, Conditions: %v, Prefix: %s", eventConfig.LifecycleEventsEnabled, eventConfig.ConditionEventsEnabled, eventConfig.EventTypePrefix) - - // Initialize reconciliation controller // Note: This requires reconciliation code to be generated via 'fabrica generate' // and reconcilers to be implemented in pkg/reconcilers/ - + if config.ReconcileEnabled { ctx := context.Background() @@ -309,8 +269,6 @@ func runServer(cmd *cobra.Command, args []string) error { log.Printf("Reconciliation controller started with %d workers", 5) } - - // Register resource prefixes for UID generation // This is required before any handlers can create resources @@ -337,14 +295,10 @@ func runServer(cmd *cobra.Command, args []string) error { r.Mount("/debug", middleware.Profiler()) } - - // Register routes - generated by 'fabrica generate' RegisterGeneratedRoutes(r) r.Get("/health", healthHandler) - - // Create HTTP server addr := fmt.Sprintf("%s:%d", config.Host, config.Port) server := &http.Server{ @@ -358,12 +312,8 @@ func runServer(cmd *cobra.Command, args []string) error { // Start server in goroutine go func() { log.Printf("Server starting on %s", addr) - - + log.Printf("Storage: sqlite3 database") - - - if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed { log.Fatalf("Server failed: %v", err) @@ -397,9 +347,6 @@ func healthHandler(w http.ResponseWriter, r *http.Request) { // registerResourcePrefixes is defined in routes_generated.go - - - var versionCmd = &cobra.Command{ Use: "version", Short: "Print the version number", @@ -408,4 +355,3 @@ var versionCmd = &cobra.Command{ fmt.Println("fru-tracker v1.0.0") }, } - diff --git a/demo/README.md b/demo/README.md index e48d14b..250766c 100644 --- a/demo/README.md +++ b/demo/README.md @@ -1,3 +1,9 @@ + + # fru-tracker Extensible Collector Tutorial This tutorial demonstrates how to run the fru-tracker API locally and use GitHub Copilot to extend the provided Redfish Go collector to gather additional hardware components. diff --git a/demo/collector-plan.md b/demo/collector-plan.md index d6c0f64..0c67eb7 100644 --- a/demo/collector-plan.md +++ b/demo/collector-plan.md @@ -1,10 +1,16 @@ + + # FRU-Tracker Collector Extension Plan ## Objective Extend the existing Go Redfish collector (`demo/collector`) to gather additional data from a BMC and format it for the OpenCHAMI fru-tracker API. You will be asked to either discover entirely new hardware components or extract additional attributes for existing components. ## API Data Model Rules -The API ingests a single `DiscoverySnapshot` containing a `rawData` array of `DeviceSpec` objects. +The API ingests a single `DiscoverySnapshot` containing a `rawData` array of `DeviceSpec` objects. 1. **`DeviceType`**: Every component must have a distinct string (e.g., "Node", "CPU", "DIMM", "Drive"). 2. **`Properties.redfish_uri`**: Every device MUST include its Redfish `@odata.id` mapped to `properties["redfish_uri"]`. This acts is used by the service to determinte parent-child relations. diff --git a/demo/collector.go b/demo/collector.go index 5342554..cd3172c 100644 --- a/demo/collector.go +++ b/demo/collector.go @@ -1,8 +1,12 @@ +// SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +// +// SPDX-License-Identifier: MIT + // This file contains the complete Redfish discovery and API posting logic. package main import ( -"context" + "context" "crypto/tls" "encoding/json" "errors" @@ -120,9 +124,13 @@ func (c *RedfishClient) Get(path string) ([]byte, error) { if err != nil { return nil, fmt.Errorf("failed to execute Redfish request for %s: %w", targetURL, err) } - defer resp.Body.Close() + defer func() { + if closeErr := resp.Body.Close(); closeErr != nil { + fmt.Printf("warning: failed to close response body for %s: %v\n", targetURL, closeErr) + } + }() if resp.StatusCode != http.StatusOK { - return nil, fmt.Errorf("Redfish API returned status code %d for %s", resp.StatusCode, targetURL) + return nil, fmt.Errorf("redfish API returned status code %d for %s", resp.StatusCode, targetURL) } body, err := io.ReadAll(resp.Body) if err != nil { diff --git a/demo/main.go b/demo/main.go index 003d2ac..fcde18d 100644 --- a/demo/main.go +++ b/demo/main.go @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +// +// SPDX-License-Identifier: MIT + package main import ( @@ -18,7 +22,9 @@ var bmcIP string func init() { // Define the --ip flag for the BMC IP rootCmd.Flags().StringVarP(&bmcIP, "ip", "i", "", "The IP address of the BMC to gather inventory from (required)") - rootCmd.MarkFlagRequired("ip") + if err := rootCmd.MarkFlagRequired("ip"); err != nil { + panic(fmt.Sprintf("failed to mark required flag: %v", err)) + } } func main() { diff --git a/demo/models.go b/demo/models.go index 4284739..a223d6a 100644 --- a/demo/models.go +++ b/demo/models.go @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +// +// SPDX-License-Identifier: MIT + package main import ( diff --git a/fru-tracker/.gitignore b/fru-tracker/.gitignore index 6dc021a..b4572bd 100644 --- a/fru-tracker/.gitignore +++ b/fru-tracker/.gitignore @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +# +# SPDX-License-Identifier: MIT # Generated by Fabrica dev # Template: init/gitignore.tmpl diff --git a/go.mod b/go.mod index 803c139..befbb5a 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +// +// SPDX-License-Identifier: MIT + // Generated by Fabrica dev // Template: init/go.mod.tmpl // Generated: 2026-02-26T11:09:26-08:00 @@ -14,7 +18,6 @@ require ( github.com/go-chi/chi/v5 v5.0.10 github.com/mattn/go-sqlite3 v1.14.17 github.com/openchami/fabrica v0.4.0 - github.com/sirupsen/logrus v1.9.4 github.com/spf13/cobra v1.10.1 github.com/spf13/viper v1.16.0 github.com/stretchr/testify v1.11.1 @@ -61,7 +64,6 @@ require ( github.com/spf13/cast v1.5.1 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.10 // indirect - github.com/stretchr/objx v0.5.2 // indirect github.com/subosito/gotenv v1.4.2 // indirect github.com/woodsbury/decimal128 v1.3.0 // indirect github.com/zclconf/go-cty v1.14.4 // indirect diff --git a/go.sum b/go.sum index 80b2308..61dd252 100644 --- a/go.sum +++ b/go.sum @@ -227,8 +227,6 @@ github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99 github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= -github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w= -github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g= github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM= github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA= @@ -245,8 +243,6 @@ github.com/spf13/viper v1.16.0/go.mod h1:yg78JgCJcbrQOvV9YLXgkLaZqUidkY9K+Dd1Fof github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= -github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= diff --git a/go.sum.license b/go.sum.license new file mode 100644 index 0000000..fc515bb --- /dev/null +++ b/go.sum.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors + +SPDX-License-Identifier: MIT diff --git a/internal/storage/ent/annotation.go b/internal/storage/ent/annotation.go index 388e7c0..8854eb3 100644 --- a/internal/storage/ent/annotation.go +++ b/internal/storage/ent/annotation.go @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +// +// SPDX-License-Identifier: MIT + // Code generated by ent, DO NOT EDIT. package ent diff --git a/internal/storage/ent/annotation/annotation.go b/internal/storage/ent/annotation/annotation.go index 15b049f..b4b94fb 100644 --- a/internal/storage/ent/annotation/annotation.go +++ b/internal/storage/ent/annotation/annotation.go @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +// +// SPDX-License-Identifier: MIT + // Code generated by ent, DO NOT EDIT. package annotation diff --git a/internal/storage/ent/annotation/stub.go b/internal/storage/ent/annotation/stub.go index c7e0771..7065c2d 100644 --- a/internal/storage/ent/annotation/stub.go +++ b/internal/storage/ent/annotation/stub.go @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +// +// SPDX-License-Identifier: MIT + // Code generated by Fabrica. DO NOT EDIT manually. // This is a stub file created during init to prevent import errors. // It will be replaced when Ent generates the real schema code. diff --git a/internal/storage/ent/annotation/where.go b/internal/storage/ent/annotation/where.go index f295809..655c6c1 100644 --- a/internal/storage/ent/annotation/where.go +++ b/internal/storage/ent/annotation/where.go @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +// +// SPDX-License-Identifier: MIT + // Code generated by ent, DO NOT EDIT. package annotation diff --git a/internal/storage/ent/annotation_create.go b/internal/storage/ent/annotation_create.go index 63c2302..8a954bb 100644 --- a/internal/storage/ent/annotation_create.go +++ b/internal/storage/ent/annotation_create.go @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +// +// SPDX-License-Identifier: MIT + // Code generated by ent, DO NOT EDIT. package ent diff --git a/internal/storage/ent/annotation_delete.go b/internal/storage/ent/annotation_delete.go index b301056..46e5897 100644 --- a/internal/storage/ent/annotation_delete.go +++ b/internal/storage/ent/annotation_delete.go @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +// +// SPDX-License-Identifier: MIT + // Code generated by ent, DO NOT EDIT. package ent diff --git a/internal/storage/ent/annotation_query.go b/internal/storage/ent/annotation_query.go index e03e830..bf25f14 100644 --- a/internal/storage/ent/annotation_query.go +++ b/internal/storage/ent/annotation_query.go @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +// +// SPDX-License-Identifier: MIT + // Code generated by ent, DO NOT EDIT. package ent diff --git a/internal/storage/ent/annotation_update.go b/internal/storage/ent/annotation_update.go index 62f667e..55b839d 100644 --- a/internal/storage/ent/annotation_update.go +++ b/internal/storage/ent/annotation_update.go @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +// +// SPDX-License-Identifier: MIT + // Code generated by ent, DO NOT EDIT. package ent diff --git a/internal/storage/ent/client.go b/internal/storage/ent/client.go index da21a87..2225b7f 100644 --- a/internal/storage/ent/client.go +++ b/internal/storage/ent/client.go @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +// +// SPDX-License-Identifier: MIT + // Code generated by ent, DO NOT EDIT. package ent diff --git a/internal/storage/ent/ent.go b/internal/storage/ent/ent.go index 53a41e5..2a42b1a 100644 --- a/internal/storage/ent/ent.go +++ b/internal/storage/ent/ent.go @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +// +// SPDX-License-Identifier: MIT + // Code generated by ent, DO NOT EDIT. package ent diff --git a/internal/storage/ent/enttest/enttest.go b/internal/storage/ent/enttest/enttest.go index 093b7c0..e6663d1 100644 --- a/internal/storage/ent/enttest/enttest.go +++ b/internal/storage/ent/enttest/enttest.go @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +// +// SPDX-License-Identifier: MIT + // Code generated by ent, DO NOT EDIT. package enttest diff --git a/internal/storage/ent/hook/hook.go b/internal/storage/ent/hook/hook.go index b4782aa..dad4849 100644 --- a/internal/storage/ent/hook/hook.go +++ b/internal/storage/ent/hook/hook.go @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +// +// SPDX-License-Identifier: MIT + // Code generated by ent, DO NOT EDIT. package hook diff --git a/internal/storage/ent/label.go b/internal/storage/ent/label.go index 5197d64..dfcb8c1 100644 --- a/internal/storage/ent/label.go +++ b/internal/storage/ent/label.go @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +// +// SPDX-License-Identifier: MIT + // Code generated by ent, DO NOT EDIT. package ent diff --git a/internal/storage/ent/label/label.go b/internal/storage/ent/label/label.go index 2ee5da5..46c1bb1 100644 --- a/internal/storage/ent/label/label.go +++ b/internal/storage/ent/label/label.go @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +// +// SPDX-License-Identifier: MIT + // Code generated by ent, DO NOT EDIT. package label diff --git a/internal/storage/ent/label/stub.go b/internal/storage/ent/label/stub.go index b59f4a1..0ab0db9 100644 --- a/internal/storage/ent/label/stub.go +++ b/internal/storage/ent/label/stub.go @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +// +// SPDX-License-Identifier: MIT + // Code generated by Fabrica. DO NOT EDIT manually. // This is a stub file created during init to prevent import errors. // It will be replaced when Ent generates the real schema code. diff --git a/internal/storage/ent/label/where.go b/internal/storage/ent/label/where.go index ceef9e9..795c8b6 100644 --- a/internal/storage/ent/label/where.go +++ b/internal/storage/ent/label/where.go @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +// +// SPDX-License-Identifier: MIT + // Code generated by ent, DO NOT EDIT. package label diff --git a/internal/storage/ent/label_create.go b/internal/storage/ent/label_create.go index e42a2c1..1b16f44 100644 --- a/internal/storage/ent/label_create.go +++ b/internal/storage/ent/label_create.go @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +// +// SPDX-License-Identifier: MIT + // Code generated by ent, DO NOT EDIT. package ent diff --git a/internal/storage/ent/label_delete.go b/internal/storage/ent/label_delete.go index 5773b17..a33963f 100644 --- a/internal/storage/ent/label_delete.go +++ b/internal/storage/ent/label_delete.go @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +// +// SPDX-License-Identifier: MIT + // Code generated by ent, DO NOT EDIT. package ent diff --git a/internal/storage/ent/label_query.go b/internal/storage/ent/label_query.go index ad6e565..56d298b 100644 --- a/internal/storage/ent/label_query.go +++ b/internal/storage/ent/label_query.go @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +// +// SPDX-License-Identifier: MIT + // Code generated by ent, DO NOT EDIT. package ent diff --git a/internal/storage/ent/label_update.go b/internal/storage/ent/label_update.go index fc4bad4..3fbf5d2 100644 --- a/internal/storage/ent/label_update.go +++ b/internal/storage/ent/label_update.go @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +// +// SPDX-License-Identifier: MIT + // Code generated by ent, DO NOT EDIT. package ent diff --git a/internal/storage/ent/migrate/migrate.go b/internal/storage/ent/migrate/migrate.go index 1956a6b..9f37e93 100644 --- a/internal/storage/ent/migrate/migrate.go +++ b/internal/storage/ent/migrate/migrate.go @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +// +// SPDX-License-Identifier: MIT + // Code generated by ent, DO NOT EDIT. package migrate diff --git a/internal/storage/ent/migrate/schema.go b/internal/storage/ent/migrate/schema.go index 5c56395..c8f6c68 100644 --- a/internal/storage/ent/migrate/schema.go +++ b/internal/storage/ent/migrate/schema.go @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +// +// SPDX-License-Identifier: MIT + // Code generated by ent, DO NOT EDIT. package migrate diff --git a/internal/storage/ent/migrate/stub.go b/internal/storage/ent/migrate/stub.go index eabfecc..c6da28b 100644 --- a/internal/storage/ent/migrate/stub.go +++ b/internal/storage/ent/migrate/stub.go @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +// +// SPDX-License-Identifier: MIT + // Code generated by Fabrica. DO NOT EDIT manually. // This is a stub file created during init to prevent import errors. // It will be replaced when Ent generates the real migration code. diff --git a/internal/storage/ent/mutation.go b/internal/storage/ent/mutation.go index 283cc1e..d00948b 100644 --- a/internal/storage/ent/mutation.go +++ b/internal/storage/ent/mutation.go @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +// +// SPDX-License-Identifier: MIT + // Code generated by ent, DO NOT EDIT. package ent diff --git a/internal/storage/ent/predicate/predicate.go b/internal/storage/ent/predicate/predicate.go index 2f2e2aa..c6c2bf1 100644 --- a/internal/storage/ent/predicate/predicate.go +++ b/internal/storage/ent/predicate/predicate.go @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +// +// SPDX-License-Identifier: MIT + // Code generated by ent, DO NOT EDIT. package predicate diff --git a/internal/storage/ent/resource.go b/internal/storage/ent/resource.go index c44aae8..f0da961 100644 --- a/internal/storage/ent/resource.go +++ b/internal/storage/ent/resource.go @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +// +// SPDX-License-Identifier: MIT + // Code generated by ent, DO NOT EDIT. package ent diff --git a/internal/storage/ent/resource/resource.go b/internal/storage/ent/resource/resource.go index 6a532b1..6db85a5 100644 --- a/internal/storage/ent/resource/resource.go +++ b/internal/storage/ent/resource/resource.go @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +// +// SPDX-License-Identifier: MIT + // Code generated by ent, DO NOT EDIT. package resource diff --git a/internal/storage/ent/resource/stub.go b/internal/storage/ent/resource/stub.go index 25a5ed2..f839a55 100644 --- a/internal/storage/ent/resource/stub.go +++ b/internal/storage/ent/resource/stub.go @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +// +// SPDX-License-Identifier: MIT + // Code generated by Fabrica. DO NOT EDIT manually. // This is a stub file created during init to prevent import errors. // It will be replaced when Ent generates the real schema code. diff --git a/internal/storage/ent/resource/where.go b/internal/storage/ent/resource/where.go index efd8434..e4c7c5b 100644 --- a/internal/storage/ent/resource/where.go +++ b/internal/storage/ent/resource/where.go @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +// +// SPDX-License-Identifier: MIT + // Code generated by ent, DO NOT EDIT. package resource diff --git a/internal/storage/ent/resource_create.go b/internal/storage/ent/resource_create.go index e930195..ce812d9 100644 --- a/internal/storage/ent/resource_create.go +++ b/internal/storage/ent/resource_create.go @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +// +// SPDX-License-Identifier: MIT + // Code generated by ent, DO NOT EDIT. package ent diff --git a/internal/storage/ent/resource_delete.go b/internal/storage/ent/resource_delete.go index 1f25c0b..f4970a4 100644 --- a/internal/storage/ent/resource_delete.go +++ b/internal/storage/ent/resource_delete.go @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +// +// SPDX-License-Identifier: MIT + // Code generated by ent, DO NOT EDIT. package ent diff --git a/internal/storage/ent/resource_query.go b/internal/storage/ent/resource_query.go index d9e5db0..f62a9fd 100644 --- a/internal/storage/ent/resource_query.go +++ b/internal/storage/ent/resource_query.go @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +// +// SPDX-License-Identifier: MIT + // Code generated by ent, DO NOT EDIT. package ent diff --git a/internal/storage/ent/resource_update.go b/internal/storage/ent/resource_update.go index 1a798e1..6934c2f 100644 --- a/internal/storage/ent/resource_update.go +++ b/internal/storage/ent/resource_update.go @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +// +// SPDX-License-Identifier: MIT + // Code generated by ent, DO NOT EDIT. package ent diff --git a/internal/storage/ent/runtime.go b/internal/storage/ent/runtime.go index 5b05eab..7647760 100644 --- a/internal/storage/ent/runtime.go +++ b/internal/storage/ent/runtime.go @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +// +// SPDX-License-Identifier: MIT + // Code generated by ent, DO NOT EDIT. package ent diff --git a/internal/storage/ent/runtime/runtime.go b/internal/storage/ent/runtime/runtime.go index 93535f9..f6240a1 100644 --- a/internal/storage/ent/runtime/runtime.go +++ b/internal/storage/ent/runtime/runtime.go @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +// +// SPDX-License-Identifier: MIT + // Code generated by ent, DO NOT EDIT. package runtime diff --git a/internal/storage/ent/stub.go b/internal/storage/ent/stub.go index 0e2a668..740c182 100644 --- a/internal/storage/ent/stub.go +++ b/internal/storage/ent/stub.go @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +// +// SPDX-License-Identifier: MIT + // Code generated by Fabrica. DO NOT EDIT manually. // This is a stub file created during init to prevent import errors. // It will be replaced when Ent generates the real schema code. diff --git a/internal/storage/ent/tx.go b/internal/storage/ent/tx.go index e4e8c7c..eb28fc5 100644 --- a/internal/storage/ent/tx.go +++ b/internal/storage/ent/tx.go @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +// +// SPDX-License-Identifier: MIT + // Code generated by ent, DO NOT EDIT. package ent diff --git a/internal/storage/ent_queries_generated.go b/internal/storage/ent_queries_generated.go index 7a4eda0..d7e9283 100644 --- a/internal/storage/ent_queries_generated.go +++ b/internal/storage/ent_queries_generated.go @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +// +// SPDX-License-Identifier: MIT + package storage import ( diff --git a/internal/storage/ent_transactions_generated.go b/internal/storage/ent_transactions_generated.go index cc9b93a..fa0f238 100644 --- a/internal/storage/ent_transactions_generated.go +++ b/internal/storage/ent_transactions_generated.go @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +// +// SPDX-License-Identifier: MIT + package storage import ( diff --git a/internal/storage/storage.go b/internal/storage/storage.go index c8b4321..76e3cbd 100644 --- a/internal/storage/storage.go +++ b/internal/storage/storage.go @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +// +// SPDX-License-Identifier: MIT + // Code generated by Fabrica. DO NOT EDIT manually. // This is a stub file created during init to prevent import errors. // It will be replaced when you run 'fabrica generate --storage' diff --git a/pkg/apiversion/registry_generated.go b/pkg/apiversion/registry_generated.go index d7983fd..42ef74e 100644 --- a/pkg/apiversion/registry_generated.go +++ b/pkg/apiversion/registry_generated.go @@ -1,6 +1,10 @@ +// SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +// +// SPDX-License-Identifier: MIT + // Code generated by Fabrica dev. DO NOT EDIT. // Template: apiversion/register.gotmpl -// Generated at: 2026-03-26T14:33:28-07:00 +// Generated at: 2026-05-05T21:44:41+01:00 package apiversion diff --git a/pkg/reconcilers/discoverysnapshot_reconciler.go b/pkg/reconcilers/discoverysnapshot_reconciler.go index c09e4aa..5791aae 100644 --- a/pkg/reconcilers/discoverysnapshot_reconciler.go +++ b/pkg/reconcilers/discoverysnapshot_reconciler.go @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors +// +// SPDX-License-Identifier: MIT + package reconcilers import ( diff --git a/pkg/resources/register_generated.go b/pkg/resources/register_generated.go index 84031ad..0ee15cd 100644 --- a/pkg/resources/register_generated.go +++ b/pkg/resources/register_generated.go @@ -1,11 +1,18 @@ -// Code generated by fabrica. DO NOT EDIT. +// Code generated by Fabrica dev. DO NOT EDIT. +// Template: cmd/fabrica/generate.go:generateVersionedRegistrationCode +// Generated: 2026-05-05T15:52:42Z +// +// Copyright © 2026 OpenCHAMI a Series of LF Projects, LLC +// +// SPDX-License-Identifier: MIT + package resources import ( "fmt" - "github.com/openchami/fabrica/pkg/codegen" v1 "github.com/example/fru-tracker/apis/example.fabrica.dev/v1" + "github.com/openchami/fabrica/pkg/codegen" ) // RegisterAllResources registers all discovered resources with the generator. diff --git a/upload_request.json b/upload_request.json index 7e1835d..9273846 100644 --- a/upload_request.json +++ b/upload_request.json @@ -25,4 +25,4 @@ } ] } -} \ No newline at end of file +} diff --git a/upload_request.json.license b/upload_request.json.license new file mode 100644 index 0000000..fc515bb --- /dev/null +++ b/upload_request.json.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: 2026 OpenCHAMI Contributors + +SPDX-License-Identifier: MIT From 12c54085d34a0ef2c3f458d6d2d4dd17551e2f45 Mon Sep 17 00:00:00 2001 From: Alex Lovell-Troy Date: Tue, 5 May 2026 22:13:24 +0100 Subject: [PATCH 3/3] Update generated files and dependencies for fru_tracker API - Regenerated OpenAPI and route files with updated project name and version. - Updated Go module dependencies to latest versions, including Fabrica and Cobra. - Refactored client code to support JWT bearer token for authorization. - Updated copyright year to 2026 across all generated files. - Removed unimplemented event bus types from event bus middleware. - Enhanced comments and documentation for clarity and consistency. Signed-off-by: Alex Lovell-Troy --- Makefile | 18 ++++- cmd/client/main.go | 23 ++++-- cmd/server/device_handlers_generated.go | 6 +- .../discoverysnapshot_handlers_generated.go | 6 +- cmd/server/models_generated.go | 4 +- cmd/server/openapi_extensions.go | 47 ++++++++++++ cmd/server/openapi_generated.go | 22 +++--- cmd/server/routes_generated.go | 74 ++++++++++--------- go.mod | 22 +++--- go.sum | 41 +++++----- .../conditional_middleware_generated.go | 4 +- internal/middleware/event_bus_generated.go | 34 +-------- .../validation_middleware_generated.go | 4 +- .../versioning_middleware_generated.go | 4 +- internal/storage/ent/schema/annotation.go | 2 +- internal/storage/ent/schema/label.go | 2 +- internal/storage/ent/schema/resource.go | 2 +- internal/storage/ent_adapter.go | 2 +- internal/storage/generate.go | 2 +- internal/storage/storage_generated.go | 2 +- pkg/apiversion/registry_generated.go | 10 +-- pkg/client/client_generated.go | 45 ++++++++--- pkg/client/models_generated.go | 21 +++--- 23 files changed, 239 insertions(+), 158 deletions(-) create mode 100644 cmd/server/openapi_extensions.go diff --git a/Makefile b/Makefile index 76751c1..22d2180 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ # # SPDX-License-Identifier: MIT -.PHONY: help build test test-integration lint clean install run docker-build docker-run release-test check-no-pkg-resources-imports generate generate-check dev +.PHONY: help build test test-integration lint clean install run docker-build docker-run release-test check-no-pkg-resources-imports generate generate-check dev reuse-annotate-generated # Variables BINARY_NAME=fru-tracker-server @@ -43,6 +43,22 @@ ifneq ($(strip $(LOCAL_FABRICA)),) fi endif $(FABRICA_ENV) $(FABRICA_CMD) generate $(FABRICA_SOURCE_ARG) + $(GO) mod tidy + @$(MAKE) reuse-annotate-generated + +reuse-annotate-generated: ## Add SPDX headers to generated Go files when REUSE is installed + @if command -v reuse >/dev/null 2>&1; then \ + files=$$({ \ + find internal/storage/ent -type f -name '*.go' -print; \ + find cmd internal pkg -type f -name '*_generated.go' -print; \ + printf '%s\n' cmd/server/export.go cmd/server/import.go cmd/client/main.go; \ + } | while IFS= read -r file; do [ -f "$$file" ] && echo "$$file"; done | sort -u); \ + if [ -n "$$files" ]; then \ + reuse annotate --copyright="OpenCHAMI Contributors" --license="MIT" --year="$(shell date +%Y)" --skip-existing $$files; \ + fi; \ + else \ + echo "reuse not installed; skipping generated file annotation"; \ + fi generate-check: ## Fail if generated files are out of sync (requires clean git tree) @if ! git diff --quiet || ! git diff --cached --quiet; then \ diff --git a/cmd/client/main.go b/cmd/client/main.go index 6c84fe1..2316c4a 100644 --- a/cmd/client/main.go +++ b/cmd/client/main.go @@ -1,5 +1,5 @@ -// Code generated by codegen. DO NOT EDIT. -// Copyright © 2025 OpenCHAMI a Series of LF Projects, LLC +// Code generated by Fabrica. DO NOT EDIT. +// Copyright © 2026 OpenCHAMI a Series of LF Projects, LLC // // SPDX-License-Identifier: MIT // @@ -21,6 +21,7 @@ // --timeout Request timeout (env: FRU_TRACKER_TIMEOUT) // --output, -o Output format: table, json, yaml (env: FRU_TRACKER_OUTPUT) // --version, -v API version to request: v1, v2beta1, etc. (env: FRU_TRACKER_VERSION) +// --token JWT bearer token (env: FRU_TRACKER_TOKEN) // --config Config file path (default: ~/.fru_tracker-cli.yaml) // // Configuration sources (in order of precedence): @@ -80,11 +81,12 @@ import ( ) var ( - cfgFile string - serverURL string - timeout time.Duration - output string - apiVersion string + cfgFile string + serverURL string + timeout time.Duration + output string + apiVersion string + bearerToken string ) func main() { @@ -109,12 +111,14 @@ func init() { rootCmd.PersistentFlags().DurationVar(&timeout, "timeout", 30*time.Second, "request timeout") rootCmd.PersistentFlags().StringVarP(&output, "output", "o", "table", "output format: table, json, yaml") rootCmd.PersistentFlags().StringVarP(&apiVersion, "version", "v", "", "API version to request (e.g., v1, v2beta1)") + rootCmd.PersistentFlags().StringVar(&bearerToken, "token", "", "JWT bearer token") // Bind flags to viper viper.BindPFlag("server", rootCmd.PersistentFlags().Lookup("server")) viper.BindPFlag("timeout", rootCmd.PersistentFlags().Lookup("timeout")) viper.BindPFlag("output", rootCmd.PersistentFlags().Lookup("output")) viper.BindPFlag("version", rootCmd.PersistentFlags().Lookup("version")) + viper.BindPFlag("token", rootCmd.PersistentFlags().Lookup("token")) // Environment variable support viper.SetEnvPrefix("FRU_TRACKER") @@ -159,6 +163,11 @@ func getClient() (*client.Client, error) { c = c.WithVersion(version) } + token := viper.GetString("token") + if token != "" { + c = c.WithBearerToken(token) + } + return c, nil } diff --git a/cmd/server/device_handlers_generated.go b/cmd/server/device_handlers_generated.go index 100f687..2403d62 100644 --- a/cmd/server/device_handlers_generated.go +++ b/cmd/server/device_handlers_generated.go @@ -1,8 +1,8 @@ // Code generated by Fabrica dev. DO NOT EDIT. // Template: server/handlers.go.tmpl -// Generated: 2026-05-05T21:44:41+01:00 +// Generated: 2026-05-05T20:59:07Z // -// # Copyright © 2025 OpenCHAMI a Series of LF Projects, LLC +// # Copyright © 2026 OpenCHAMI a Series of LF Projects, LLC // // SPDX-License-Identifier: MIT // @@ -10,7 +10,7 @@ // // To modify this code: // 1. Edit the template file: pkg/codegen/templates/handlers.go.tmpl -// 2. Run 'make dev' to regenerate +// 2. Run 'fabrica generate' to regenerate // 3. Do NOT edit this file directly - changes will be lost // // Generated handlers provide: diff --git a/cmd/server/discoverysnapshot_handlers_generated.go b/cmd/server/discoverysnapshot_handlers_generated.go index 3150ce5..b555050 100644 --- a/cmd/server/discoverysnapshot_handlers_generated.go +++ b/cmd/server/discoverysnapshot_handlers_generated.go @@ -1,8 +1,8 @@ // Code generated by Fabrica dev. DO NOT EDIT. // Template: server/handlers.go.tmpl -// Generated: 2026-05-05T21:44:41+01:00 +// Generated: 2026-05-05T20:59:07Z // -// # Copyright © 2025 OpenCHAMI a Series of LF Projects, LLC +// # Copyright © 2026 OpenCHAMI a Series of LF Projects, LLC // // SPDX-License-Identifier: MIT // @@ -10,7 +10,7 @@ // // To modify this code: // 1. Edit the template file: pkg/codegen/templates/handlers.go.tmpl -// 2. Run 'make dev' to regenerate +// 2. Run 'fabrica generate' to regenerate // 3. Do NOT edit this file directly - changes will be lost // // Generated handlers provide: diff --git a/cmd/server/models_generated.go b/cmd/server/models_generated.go index eb8e7a8..baef7e8 100644 --- a/cmd/server/models_generated.go +++ b/cmd/server/models_generated.go @@ -1,5 +1,5 @@ // Code generated by Fabrica dev. DO NOT EDIT. -// Copyright © 2025 OpenCHAMI a Series of LF Projects, LLC +// Copyright © 2026 OpenCHAMI a Series of LF Projects, LLC // // SPDX-License-Identifier: MIT // @@ -8,7 +8,7 @@ // // To modify request/response models: // 1. Edit the template file: pkg/codegen/templates/models.go.tmpl -// 2. Run 'make dev' to regenerate +// 2. Run 'fabrica generate' to regenerate // 3. Do NOT edit this file directly - changes will be lost // // Generated models for each resource: diff --git a/cmd/server/openapi_extensions.go b/cmd/server/openapi_extensions.go new file mode 100644 index 0000000..3c3dbaa --- /dev/null +++ b/cmd/server/openapi_extensions.go @@ -0,0 +1,47 @@ +// Copyright © 2026 OpenCHAMI a Series of LF Projects, LLC +// +// SPDX-License-Identifier: MIT +// +// This file contains the user-editable OpenAPI extension hook. +// +// ✅ This file is safe to edit: it will NOT be overwritten by regeneration. +// +// Add any routes that are not Fabrica-generated (legacy APIs, custom endpoints, +// WireGuard, cloud-init, etc.) to registerCustomOpenAPIPaths so they appear in +// the served OpenAPI spec and Swagger UI at /openapi.json and /docs. +// +// Example: +// +// func registerCustomOpenAPIPaths(spec *openapi3.T) { +// metaDataOp := openapi3.NewOperation() +// metaDataOp.OperationID = "getMetaData" +// metaDataOp.Summary = "Cloud-init meta-data endpoint" +// metaDataOp.Tags = []string{"cloud-init"} +// metaDataOp.Responses = openapi3.NewResponses() +// metaDataOp.Responses.Set("200", &openapi3.ResponseRef{ +// Value: openapi3.NewResponse().WithDescription("YAML metadata for the requesting node"), +// }) +// spec.Paths.Set("/meta-data", &openapi3.PathItem{Get: metaDataOp}) +// } +package main + +import "github.com/getkin/kin-openapi/openapi3" + +// registerCustomOpenAPIPaths is called by GenerateOpenAPISpec after all +// Fabrica-generated resource paths have been registered. +// Add your custom / non-generated route definitions here. +func registerCustomOpenAPIPaths(spec *openapi3.T) { + // Add custom route definitions here. + // Example (uncomment and extend as needed): + // + // op := openapi3.NewOperation() + // op.OperationID = "myCustomEndpoint" + // op.Summary = "My custom endpoint" + // op.Tags = []string{"Custom"} + // op.Responses = openapi3.NewResponses() + // op.Responses.Set("200", &openapi3.ResponseRef{ + // Value: openapi3.NewResponse().WithDescription("OK"), + // }) + // spec.Paths.Set("/my-endpoint", &openapi3.PathItem{Get: op}) + _ = spec +} diff --git a/cmd/server/openapi_generated.go b/cmd/server/openapi_generated.go index 544f9fa..233a7a6 100644 --- a/cmd/server/openapi_generated.go +++ b/cmd/server/openapi_generated.go @@ -1,5 +1,5 @@ -// Code generated by codegen. DO NOT EDIT. -// Copyright © 2025 OpenCHAMI a Series of LF Projects, LLC +// Code generated by Fabrica. DO NOT EDIT. +// Copyright © 2026 OpenCHAMI a Series of LF Projects, LLC // // SPDX-License-Identifier: MIT // @@ -8,7 +8,7 @@ // // To modify OpenAPI spec: // 1. Edit the template file: pkg/codegen/templates/openapi.go.tmpl -// 2. Run 'make dev' to regenerate +// 2. Run 'fabrica generate' to regenerate // 3. Do NOT edit this file directly - changes will be lost // // OpenAPI endpoints: @@ -43,7 +43,7 @@ func ServeSwaggerUI(w http.ResponseWriter, r *http.Request) { - OpenCHAMI Inventory API Documentation + fru_tracker API Documentation