diff --git a/.github/workflows/deployments.yml b/.github/workflows/deployments.yml deleted file mode 100644 index c06a3f4..0000000 --- a/.github/workflows/deployments.yml +++ /dev/null @@ -1,136 +0,0 @@ -name: Deployments -permissions: - contents: write - id-token: write - -on: - workflow_dispatch: - push: - branches: - - main - paths-ignore: - - 'deployment/**' - -env: - IMAGE_REGISTRY: us-west1-docker.pkg.dev/plainsightai-prod/oci - -jobs: - build: - runs-on: ${{ matrix.platform.runner }} - strategy: - fail-fast: false - matrix: - image: - - name: openfilter-pipelines-controller - context: . - dockerfile: Dockerfile - - name: openfilter-pipelines-claimer - context: . - dockerfile: cmd/claimer/Dockerfile - platform: - - arch: amd64 - runner: blacksmith-2vcpu-ubuntu-2404 - - arch: arm64 - runner: blacksmith-2vcpu-ubuntu-2204-arm - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Authenticate to Google Cloud - uses: PlainsightAI/gh-actions-public/google-cloud-auth@main - with: - environment: production - - - name: Configure Docker for GAR - shell: bash - run: gcloud auth configure-docker us-west1-docker.pkg.dev --quiet - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v4 - - - name: Build and push by digest - id: build - uses: docker/build-push-action@v6 - with: - context: ${{ matrix.image.context }} - file: ${{ matrix.image.dockerfile }} - platforms: linux/${{ matrix.platform.arch }} - cache-from: type=gha,scope=${{ matrix.image.name }}-${{ matrix.platform.arch }} - cache-to: type=gha,mode=max,scope=${{ matrix.image.name }}-${{ matrix.platform.arch }} - outputs: type=image,name=${{ env.IMAGE_REGISTRY }}/${{ matrix.image.name }},push-by-digest=true,name-canonical=true,push=true - - - name: Export digest - run: | - mkdir -p /tmp/digests - digest="${{ steps.build.outputs.digest }}" - touch "/tmp/digests/${digest#sha256:}" - - - name: Upload digest - uses: actions/upload-artifact@v4 - with: - name: digests-${{ matrix.image.name }}-${{ matrix.platform.arch }} - path: /tmp/digests/* - if-no-files-found: error - retention-days: 1 - - merge: - needs: build - runs-on: blacksmith-2vcpu-ubuntu-2404 - strategy: - fail-fast: false - matrix: - image: - - openfilter-pipelines-controller - - openfilter-pipelines-claimer - steps: - - name: Download digests - uses: actions/download-artifact@v4 - with: - path: /tmp/digests - pattern: digests-${{ matrix.image }}-* - merge-multiple: true - - - name: Authenticate to Google Cloud - uses: PlainsightAI/gh-actions-public/google-cloud-auth@main - with: - environment: production - - - name: Configure Docker for GAR - shell: bash - run: gcloud auth configure-docker us-west1-docker.pkg.dev --quiet - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v4 - - - name: Create multi-arch manifest - working-directory: /tmp/digests - run: | - docker buildx imagetools create \ - --tag "${IMAGE_REGISTRY}/${{ matrix.image }}:${{ github.sha }}" \ - $(printf "${IMAGE_REGISTRY}/${{ matrix.image }}@sha256:%s " *) - - - name: Inspect manifest - run: | - docker buildx imagetools inspect \ - "${IMAGE_REGISTRY}/${{ matrix.image }}:${{ github.sha }}" - - deploy: - needs: merge - uses: PlainsightAI/gh-actions-public/.github/workflows/deploy-service.yaml@main - with: - service-name: openfilter-pipelines-controller - manifests-path: deployment - secrets: - GH_BOT_USER_PAT: ${{ secrets.GH_BOT_USER_PAT }} - - deploy-lab: - needs: deploy - runs-on: ubuntu-latest - steps: - - name: Deploy to Lab - uses: PlainsightAI/gh-actions-public/deploy-env@main - with: - environment: lab - service-name: openfilter-pipelines-controller - manifests-path: deployment - gh-bot-user-pat: ${{ secrets.GH_BOT_USER_PAT }} diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml new file mode 100644 index 0000000..2f5f640 --- /dev/null +++ b/.github/workflows/docker-publish.yml @@ -0,0 +1,215 @@ +name: Build and Push Docker Image + +on: + workflow_dispatch: + push: + branches: [main] + tags: ["v*.*.*"] + paths-ignore: + - "deployment/**" + pull_request: + branches: [main] + paths-ignore: + - "deployment/**" + +permissions: + contents: write + id-token: write + +env: + DOCKERHUB_USERNAME: plainsightai + +jobs: + build-and-push: + strategy: + fail-fast: false + matrix: + image: + - { name: openfilter-pipelines-controller, dockerfile: Dockerfile, context: . } + - { name: openfilter-pipelines-claimer, dockerfile: cmd/claimer/Dockerfile, context: . } + arch: + - { name: amd64, runner: blacksmith-2vcpu-ubuntu-2404 } + - { name: arm64, runner: blacksmith-2vcpu-ubuntu-2204-arm } + runs-on: ${{ matrix.arch.runner }} + permissions: + contents: read + steps: + - name: Validate secrets configuration + if: github.event_name != 'pull_request' + run: | + if [ -z "${{ secrets.DOCKERHUB_ACCESS_TOKEN }}" ]; then + echo "ERROR: DOCKERHUB_ACCESS_TOKEN secret not configured" + echo "Add secret via: Settings > Secrets and variables > Actions" + exit 1 + fi + + - name: Checkout code + uses: actions/checkout@v6 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v4 + + - name: Log in to DockerHub + if: github.event_name != 'pull_request' + uses: docker/login-action@v4 + with: + username: ${{ env.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN }} + + - name: Extract image labels + id: meta + uses: docker/metadata-action@v6 + with: + images: plainsightai/${{ matrix.image.name }} + + - name: Build and push image by digest + id: build + uses: docker/build-push-action@v7 + with: + context: ${{ matrix.image.context }} + file: ${{ matrix.image.dockerfile }} + platforms: linux/${{ matrix.arch.name }} + labels: ${{ steps.meta.outputs.labels }} + outputs: type=image,name=plainsightai/${{ matrix.image.name }},push-by-digest=true,name-canonical=true,push=${{ github.event_name != 'pull_request' }} + cache-from: type=gha,scope=${{ matrix.image.name }}-${{ matrix.arch.name }} + cache-to: type=gha,mode=max,scope=${{ matrix.image.name }}-${{ matrix.arch.name }} + + - name: Export digest + if: github.event_name != 'pull_request' + run: | + mkdir -p /tmp/digests + digest="${{ steps.build.outputs.digest }}" + touch "/tmp/digests/${digest#sha256:}" + + - name: Upload digest + if: github.event_name != 'pull_request' + uses: actions/upload-artifact@v4 + with: + name: digests-${{ matrix.image.name }}-${{ matrix.arch.name }} + path: /tmp/digests/* + if-no-files-found: error + retention-days: 1 + + merge: + needs: build-and-push + if: github.event_name != 'pull_request' + runs-on: blacksmith-2vcpu-ubuntu-2404 + permissions: + contents: read + strategy: + fail-fast: false + matrix: + image: + - openfilter-pipelines-controller + - openfilter-pipelines-claimer + steps: + - name: Validate secrets configuration + run: | + if [ -z "${{ secrets.DOCKERHUB_ACCESS_TOKEN }}" ]; then + echo "ERROR: DOCKERHUB_ACCESS_TOKEN secret not configured" + echo "Add secret via: Settings > Secrets and variables > Actions" + exit 1 + fi + + - name: Download digests + uses: actions/download-artifact@v4 + with: + path: /tmp/digests + pattern: digests-${{ matrix.image }}-* + merge-multiple: true + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v4 + + - name: Log in to DockerHub + uses: docker/login-action@v4 + with: + username: ${{ env.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN }} + + - name: Extract metadata (tags) + id: meta + uses: docker/metadata-action@v6 + with: + images: plainsightai/${{ matrix.image }} + tags: | + type=ref,event=pr + type=sha,format=long,prefix= + type=semver,pattern={{version}} + type=raw,value=latest,enable=${{ startsWith(github.ref, 'refs/tags/v') }} + + - name: Create multi-arch manifest + working-directory: /tmp/digests + run: | + docker buildx imagetools create \ + $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ + $(printf 'plainsightai/${{ matrix.image }}@sha256:%s ' *) + + - name: Inspect image + run: | + docker buildx imagetools inspect plainsightai/${{ matrix.image }}:${{ steps.meta.outputs.version }} + + publish-chart: + needs: merge + if: startsWith(github.ref, 'refs/tags/v') + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Extract version + id: version + run: echo "version=${GITHUB_REF_NAME#v}" >> $GITHUB_OUTPUT + + - name: Set up Helm + uses: azure/setup-helm@v5 + + - name: Add chart dependency repos + run: | + helm repo add bitnami https://charts.bitnami.com/bitnami + helm repo update + + - name: Update Helm dependencies + run: | + cd deployment/openfilter-pipelines-controller + helm dependency update + + - name: Log in to DockerHub (Helm OCI) + run: echo "${{ secrets.DOCKERHUB_ACCESS_TOKEN }}" | helm registry login registry-1.docker.io -u ${{ env.DOCKERHUB_USERNAME }} --password-stdin + + - name: Package Helm chart + run: | + helm package deployment/openfilter-pipelines-controller \ + --version ${{ steps.version.outputs.version }} \ + --app-version ${{ steps.version.outputs.version }} + + - name: Push Helm chart to DockerHub OCI + run: | + helm push openfilter-pipelines-controller-${{ steps.version.outputs.version }}.tgz \ + oci://registry-1.docker.io/plainsightai + + deploy: + needs: merge + if: github.ref == 'refs/heads/main' + uses: PlainsightAI/gh-actions-public/.github/workflows/deploy-service.yaml@main + with: + service-name: openfilter-pipelines-controller + manifests-path: deployment + secrets: inherit + + deploy-lab: + needs: deploy + if: github.ref == 'refs/heads/main' + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - name: Deploy to Lab + uses: PlainsightAI/gh-actions-public/deploy-env@main + with: + environment: lab + service-name: openfilter-pipelines-controller + manifests-path: deployment + gh-bot-user-pat: ${{ secrets.GH_BOT_USER_PAT }} diff --git a/Makefile b/Makefile index 9fb8814..ca738ad 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,13 @@ -# Image URL to use all building/pushing image targets. -# IMAGE_REGISTRY is empty by default so `make docker-build` / `make publish-image` -# produce plain, locally-taggable images for OSS contributors. CI (the -# publish-docker-image reusable action) sets IMAGE_REGISTRY — or IMG/CLAIMER_IMG -# directly — via env to push to the Plainsight registry. -IMAGE_REGISTRY ?= +# Image URLs to use for all building/pushing image targets. +# Defaults pin to Docker Hub under the plainsightai org — that is where both +# images are published from the docker-publish.yml workflow and where +# image-policy-applier looks up tags for the env overrides. Override IMG / +# CLAIMER_IMG directly if you need to push elsewhere. +IMAGE = plainsightai/openfilter-pipelines-controller +CLAIMER_IMAGE = plainsightai/openfilter-pipelines-claimer VERSION ?= $(shell git rev-parse --short HEAD) -IMG ?= $(if $(IMAGE_REGISTRY),$(IMAGE_REGISTRY)/)openfilter-pipelines-controller:$(VERSION) -CLAIMER_IMG ?= $(if $(IMAGE_REGISTRY),$(IMAGE_REGISTRY)/)openfilter-pipelines-claimer:$(VERSION) +IMG ?= $(IMAGE):$(VERSION) +CLAIMER_IMG ?= $(CLAIMER_IMAGE):$(VERSION) # Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set) ifeq (,$(shell go env GOBIN)) diff --git a/deployment/openfilter-pipelines-controller/README.md b/deployment/openfilter-pipelines-controller/README.md index 834bd94..75e6dbe 100644 --- a/deployment/openfilter-pipelines-controller/README.md +++ b/deployment/openfilter-pipelines-controller/README.md @@ -9,10 +9,29 @@ A Kubernetes operator for managing Pipeline custom resources in the `filter.plai ## Installation -The chart is not published to a Helm repository. Install it from this -repository's local copy under `deployment/openfilter-pipelines-controller`. +### Install from Docker Hub (recommended) -### Install from local chart +The chart is published as an OCI artifact to Docker Hub. Helm 3.8+ supports OCI +directly — no `helm repo add` is needed: + +```bash +helm install openfilter-pipelines-controller \ + oci://registry-1.docker.io/plainsightai/openfilter-pipelines-controller \ + --version +``` + +Replace `` with the desired release (e.g. `0.5.2`); the published +tags match the git tags on this repository (`vX.Y.Z` → chart `X.Y.Z`). + +Container images: +[`plainsightai/openfilter-pipelines-controller`](https://hub.docker.com/r/plainsightai/openfilter-pipelines-controller) +and +[`plainsightai/openfilter-pipelines-claimer`](https://hub.docker.com/r/plainsightai/openfilter-pipelines-claimer). + +### Install from a local chart copy + +You can also install directly from this repository's local copy under +`deployment/openfilter-pipelines-controller`. ```bash # Install with default values diff --git a/deployment/openfilter-pipelines-controller/overrides/development.yaml b/deployment/openfilter-pipelines-controller/overrides/development.yaml index c8e50ac..33e2d12 100644 --- a/deployment/openfilter-pipelines-controller/overrides/development.yaml +++ b/deployment/openfilter-pipelines-controller/overrides/development.yaml @@ -1,8 +1,8 @@ image: - repository: us-west1-docker.pkg.dev/plainsightai-prod/oci/openfilter-pipelines-controller + repository: plainsightai/openfilter-pipelines-controller tag: "62146d3f171083e027f2638fee27db767d50b4ff" # {"$imagepolicy": "development:openfilter-pipelines-controller:tag"} claimerImage: - repository: us-west1-docker.pkg.dev/plainsightai-prod/oci/openfilter-pipelines-claimer + repository: plainsightai/openfilter-pipelines-claimer tag: "62146d3f171083e027f2638fee27db767d50b4ff" # {"$imagepolicy": "development:openfilter-pipelines-controller:tag"} telemetry: exporterType: otlp diff --git a/deployment/openfilter-pipelines-controller/overrides/lab.yaml b/deployment/openfilter-pipelines-controller/overrides/lab.yaml index 5d317cd..3640d17 100644 --- a/deployment/openfilter-pipelines-controller/overrides/lab.yaml +++ b/deployment/openfilter-pipelines-controller/overrides/lab.yaml @@ -1,8 +1,8 @@ image: - repository: us-west1-docker.pkg.dev/plainsightai-prod/oci/openfilter-pipelines-controller + repository: plainsightai/openfilter-pipelines-controller tag: "62146d3f171083e027f2638fee27db767d50b4ff" # {"$imagepolicy": "lab:openfilter-pipelines-controller:tag"} claimerImage: - repository: us-west1-docker.pkg.dev/plainsightai-prod/oci/openfilter-pipelines-claimer + repository: plainsightai/openfilter-pipelines-claimer tag: "62146d3f171083e027f2638fee27db767d50b4ff" # {"$imagepolicy": "lab:openfilter-pipelines-controller:tag"} telemetry: # Lab has no monitoring overlay (no controllers/monitoring/overrides/lab.yaml), diff --git a/deployment/openfilter-pipelines-controller/overrides/production.yaml b/deployment/openfilter-pipelines-controller/overrides/production.yaml index 00a328c..8355e11 100644 --- a/deployment/openfilter-pipelines-controller/overrides/production.yaml +++ b/deployment/openfilter-pipelines-controller/overrides/production.yaml @@ -1,8 +1,8 @@ image: - repository: us-west1-docker.pkg.dev/plainsightai-prod/oci/openfilter-pipelines-controller + repository: plainsightai/openfilter-pipelines-controller tag: "62146d3f171083e027f2638fee27db767d50b4ff" # {"$imagepolicy": "production:openfilter-pipelines-controller:tag"} claimerImage: - repository: us-west1-docker.pkg.dev/plainsightai-prod/oci/openfilter-pipelines-claimer + repository: plainsightai/openfilter-pipelines-claimer tag: "62146d3f171083e027f2638fee27db767d50b4ff" # {"$imagepolicy": "production:openfilter-pipelines-controller:tag"} resources: requests: diff --git a/deployment/openfilter-pipelines-controller/overrides/staging.yaml b/deployment/openfilter-pipelines-controller/overrides/staging.yaml index 2041a54..04145b8 100644 --- a/deployment/openfilter-pipelines-controller/overrides/staging.yaml +++ b/deployment/openfilter-pipelines-controller/overrides/staging.yaml @@ -1,8 +1,8 @@ image: - repository: us-west1-docker.pkg.dev/plainsightai-prod/oci/openfilter-pipelines-controller + repository: plainsightai/openfilter-pipelines-controller tag: "62146d3f171083e027f2638fee27db767d50b4ff" # {"$imagepolicy": "staging:openfilter-pipelines-controller:tag"} claimerImage: - repository: us-west1-docker.pkg.dev/plainsightai-prod/oci/openfilter-pipelines-claimer + repository: plainsightai/openfilter-pipelines-claimer tag: "62146d3f171083e027f2638fee27db767d50b4ff" # {"$imagepolicy": "staging:openfilter-pipelines-controller:tag"} telemetry: exporterType: otlp