release: v1.0.0 — initial LTS#15
Merged
Merged
Conversation
Eliminates all scattered os.Getenv calls outside internal/config and upgrades the logger to a structured, OTel-wired pkg/logger package. Config changes: - Expand EnvConfig with OtelConfig, StorageConfig, CORS origins, EncryptionKey, LogLevel, AutoMigrate, MaxAssetSizeBytes - Add sync.Once singleton (Init / MustGet) — all internal packages read from config.MustGet() instead of os.Getenv - All required vars validated at startup; ENCRYPTION_KEY validated for exact 32-byte length - .env.example documents every var across Go and Python sides Logger changes: - New pkg/logger package: New(), prettyCore (dev), JSON (prod), OTel bridge via otelzap, context helpers, trace annotation, Sync() - Drop pkg/utils/logger.go; all callers migrated to *zap.Logger - crypt.go: GenerateToken/DecryptToken accept key param instead of reading env — pkg/utils stays free of internal/config coupling Python worker: - Add OtelConfig dataclass and missing fields (auto_migrate, migrations_dir, log_level) to WorkerConfig - Add get_config() / init_config() lazy singleton - worker/utils/metrics.py: init_metrics accepts all OTel params explicitly instead of reading env internally Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ogger feat: centralise config singleton and replace logger with pkg/logger
- Apply AuthMiddleware to /storage and /assets route groups - Run auth before presign rate limiter to reject anonymous traffic early - Keep info and health endpoints public - Add unit tests for reject paths and userID context injection
- Invert OTEL_TLS_INSECURE default so unset means plaintext, not TLS - Add parseTLSInsecure helper: only "false" opts into TLS - Stop silent telemetry loss against the bundled plaintext collector - Add unit tests for the env-var parsing
- Use a fresh 10s context for tracer and metrics shutdown - Stop passing the cancelled serverCtx, which aborted the flush - Pass serverCtx directly to init; drop redundant alias vars
- Move docker-compose stack and observability overlay to project root - Remove obsolete deploy/docker/docker-compose.observability.yml - Write /tmp/worker_healthy sentinel for the worker container healthcheck - Update .env.example docs (compose hosts, storage providers, OTel TLS) - Add project CLAUDE.md
…ogger feat: centralise config singleton, pkg/logger, and deploy packaging
…ddleware fix(auth): register AuthMiddleware on protected routes (DEV-31)
…e-default fix(otel): default OTLP exporter to plaintext gRPC (DEV-32)
…esh-ctx fix(otel): flush telemetry on shutdown with fresh context (DEV-33)
- Stop the processor stamping assets.status=failed on every exception - Retryable failures no longer leave the asset stuck failed mid-retry - Consumer already marks failed only past the retry cap, ready on success - Add regression test asserting no failed-status write on processing error
…set-state fix(worker): let consumer own asset state on failure (DEV-34)
- Time-gate recovery via _maybe_recover and call it every consume() - Recover regardless of load instead of only on the idle path - Stop in_progress jobs from a crashed worker getting stuck under load - Sweep leftovers at startup (_last_recovery starts at 0) - Add tests for the load-path firing and the interval gate
…ob-recovery fix(worker): run stuck-job recovery on a fixed cadence (DEV-35)
- alpine builder has no `file` util, so the verify step exited 127 - ls -lh already confirms the binary exists; that is enough
ci: fix docker build failing on missing `file` util
- Move RecoveryMiddleware outermost so panics in inner middleware are caught (DEV-36) - Replace time-based request-ID chars with math/rand/v2 (unbiased, no collisions) (DEV-37) - Centralise supported MIME types in repository.SupportedMIMETypes; handler gates against it (DEV-38) - Add tests for request-ID generation and the MIME gate
fix(api): hardening batch — recovery order, request IDs, MIME allowlist
- Only RetryableException re-queues; other errors fail the job/asset immediately - Stop burning the full retry budget on permanent failures (bad type, corrupt file) - Add tests for retryable requeue vs non-retryable fail-fast
…tion fix(worker): fail fast on non-retryable exceptions (DEV-52)
- New migration 000002 for the webhook system (DEV-44) - webhook_deliveries is the outbox: status, attempts, next_attempt_at - Partial index on next_attempt_at WHERE status='pending' for the poll loop - ON DELETE CASCADE from deliveries to their registration - uuid_generate_v4 + IF NOT EXISTS to match existing schema conventions
feat(db): webhook tables migration (DEV-44)
…tion - Implement s3Storage (aws-sdk-go-v2) for AWS S3 and MinIO (DEV-48) - Add storagex.New factory; select provider from BUCKET_PROVIDER config - Neutralise GetObjectAttrs to a provider-agnostic storagex.ObjectAttrs - Add S3Config + BUCKET_NAME/S3_* env wiring; drop hardcoded "mpiper" bucket - MinIO support via S3_ENDPOINT_URL + path-style addressing - Add MinIO round-trip integration test (skips without S3_TEST_ENDPOINT) - Ignore local e2e artifacts (.env.local, .secrets, compose override)
feat(storage): S3/MinIO provider + config-driven selection (DEV-48)
Implement the S3/MinIO storage backend for the Python worker, mirroring the Go side so a single .env drives both services for local e2e. - s3.py: S3Storage(StorageX) on boto3; path-style + endpoint_url for MinIO, virtual-host URLs for AWS — public_url matches pkg/utils/storagex/s3.go - base.py/gcs.py: add public_url to the StorageX ABC + GCS impl - storage/__init__.py: get_storage(cfg) factory keyed on bucket.provider - main.py: use the factory; drop hardcoded GCS get_storage - config.py: read S3_* env vars first, BUCKET_* fallback (mirrors env.go) - images.py/videos.py: replace hardcoded storage.googleapis.com URLs with storage.public_url(key) so DB URLs are correct under MinIO - pyproject: add boto3, fix readme path, set package-mode = false Closes DEV-49 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…storage-add-storage-abc-and-s3-implementation-to feat(worker): add S3Storage provider, factory, and public_url
Set .version to 1.0.0 so CI (build-and-push + release-lts) stamps the 1.0.0 images and ldflags-embedded main.Version. Update the Go local-run fallback and pyproject version to match. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
chore(release): bump version to 1.0.0
🚀 Staging Build Successful
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
v1.0.0 — Initial LTS Release
Promotes
stagingtomasterto cut the first long-term-support build. Merging this triggersrelease-lts.yml, which builds and pushes the production LTS images to GHCR:ghcr.io/rndmcodeguy20/mpiper:1.0.0-ltsghcr.io/rndmcodeguy20/mpiper:<sha>-ltsghcr.io/rndmcodeguy20/mpiper:ltsHighlights since 0.1.0
StorageXprovider + config-driven selection (DEV-48)public_url(DEV-49)webhook_registrations/webhook_deliveriesschema (DEV-44)After merge: a
v1.0.0git tag + GitHub Release will be created, andmasterwill become the default branch.🤖 Generated with Claude Code