{"id":51858584,"url":"https://github.com/stuttgart-things/machinery-catalog-publisher","last_synced_at":"2026-07-24T03:31:08.187Z","repository":{"id":363412126,"uuid":"1261049704","full_name":"stuttgart-things/machinery-catalog-publisher","owner":"stuttgart-things","description":"Publishes live Crossplane resource status from machinery as Backstage Resource entities to S3/MinIO","archived":false,"fork":false,"pushed_at":"2026-07-12T01:06:30.000Z","size":57,"stargazers_count":0,"open_issues_count":4,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-07-12T03:07:26.430Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/stuttgart-things.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-06T07:09:29.000Z","updated_at":"2026-06-08T20:23:40.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/stuttgart-things/machinery-catalog-publisher","commit_stats":null,"previous_names":["stuttgart-things/machinery-catalog-publisher"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/stuttgart-things/machinery-catalog-publisher","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stuttgart-things%2Fmachinery-catalog-publisher","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stuttgart-things%2Fmachinery-catalog-publisher/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stuttgart-things%2Fmachinery-catalog-publisher/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stuttgart-things%2Fmachinery-catalog-publisher/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stuttgart-things","download_url":"https://codeload.github.com/stuttgart-things/machinery-catalog-publisher/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stuttgart-things%2Fmachinery-catalog-publisher/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35826032,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-07-20T02:08:10.276Z","status":"online","status_checked_at":"2026-07-24T02:00:07.870Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-07-24T03:31:07.038Z","updated_at":"2026-07-24T03:31:08.166Z","avatar_url":"https://github.com/stuttgart-things.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# stuttgart-things/machinery-catalog-publisher\n\nPublishes **live Crossplane resource status** as Backstage `Resource` entities to an\nS3/MinIO bucket, which a Git-side Backstage `Location` points at. It closes the loop\nbetween [`machinery`](https://github.com/stuttgart-things/machinery) (the live-cluster\ngRPC status API) and Backstage's declarative catalog.\n\n```\ncrossplane cluster\n   │  (dynamic informer)\n   ▼\nmachinery  ──gRPC WatchResources──▶  machinery-catalog-publisher  ──PUT──▶  S3 / MinIO\n(extracts ResourceStatus)             • ResourceStatus → Backstage Resource YAML\n                                      • Cache-Control: no-cache (fresh ETag per write)\n                                      • key: status/\u003cns\u003e/\u003cname\u003e.yaml\n                                              │\n                  Backstage Location (in Git) ──GET──┘  (polls each processing cycle)\n```\n\n## How it works\n\n- Opens machinery's `WatchResources` stream: the cache replays as `ADDED` (initial fill /\n  placeholders), then live `ADDED`/`MODIFIED`/`DELETED` deltas stream in.\n- Each status is rendered to a Backstage `Resource` named `\u003cname\u003e-status` (the `-status`\n  suffix avoids colliding with the Git-owned `Component`), with phase / last-updated /\n  info fields as `sthings.lab/*` annotations and a `dependencyOf` relation to the Component.\n- A periodic **resync ticker** (`interval`) does a full `GetResources` to heal anything a\n  dropped stream missed, and deletes objects whose resources have vanished.\n- Health is exposed at `/metrics` (Prometheus) and `/healthz` — the deployment-mode\n  stand-in for a CR status subresource.\n\n## Layouts\n\n- `PerResource` (default) — one object per resource at `status/\u003cns\u003e/\u003cname\u003e.yaml`; the Git\n  `Location` references each. Clean per-resource deletes.\n- `Aggregate` — a single `status/all.yaml` multi-doc; one `Location`, coarser deletes.\n\n## Configuration\n\nTwo inputs, matching the deployment model:\n\n1. **`config.yaml`** (non-secret, mounted from a ConfigMap) — see [`examples/config.yaml`](examples/config.yaml).\n2. **Connection secret** (S3/MinIO endpoint + creds + TLS trust, via `envFrom`) — see\n   [`examples/connection-secret.yaml`](examples/connection-secret.yaml). Maps onto the\n   `mc alias set` model: `S3_ALIAS` / `S3_ENDPOINT` / `S3_ACCESS_KEY` / `S3_SECRET_KEY`,\n   plus `S3_CA_BUNDLE` **or** `S3_INSECURE_SKIP_VERIFY` (set one, not both).\n\n| Env var | Purpose |\n|---|---|\n| `CONFIG_FILE` | path to config.yaml (default `/etc/publisher/config.yaml`) |\n| `METRICS_ADDR` | metrics/health listen addr (default `:8080`) |\n| `S3_ENDPOINT` / `S3_ACCESS_KEY` / `S3_SECRET_KEY` | connection secret (required) |\n| `S3_REGION` | SDK region (default `us-east-1`; MinIO ignores it) |\n| `S3_CA_BUNDLE` / `S3_CA_BUNDLE_FILE` | custom TLS trust (PEM inline or file) |\n| `S3_INSECURE_SKIP_VERIFY` | skip TLS verification (dev only) |\n\n## Run locally\n\n```bash\ngo test ./...\nCONFIG_FILE=examples/config.yaml \\\n  S3_ENDPOINT=https://minio.sthings.lab S3_ACCESS_KEY=... S3_SECRET_KEY=... \\\n  go run ./cmd/server\n```\n\n\u003e The gRPC stubs come from the [`machinery`](https://github.com/stuttgart-things/machinery)\n\u003e module (`github.com/stuttgart-things/machinery/resourceservice`). The pin is currently a\n\u003e pseudo-version of the module-path-rename commit; bump it to a tagged release once\n\u003e [machinery#85](https://github.com/stuttgart-things/machinery/pull/85) merges and ships.\n\n## Deploy (KCL)\n\n```bash\nkcl run kcl/ \\\n  -D config.namespace=machinery-catalog-publisher \\\n  -D config.bucket=backstage-status \\\n  -D config.connectionSecret=minio-homerun \\\n  -D config.machineryAddr=machinery.machinery-system.svc:50051\n```\n\n`replicas: 0` suspends the sync. With Stakater Reloader installed (`reloaderEnabled`,\ndefault on), editing the ConfigMap or connection Secret restarts the Pod automatically.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstuttgart-things%2Fmachinery-catalog-publisher","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstuttgart-things%2Fmachinery-catalog-publisher","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstuttgart-things%2Fmachinery-catalog-publisher/lists"}