diff --git a/.github/workflows/publish-ghcr-test.yaml b/.github/workflows/publish-ghcr-test.yaml new file mode 100644 index 0000000000..87aad005d8 --- /dev/null +++ b/.github/workflows/publish-ghcr-test.yaml @@ -0,0 +1,97 @@ +name: Publish Test Image to GHCR + +on: + workflow_dispatch: + inputs: + image_name: + description: "Full image name (e.g. ghcr.io//opa-test)" + required: true + type: string + image_tag: + description: "Image tag to publish (defaults to short commit SHA)" + required: false + type: string + +permissions: + contents: read + packages: write + +jobs: + build-linux-binaries: + name: Build Linux Binaries (${{ matrix.goarch }}) + runs-on: ubuntu-24.04 + strategy: + fail-fast: false + matrix: + goarch: + - amd64 + - arm64 + + steps: + - name: Check out code + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + + - name: Build Linux binaries + env: + GOARCH: ${{ matrix.goarch }} + run: make ci-go-ci-build-linux ci-go-ci-build-linux-static + + - name: Upload binaries + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: binaries-linux-${{ matrix.goarch }} + path: _release/opa_linux_${{ matrix.goarch }}* + + publish-ghcr: + name: Publish to GHCR + needs: build-linux-binaries + runs-on: ubuntu-24.04 + + steps: + - name: Check out code + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + + - name: Download release binaries + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + pattern: binaries-linux-* + merge-multiple: true + path: _release + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0 + + - name: Login to GHCR + env: + GHCR_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + echo "$GHCR_TOKEN" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin + + - name: Select image tag + env: + INPUT_TAG: ${{ inputs.image_tag }} + run: | + if [ -n "$INPUT_TAG" ]; then + echo "IMAGE_TAG=$INPUT_TAG" >> "$GITHUB_ENV" + else + echo "IMAGE_TAG=$(git rev-parse --short HEAD)" >> "$GITHUB_ENV" + fi + + - name: Validate image tag + env: + IMAGE_TAG: ${{ env.IMAGE_TAG }} + run: | + if [[ ! "$IMAGE_TAG" =~ ^[A-Za-z0-9][A-Za-z0-9_.-]{0,127}$ ]]; then + echo "Invalid image_tag: '$IMAGE_TAG'" + exit 1 + fi + + - name: Build and push multi-arch images + env: + DOCKER_IMAGE: ${{ inputs.image_name }} + IMAGE_TAG: ${{ env.IMAGE_TAG }} + run: make "push-manifest-list-${IMAGE_TAG}" diff --git a/docs/docs/contrib-development.md b/docs/docs/contrib-development.md index f63ef4d8c8..c5adbaf113 100644 --- a/docs/docs/contrib-development.md +++ b/docs/docs/contrib-development.md @@ -192,6 +192,19 @@ The following secrets are used by the Github Action workflows: | SLACK_NOTIFICATION_WEBHOOK | Slack webhook for sending notifications. Optional -- If not provided the notification steps are skipped. | | NETLIFY_BUILD_HOOK_URL | URL to trigger Netlify (openpolicyagent.org) deploys after release. Optional -- If not provided the Netlify steps are skipped. | +### Publish a test image to GHCR + +To build and publish a test image from your branch to your own GitHub Container Registry repository, run the +`Publish Test Image to GHCR` workflow manually from the Actions tab. + +The workflow expects: + +- `image_name`: full target image name like `ghcr.io//opa-test` +- `image_tag` (optional): tag to push (defaults to short commit SHA) + +It uses the repository `GITHUB_TOKEN` for authentication, so your repository/package settings must allow workflow +write access to packages. + ### Periodic Workflows Some of the Github Action workflows are triggered on a schedule, and not included in the diff --git a/v1/plugins/logger/opentelemetry/plugin.go b/v1/plugins/logger/opentelemetry/plugin.go index 7e38e1b1e2..2bbc52cc2f 100644 --- a/v1/plugins/logger/opentelemetry/plugin.go +++ b/v1/plugins/logger/opentelemetry/plugin.go @@ -7,6 +7,7 @@ package opentelemetry import ( "context" "crypto/tls" + "errors" "fmt" "log/slog" "strings" @@ -96,7 +97,7 @@ func (p *Plugin) Start(ctx context.Context) error { defer p.mtx.Unlock() if p.handler != nil { - return fmt.Errorf("OpenTelemetry logger already started") + return errors.New("OpenTelemetry logger already started") } provider, err := newLoggerProvider(ctx, p.config) diff --git a/v1/plugins/logger/opentelemetry/plugin_test.go b/v1/plugins/logger/opentelemetry/plugin_test.go index f542ac35ac..76e2ee7553 100644 --- a/v1/plugins/logger/opentelemetry/plugin_test.go +++ b/v1/plugins/logger/opentelemetry/plugin_test.go @@ -12,6 +12,7 @@ import ( "net" "net/http" "net/http/httptest" + "strconv" "sync" "testing" "time" @@ -227,9 +228,9 @@ func anyValueString(value *commonpb.AnyValue) string { case *commonpb.AnyValue_StringValue: return v.StringValue case *commonpb.AnyValue_IntValue: - return fmt.Sprintf("%d", v.IntValue) + return strconv.FormatInt(v.IntValue, 10) case *commonpb.AnyValue_BoolValue: - return fmt.Sprintf("%t", v.BoolValue) + return strconv.FormatBool(v.BoolValue) case *commonpb.AnyValue_DoubleValue: return fmt.Sprintf("%v", v.DoubleValue) default: