Skip to content

🤖 ci: add OCI image labels and Apache-2.0 license#57

Merged
ThomasK33 merged 1 commit into
mainfrom
docker-ng55
Feb 12, 2026
Merged

🤖 ci: add OCI image labels and Apache-2.0 license#57
ThomasK33 merged 1 commit into
mainfrom
docker-ng55

Conversation

@ThomasK33
Copy link
Copy Markdown
Member

@ThomasK33 ThomasK33 commented Feb 12, 2026

Summary

This PR adds standard OCI image metadata labels to publish-time container images and introduces an explicit Apache-2.0 repository license.

Background

Published images should expose canonical source/version/license metadata for registries and supply-chain tooling. The repository also needed an explicit license file and matching image license annotation.

Implementation

  • Added a root LICENSE file with Apache License 2.0 text.
  • Added a README license section linking to LICENSE.
  • Updated .goreleaser.yaml to inject OCI labels for release images via build_flag_templates.
  • Updated the publish-main job in .github/workflows/ci.yaml to compute an RFC3339 UTC timestamp and pass OCI labels to docker/build-push-action for ghcr.io/coder/coder-k8s:main.

Validation

  • go tool actionlint
  • make verify-vendor
  • make build
  • make test
  • make lint

Risks

Low. Changes are limited to release/publish metadata and licensing/docs. Runtime controller behavior is unchanged.


📋 Implementation Plan

Plan: Add OCI image labels + Apache-2.0 license

Context / Why

We want coder-k8s images published to GHCR to include standard OCI image annotations (surfaced as Docker image labels) so registries and supply-chain tooling can reliably show:

  • where the source lives (org.opencontainers.image.source)
  • what version/commit the image contains (…version, …revision)
  • when it was built (…created)
  • basic project metadata (…title, …description, …documentation, etc.)

Additionally, we want the repository to be explicitly licensed by adding an Apache-2.0 LICENSE file, and to reflect that license in image metadata (org.opencontainers.image.licenses=Apache-2.0).

User decisions (2026-02-12):

  • License: Apache-2.0
  • Label scope: Release/Publish only (GoReleaser release images + GH Actions :main publish). Keep e2e/kind/local docker build images unchanged.

Evidence

  • Dockerfile.goreleaser has no LABEL instructions (so adding labels must be done via build flags for the selected scope).
  • .goreleaser.yaml uses dockers[].build_flag_templates, which supports passing --label=… at build time.
  • .github/workflows/ci.yaml publishes ghcr.io/coder/coder-k8s:main via docker/build-push-action but currently provides no labels.
  • OCI spec “Pre-Defined Annotation Keys” list (org.opencontainers.image.*): opencontainers/image-spec annotations.md.
  • GoReleaser templates: .Date is UTC RFC3339 and .FullCommit/.Version are available template keys.

Implementation details

1) Add Apache-2.0 LICENSE

Files:

  • LICENSE (new)

Steps:

  1. Add a repo-root LICENSE file containing the canonical Apache License, Version 2.0 text.
  2. (Optional, but nice) Add a one-line note to README.md like ## LicenseApache-2.0.

Notes:

  • The OCI label expects an SPDX expression, so we’ll use Apache-2.0.
  • Adding NOTICE is only necessary if we want to carry additional attribution notices; defer unless we have a concrete need.

2) Add OCI labels to release images built by GoReleaser

File:

  • .goreleaser.yaml

Approach:
Add OCI labels as Docker --label=… flags in the existing dockers[0].build_flag_templates list.

Proposed label set (OCI pre-defined keys):

  • org.opencontainers.image.created = build time (RFC3339)
  • org.opencontainers.image.source = repo URL
  • org.opencontainers.image.url = project homepage URL (docs site)
  • org.opencontainers.image.documentation = docs URL
  • org.opencontainers.image.title = coder-k8s
  • org.opencontainers.image.description = short human description
  • org.opencontainers.image.version = release version
  • org.opencontainers.image.revision = git commit SHA
  • org.opencontainers.image.vendor = Coder
  • org.opencontainers.image.licenses = Apache-2.0
  • org.opencontainers.image.authors = Coder (or Coder <support@coder.com> if preferred)

Config sketch:

# .goreleaser.yaml

dockers:
  - id: coder-k8s-image
    image_templates:
      - "ghcr.io/coder/coder-k8s:{{ .Version }}"
      - "ghcr.io/coder/coder-k8s:latest"
    dockerfile: Dockerfile.goreleaser
    use: buildx
    build_flag_templates:
      - "--pull"
      - "--platform=linux/amd64"

      # OCI image labels
      - "--label=org.opencontainers.image.created={{ .Date }}"
      - "--label=org.opencontainers.image.source=https://github.com/coder/coder-k8s"
      - "--label=org.opencontainers.image.url=https://coder.github.io/coder-k8s/"
      - "--label=org.opencontainers.image.documentation=https://coder.github.io/coder-k8s/"
      - "--label=org.opencontainers.image.title=coder-k8s"
      - "--label=org.opencontainers.image.description=Kubernetes operator for Coder"
      - "--label=org.opencontainers.image.version={{ .Version }}"
      - "--label=org.opencontainers.image.revision={{ .FullCommit }}"
      - "--label=org.opencontainers.image.vendor=Coder"
      - "--label=org.opencontainers.image.licenses=Apache-2.0"
      - "--label=org.opencontainers.image.authors=Coder"

Deliberate omissions:

  • org.opencontainers.image.ref.name (OCI spec says it’s only meaningful for OCI image layout descriptors).
  • org.opencontainers.image.base.* (requires pinning + reliably discovering base digest; out of scope for now).

3) Add OCI labels to GH Actions publish :main image

File:

  • .github/workflows/ci.yaml

Approach:

  • Add a small run: step in publish-main to compute an RFC3339 UTC timestamp.
  • Pass a multiline labels: block to docker/build-push-action.

Workflow sketch:

# .github/workflows/ci.yaml (job: publish-main)

      - name: Compute OCI label values
        id: oci
        run: |
          echo "created=$(date -u +%Y-%m-%dT%H:%M:%SZ)" >> "$GITHUB_OUTPUT"

      - name: Build and push :main
        uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5.4.0
        with:
          context: .
          file: Dockerfile.goreleaser
          push: true
          tags: ghcr.io/coder/coder-k8s:main
          labels: |
            org.opencontainers.image.created=${{ steps.oci.outputs.created }}
            org.opencontainers.image.source=https://github.com/coder/coder-k8s
            org.opencontainers.image.url=https://coder.github.io/coder-k8s/
            org.opencontainers.image.documentation=https://coder.github.io/coder-k8s/
            org.opencontainers.image.title=coder-k8s
            org.opencontainers.image.description=Kubernetes operator for Coder
            org.opencontainers.image.version=main
            org.opencontainers.image.revision=${{ github.sha }}
            org.opencontainers.image.vendor=Coder
            org.opencontainers.image.licenses=Apache-2.0
            org.opencontainers.image.authors=Coder

This keeps the label scope tightly limited to published images (release + :main) without adding labels to the Dockerfile that would also affect e2e/kind/local builds.

4) Validation / roll-out

  1. Run the standard project checks:
    • make test
    • make build
    • make lint
  2. Validate workflows locally with:
    • go tool actionlint
  3. Spot-check label presence:
    • For the GH Actions :main label set, run a local build with equivalent --label flags (copied from the workflow) and inspect:

      created="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
      rev="$(git rev-parse HEAD)"
      
      docker build -f Dockerfile.goreleaser -t coder-k8s:test \
        --label "org.opencontainers.image.created=$created" \
        --label "org.opencontainers.image.source=https://github.com/coder/coder-k8s" \
        --label "org.opencontainers.image.url=https://coder.github.io/coder-k8s/" \
        --label "org.opencontainers.image.documentation=https://coder.github.io/coder-k8s/" \
        --label "org.opencontainers.image.title=coder-k8s" \
        --label "org.opencontainers.image.description=Kubernetes operator for Coder" \
        --label "org.opencontainers.image.version=main" \
        --label "org.opencontainers.image.revision=$rev" \
        --label "org.opencontainers.image.vendor=Coder" \
        --label "org.opencontainers.image.licenses=Apache-2.0" \
        --label "org.opencontainers.image.authors=Coder" \
        .
      
      docker inspect coder-k8s:test --format '{{ json .Config.Labels }}' | jq
    • For GoReleaser-built (release) images:

      • goreleaser release --snapshot --clean (snapshot mode implies no publishing)
      • Inspect the resulting image labels via docker inspect … (GoReleaser will print the image tags it built).
Notes / future enhancements (not in scope)
  • Consider image signing (cosign), provenance/SLSA attestation, and SBOM attachment (SPDX/CycloneDX) once OCI metadata is in place.
  • Consider adding org.opencontainers.image.base.name/…base.digest after pinning the distroless base image to a digest.

Generated with mux • Model: openai:gpt-5.3-codex • Thinking: xhigh • Cost: $0.94

Add standard OCI image labels to publish-time image builds so release images
and ghcr.io/coder/coder-k8s:main carry source, version/revision, build time,
and licensing metadata.

Also add an Apache-2.0 LICENSE file and document license information in the
README.

---

_Generated with `mux` • Model: `openai:gpt-5.3-codex` • Thinking: `xhigh` • Cost: `$0.94`_

<!-- mux-attribution: model=openai:gpt-5.3-codex thinking=xhigh costs=0.94 -->
@ThomasK33
Copy link
Copy Markdown
Member Author

@codex review

Please review this PR for OCI label metadata and licensing changes.

@chatgpt-codex-connector
Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Hooray!

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ThomasK33 ThomasK33 added this pull request to the merge queue Feb 12, 2026
@ThomasK33
Copy link
Copy Markdown
Member Author

Merged via the queue into main with commit f9a37bc Feb 12, 2026
8 checks passed
@ThomasK33 ThomasK33 deleted the docker-ng55 branch February 12, 2026 09:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant