Skip to content

OCI bundle image loading error "Bundle load failed: no layers in manifest" #7461

Open
@srenatus

Description

@srenatus

Discussed in https://github.com/orgs/open-policy-agent/discussions/666

Originally posted by zscott March 1, 2025

❗ When this makes it into a CHANGELOG, let's ensure to attribute it to @zscott, not me!

Problem

I build and push OCI bundles to ghcr.io using github actions but when I try to pull the bundle into opa I get "Bundle load failed: no layers in manifest". I'm probably doing something silly, but I've been banging my head on this for a while now.

❯ opa run --server --config-file=opa-config.yaml
{"addrs":["localhost:8181"],"diagnostic-addrs":[],"level":"info","msg":"Initializing server.","time":"2025-03-01T05:52:24-06:00"}
{"level":"info","msg":"Starting bundle loader.","name":"trust-framework","plugin":"bundle","time":"2025-03-01T05:52:24-06:00"}
{"level":"error","msg":"Bundle load failed: no layers in manifest","name":"trust-framework","plugin":"bundle","time":"2025-03-01T05:52:24-06:00"}
{"level":"error","msg":"Bundle load failed: no layers in manifest","name":"trust-framework","plugin":"bundle","time":"2025-03-01T05:52:25-06:00"}
{"level":"error","msg":"Bundle load failed: no layers in manifest","name":"trust-framework","plugin":"bundle","time":"2025-03-01T05:52:25-06:00"}
{"level":"error","msg":"Bundle load failed: no layers in manifest","name":"trust-framework","plugin":"bundle","time":"2025-03-01T05:52:26-06:00"}
{"level":"error","msg":"Bundle load failed: no layers in manifest","name":"trust-framework","plugin":"bundle","time":"2025-03-01T05:52:27-06:00"}
^C{"level":"info","msg":"Shutting down...","time":"2025-03-01T05:52:27-06:00"}

opa-config.yaml

services:
  ghcr:
    url: https://ghcr.io
    type: oci
    credentials:
      bearer:
        token: "${GHCR_TOKEN}"

bundles:
  trust-framework:
    service: ghcr
    resource: ghcr.io/<org>/<image>:sha-1ebe12f
    persist: false
    polling:
      min_delay_seconds: 60
      max_delay_seconds: 120

When I examine the image with dive it only has a single layer.
image

Build steps (full github workflow below):

make bundle
echo '{}' > config.json
oras push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }} \
            --config config.json:application/vnd.oci.image.config.v1+json \
            bundle/bundle.tar.gz:application/vnd.oci.image.layer.v1.tar+gzip

Versions

❯ opa version
Version: 1.2.0
Build Commit: d537788
Build Timestamp: 2025-02-28T14:17:35Z
Build Hostname:
Go Version: go1.24.0
Platform: darwin/arm64
Rego Version: v1
WebAssembly: unavailable

❯ oras version
Version: 1.2.2+Homebrew
Go version: go1.23.4

Makefile

.PHONY: build test run clean

# Variables
BUNDLE_DIR := bundle
BUNDLE_FILE := bundle.tar.gz
BUILD_HASH := $(shell git rev-parse HEAD)

bundle:
	@mkdir -p $(BUNDLE_DIR)
	@opa build --bundle --revision $(BUILD_HASH) -o $(BUNDLE_DIR)/$(BUNDLE_FILE) ./src

test:
	@opa test ./src

run: build
	@./scripts/run-server.sh

clean:
	@rm -rf $(BUNDLE_DIR)

github workflow

name: Build and Deploy

on:
  push:
    branches: [ "main" ]
    tags: [ 'v*' ]
  pull_request:
    branches: [ "main" ]

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write

    steps:
      - name: Checkout repository
        uses: actions/checkout@v3

      - name: Install OPA
        run: |
          curl -L -o opa https://openpolicyagent.org/downloads/v1.2.0/opa_linux_amd64_static
          chmod +x opa
          sudo mv opa /usr/local/bin/

      - name: Install ORAS
        run: |
          VERSION="1.2.0"
          curl -LO "https://github.com/oras-project/oras/releases/download/v${VERSION}/oras_${VERSION}_linux_amd64.tar.gz"
          mkdir -p oras-install/
          tar -zxf oras_${VERSION}_*.tar.gz -C oras-install/
          sudo mv oras-install/oras /usr/local/bin/
          rm -rf oras_${VERSION}_*.tar.gz oras-install/

      - name: Log in to the Container registry
        if: github.event_name != 'pull_request'
        uses: docker/login-action@v2
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Build bundle
        run: make bundle

      - name: Push bundle to container registry
        if: github.event_name != 'pull_request'
        run: |
          # Create a simple config file for the OCI image
          echo '{}' > config.json
          
          # Push the bundle to the container registry with proper media types that OPA expects
          oras push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }} \
            --config config.json:application/vnd.oci.image.config.v1+json \
            bundle/bundle.tar.gz:application/vnd.oci.image.layer.v1.tar+gzip

      - name: Extract metadata
        id: meta
        uses: docker/metadata-action@v4
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
          tags: |
            type=semver,pattern={{version}}
            type=ref,event=branch
            type=sha,format=short

      - name: Create artifact version from git
        id: version
        run: |
          if [[ $GITHUB_REF == refs/tags/v* ]]; then
            VERSION=${GITHUB_REF#refs/tags/v}
          else
            VERSION="latest"
          fi
          echo "VERSION=$VERSION" >> $GITHUB_ENV

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v2
        
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v2
        
      - name: Build and push Docker image
        if: github.event_name != 'pull_request'
        uses: docker/build-push-action@v4
        with:
          context: .
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          file: .github/workflows/Dockerfile
          platforms: linux/amd64,linux/arm64
```</div>

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions