Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 95 additions & 0 deletions .github/workflows/pr-checks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# ABOUTME: Runs safe PR validation checks for Rust formatting, tests, and integration coverage.
# ABOUTME: Avoids exposing repository credentials to code from pull request branches.
name: PR checks

on:
pull_request:

permissions:
contents: read

jobs:
cargo-fmt:
name: cargo fmt --all --check
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
with:
persist-credentials: false
- run: rustup component add rustfmt
- run: cargo fmt --all --check

cargo-test:
name: cargo test
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
with:
persist-credentials: false
- uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
with:
cache-on-failure: "true"
- run: cargo test --workspace

integration-tests:
name: integration tests
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
with:
persist-credentials: false
- uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd
- uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f
with:
context: .
file: ./Dockerfile
tags: pkgly:test
load: true
cache-from: type=gha,scope=pkgly
cache-to: type=gha,scope=pkgly,mode=max
- uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f
with:
context: ./tests/docker
file: ./tests/docker/Dockerfile.test-runner
tags: pkgly-test-runner:ci
load: true
cache-from: type=gha,scope=test-runner
cache-to: type=gha,scope=test-runner,mode=max
- run: ./tests/run_integration_tests.sh
env:
PKGLY_INTEGRATION_COMPOSE_OVERRIDE: ${{ github.workspace }}/tests/docker/docker-compose.ci-cache.yml

chart-changes:
name: detect chart changes
runs-on: ubuntu-24.04
outputs:
changed: ${{ steps.changes.outputs.changed }}
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
persist-credentials: false
- id: changes
run: |
set +e
git diff --quiet "${{ github.event.pull_request.base.sha }}" "${{ github.event.pull_request.head.sha }}" -- charts/
status=$?
set -e

case "$status" in
0) echo "changed=false" >> "$GITHUB_OUTPUT" ;;
1) echo "changed=true" >> "$GITHUB_OUTPUT" ;;
*) exit "$status" ;;
esac

helm-lint:
name: helm lint and unit
needs: chart-changes
if: needs.chart-changes.outputs.changed == 'true'
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
with:
persist-credentials: false
- run: ./charts/pkgly/tests/unit.sh
7 changes: 2 additions & 5 deletions charts/pkgly/Chart.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,5 @@ dependencies:
- name: postgresql
repository: https://charts.bitnami.com/bitnami
version: 18.1.8
- name: jaeger
repository: https://jaegertracing.github.io/helm-charts
version: 3.4.1
digest: sha256:ba00edc6e27519de3e596b6c6b46a3d9855383b344d7537d5620a36573189c88
generated: "2025-11-09T10:43:52.239090332+01:00"
digest: sha256:18ae170b87964c4d42c923aace1bdcce6bc990f55bf62dd4ff51fc1cc966a579
generated: "2026-06-14T16:40:59.09543+02:00"
10 changes: 3 additions & 7 deletions charts/pkgly/Chart.yaml
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
# ABOUTME: Helm chart metadata for Pkgly - Universal artifact repository.
# ABOUTME: Defines chart version, dependencies (PostgreSQL, Jaeger), and metadata.
# ABOUTME: Defines chart version, optional PostgreSQL dependency, and metadata.
apiVersion: v2
appVersion: 3.0.0-BETA
appVersion: 1.0.0-BETA
dependencies:
- condition: postgresql.enabled
name: postgresql
repository: https://charts.bitnami.com/bitnami
version: 18.1.8
- condition: jaeger.enabled
name: jaeger
repository: https://jaegertracing.github.io/helm-charts
version: 3.4.1
description: Pkgly - Universal artifact repository supporting various packages
home: https://github.com/kshcherban/pkgly
keywords:
Expand All @@ -29,4 +25,4 @@ name: pkgly
sources:
- https://github.com/kshcherban/pkgly
type: application
version: 0.4.0
version: 0.5.0
63 changes: 40 additions & 23 deletions charts/pkgly/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ This Helm chart deploys Pkgly, a universal artifact repository supporting Docker
- **Multi-protocol support**: HTTP, OCI, and native package manager protocols
- **Repository types**: Docker, Go proxy, Maven, NPM, PHP Composer, Python PyPI, Helm charts
- **Database**: PostgreSQL (included as dependency)
- **Tracing**: Jaeger integration (optional)
- **Tracing**: OpenTelemetry export to an operator-managed collector
- **Storage**: Local filesystem (with PVC support)
- **Security**: Security contexts, resource limits, health checks
- **Ingress**: Nginx ingress support with large file upload handling
Expand All @@ -25,11 +25,11 @@ Add the repository and install the chart:
```bash
# Install dependencies
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo add jaegertracing https://jaegertracing.github.io/helm-charts
helm repo update

# Install the chart
helm install my-pkgly ./pkgly-chart
helm dependency build ./charts/pkgly
helm install my-pkgly ./charts/pkgly
```

## Uninstalling the Chart
Expand All @@ -45,29 +45,26 @@ See `values.yaml` for configuration options. The following table shows the confi
| Parameter | Description | Default |
|-----------|-------------|---------|
| `replicaCount` | Number of Pkgly replicas | `1` |
| `image.repository` | Container image repository | `ghcr.io/sudoers/pkgly` |
| `image.repository` | Container image repository | `ghcr.io/pkgly/pkgly` |
| `image.tag` | Container image tag | `latest` |
| `service.type` | Kubernetes service type | `ClusterIP` |
| `service.port` | Service port | `6742` |
| `ingress.enabled` | Enable ingress | `false` |
| `postgresql.enabled` | Deploy PostgreSQL | `true` |
| `jaeger.enabled` | Deploy Jaeger for tracing | `false` |
| `opentelemetry.endpoint` | Operator-managed OTLP collector endpoint | `http://otel-collector.observability.svc:4317` |
| `persistence.enabled` | Enable persistent storage | `true` |
| `persistence.size` | Storage size | `10Gi` |
| `rustLog` | Rust log level | `info` |
| `env` | Custom environment variables with secret support | `[]` |
| `externalDatabase.secretRef.enabled` | Use secret for external database URL | `false` |
| `externalDatabase.secretRef.enabled` | Use a Secret for the external database password | `false` |

### Development Mode
### OpenTelemetry

For development with Jaeger tracing enabled:
Jaeger is not installed by this chart. Deploy an OpenTelemetry collector or Jaeger separately, then configure its OTLP endpoint:

```yaml
tracing:
opentelemetry:
enabled: true
jaeger:
enabled: true
rustLog: "debug"
endpoint: "http://otel-collector.observability.svc:4317"
```

### Production Mode
Expand All @@ -94,43 +91,54 @@ postgresql:

## Persistence

The chart uses a PersistentVolumeClaim for storing repository data. The PVC is created by default and uses the default storage class.
The chart uses a PersistentVolumeClaim for repository data, sessions, staging files, and extracted frontend assets. The PVC is created by default and uses the default storage class. Helm upgrades and pod restarts reuse the same claim.

The bundled PostgreSQL dependency also enables its own PersistentVolumeClaim by default.

The liveness probe calls `GET /health`. Pkgly exposes this endpoint after application startup and database initialization complete.

## Database

By default, the chart deploys PostgreSQL as a dependency. You can disable it and use an external database:

### External Database with Secret (Recommended)
### External Database with Secret

For production environments, use a Kubernetes secret to store the database URL:
Disable the bundled dependency and provide connection fields. Use a Kubernetes Secret for the password:

```yaml
postgresql:
enabled: false
externalDatabase:
host: postgres.database.svc
port: 5432
user: pkgly
database: pkgly
secretRef:
enabled: true
name: database-secret
key: url
optional: false
passwordKey: password
```

Create the secret:

```bash
kubectl create secret generic database-secret \
--from-literal=url="postgresql://user:password@host:5432/database"
--from-literal=password="replace-me"
```

### External Database with Direct URL
### External Database with Direct Password

For development environments:

```yaml
postgresql:
enabled: false
externalDatabase:
url: "postgresql://user:password@host:5432/database"
host: postgres.database.svc
port: 5432
user: pkgly
password: pkgly
database: pkgly
secretRef:
enabled: false
```
Expand Down Expand Up @@ -170,7 +178,6 @@ env:

- **Web UI**: `http://<service-name>.<namespace>.svc.cluster.local:6742`
- **API**: Same URL, with appropriate endpoints
- **Default credentials**: `admin` / `admin123` (change `adminPassword` in production)

## Repository URLs

Expand All @@ -188,6 +195,16 @@ Once deployed, repositories are accessible at:
helm upgrade my-pkgly ./pkgly-chart
```

## Testing

The chart test suite expects a local kind cluster named `kind`, the default namespace, and a local `pkgly:test` image:

```bash
./charts/pkgly/tests/run.sh
```

Override the image or cluster with `PKGLY_TEST_IMAGE_REPOSITORY`, `PKGLY_TEST_IMAGE_TAG`, or `PKGLY_KIND_CLUSTER`.

## Contributing

This chart is part of the Pkgly project. Please submit issues and PRs to the main repository.
This chart is part of the Pkgly project. Please submit issues and PRs to the main repository.
37 changes: 8 additions & 29 deletions charts/pkgly/templates/configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,24 +14,10 @@ data:
# ==========================================================================
# Database Configuration
# ==========================================================================
{{- if and (not .Values.postgresql.enabled) (not .Values.externalDatabase.secretRef.enabled) }}
[database]
{{- if .Values.postgresql.enabled }}
user = {{ .Values.postgresql.auth.username | quote }}
{{- if .Values.postgresql.auth.existingSecret }}
password = "${DB_PASSWORD}"
{{- else }}
password = {{ .Values.postgresql.auth.password | quote }}
{{- end }}
database = {{ .Values.postgresql.auth.database | quote }}
host = "{{ include "pkgly-chart.fullname" . }}-postgresql"
port = 5432
{{- else }}
user = {{ .Values.externalDatabase.user | quote }}
{{- if .Values.externalDatabase.secretRef.enabled }}
password = "${DB_PASSWORD}"
{{- else }}
password = {{ .Values.externalDatabase.password | quote }}
{{- end }}
database = {{ .Values.externalDatabase.database | quote }}
host = {{ .Values.externalDatabase.host | quote }}
port = {{ .Values.externalDatabase.port }}
Expand All @@ -43,9 +29,7 @@ data:
[web_server]
bind_address = "0.0.0.0:{{ .Values.service.port }}"
open_api_routes = {{ .Values.webServer.openApiRoutes }}

[web_server.max_upload]
max_size = {{ .Values.webServer.maxUpload | quote }}
max_upload = {{ .Values.webServer.maxUpload | quote }}

# ==========================================================================
# Session Configuration
Expand All @@ -58,13 +42,14 @@ data:
# ==========================================================================
# Site Configuration
# ==========================================================================
{{- if .Values.site.appUrl }}
[site]
app_url = {{ .Values.site.appUrl | quote }}
{{- with .Values.site.appUrl }}
app_url = {{ . | quote }}
{{- end }}
name = {{ .Values.site.name | quote }}
description = {{ .Values.site.description | quote }}
is_https = {{ .Values.site.isHttps }}
{{- end }}
frontend_path = {{ .Values.site.frontendPath | quote }}

# ==========================================================================
# Security Configuration
Expand Down Expand Up @@ -95,10 +80,8 @@ data:
# Staging Configuration
# ==========================================================================
[staging]
enabled = {{ .Values.staging.enabled }}
max_size = {{ .Values.staging.maxSize | quote }}
cleanup_interval = {{ .Values.staging.cleanupInterval }}
stale_timeout = {{ .Values.staging.staleTimeout }}
staging_dir = {{ .Values.staging.stagingDir | quote }}
time_till_cleanup = {{ .Values.staging.timeTillCleanup }}

# ==========================================================================
# S3 Storage Configuration
Expand Down Expand Up @@ -134,11 +117,7 @@ data:
[opentelemetry]
enabled = true
protocol = {{ .Values.opentelemetry.protocol | quote }}
{{- if .Values.jaeger.enabled }}
endpoint = "http://{{ include "pkgly-chart.fullname" . }}-jaeger-collector:4317"
{{- else }}
endpoint = {{ .Values.opentelemetry.endpoint | quote }}
{{- end }}
traces = {{ .Values.opentelemetry.traces }}
logs = {{ .Values.opentelemetry.logs }}

Expand Down
Loading