From 6857aa79e5e77ebc7c70017661588a50de591a1a Mon Sep 17 00:00:00 2001 From: "Benjamin R. J. Schwedler" Date: Thu, 4 Jun 2026 15:22:22 -0500 Subject: [PATCH 1/3] Add fork-safe install CI with replicas=0 Fork PRs have no access to license secrets, so ct install (which waits for pods that require a valid license) cannot run as-is. Add a detect-fork job and gate the existing install steps on non-forks. For fork PRs, run ct install with --helm-extra-set-args '--set=replicas=0': Kubernetes creates all non-pod resources (Services, RBAC, ConfigMaps, PVCs) and considers the Deployment immediately rolled out, without ever scheduling a pod that needs the license. --- .github/workflows/chart-test.yaml | 34 +++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/.github/workflows/chart-test.yaml b/.github/workflows/chart-test.yaml index 1e775c49..38cc88a4 100644 --- a/.github/workflows/chart-test.yaml +++ b/.github/workflows/chart-test.yaml @@ -137,8 +137,21 @@ jobs: if: steps.unittest.outcome == 'failure' run: exit 1 + detect-fork: + runs-on: ubuntu-latest + permissions: {} + outputs: + is-fork: ${{ steps.check.outputs.is-fork }} + steps: + - name: Check fork status + id: check + env: + IS_FORK: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository }} + run: echo "is-fork=$IS_FORK" >> "$GITHUB_OUTPUT" + install: runs-on: ubuntu-latest-4x + needs: [detect-fork] steps: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -178,6 +191,7 @@ jobs: run: kubectl create namespace posit-test - name: Create License File Secrets + if: needs.detect-fork.outputs.is-fork != 'true' env: PWB_LICENSE: ${{ secrets.PWB_LICENSE_FILE }} PCT_LICENSE: ${{ secrets.PCT_LICENSE_FILE }} @@ -201,16 +215,32 @@ jobs: # no allow-failure until https://github.com/actions/toolkit/issues/399 - name: Run chart-testing (install changed) id: ct-install - if: ${{ github.ref != 'refs/heads/main' && steps.list-changed.outputs.changed == 'true' }} + if: ${{ github.ref != 'refs/heads/main' && steps.list-changed.outputs.changed == 'true' && needs.detect-fork.outputs.is-fork != 'true' }} run: ct install --target-branch main --chart-dirs charts --chart-dirs other-charts --excluded-charts rstudio-library,rstudio-library-test --namespace posit-test continue-on-error: true # no allow-failure until https://github.com/actions/toolkit/issues/399 - name: Run chart-testing (install all) id: ct-install-all + if: needs.detect-fork.outputs.is-fork != 'true' run: ct install --target-branch main --all --chart-dirs charts --chart-dirs other-charts --excluded-charts rstudio-library,rstudio-library-test --namespace posit-test continue-on-error: true + # Fork PRs have no access to license secrets. replicas=0 causes Kubernetes to + # create all non-pod resources (Services, RBAC, ConfigMaps, PVCs) and consider + # the Deployment immediately rolled out — no pod is scheduled that needs the license. + - name: Run chart-testing (install changed, fork) + id: ct-install-fork + if: ${{ github.ref != 'refs/heads/main' && steps.list-changed.outputs.changed == 'true' && needs.detect-fork.outputs.is-fork == 'true' }} + run: ct install --target-branch main --chart-dirs charts --chart-dirs other-charts --excluded-charts rstudio-library,rstudio-library-test --namespace posit-test --helm-extra-set-args "--set=replicas=0" + continue-on-error: true + + - name: Run chart-testing (install all, fork) + id: ct-install-all-fork + if: needs.detect-fork.outputs.is-fork == 'true' + run: ct install --target-branch main --all --chart-dirs charts --chart-dirs other-charts --excluded-charts rstudio-library,rstudio-library-test --namespace posit-test --helm-extra-set-args "--set=replicas=0" + continue-on-error: true + - name: Notify Slack of chart install failure if on main if: github.ref == 'refs/heads/main' && (steps.ct-install.outcome == 'failure' || steps.ct-install-all.outcome == 'failure') uses: slackapi/slack-github-action@45a88b9581bfab2566dc881e2cd66d334e621e2c # v3.0.3 @@ -233,7 +263,7 @@ jobs: SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK - name: Fail the workflow if failed installs - if: steps.ct-install.outcome == 'failure' || steps.ct-install-all.outcome == 'failure' + if: steps.ct-install.outcome == 'failure' || steps.ct-install-all.outcome == 'failure' || steps.ct-install-fork.outcome == 'failure' || steps.ct-install-all-fork.outcome == 'failure' run: exit 1 check-versions-connect: From b148724b7dbac09d91bc4ea863c7999e9bbcb8d4 Mon Sep 17 00:00:00 2001 From: "Benjamin R. J. Schwedler" Date: Thu, 4 Jun 2026 15:43:07 -0500 Subject: [PATCH 2/3] Bump helm-unittest to v1.1.0, fix errorPattern regexes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Helm 3.18.5 changed its JSON schema parser, producing a different error string format for schema validation failures. helm-unittest v1.0.1 documented this as a known breaking change. The posit-chronicle configmap_fail_test.yaml tests used errorPattern values that matched the old format ("ServiceLogLevel: Does not match pattern") but not the new one ("'/config/Logging/ServiceLogLevel': 'INVALID' does not match pattern"). This caused the tests to fail locally with helm-unittest >= v1.0.1 while CI (pinned to v1.0.0) continued to pass — a latent break waiting for the version bump. Relax both patterns to ".*ServiceLogLevel.*does not match pattern.*" and ".*ServiceLogFormat.*does not match pattern.*", which match both the old and new error formats. --- .github/workflows/chart-test.yaml | 2 +- charts/posit-chronicle/tests/configmap_fail_test.yaml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/chart-test.yaml b/.github/workflows/chart-test.yaml index 38cc88a4..4d2b4a85 100644 --- a/.github/workflows/chart-test.yaml +++ b/.github/workflows/chart-test.yaml @@ -87,7 +87,7 @@ jobs: version: "v3.19.2" - name: Install helm unittest plugin - run: helm plugin install https://github.com/helm-unittest/helm-unittest.git --version v1.0.0 + run: helm plugin install https://github.com/helm-unittest/helm-unittest.git --version v1.1.0 - name: Run chart unit tests id: unittest diff --git a/charts/posit-chronicle/tests/configmap_fail_test.yaml b/charts/posit-chronicle/tests/configmap_fail_test.yaml index 402dc91f..9164c140 100644 --- a/charts/posit-chronicle/tests/configmap_fail_test.yaml +++ b/charts/posit-chronicle/tests/configmap_fail_test.yaml @@ -27,7 +27,7 @@ tests: ServiceLogLevel: INVALID asserts: - failedTemplate: - errorPattern: ".*ServiceLogLevel: Does not match pattern.*" + errorPattern: ".*ServiceLogLevel.*does not match pattern.*" - it: should fail for invalid log level values set: config: @@ -35,7 +35,7 @@ tests: ServiceLogFormat: INVALID asserts: - failedTemplate: - errorPattern: ".*ServiceLogFormat: Does not match pattern.*" + errorPattern: ".*ServiceLogFormat.*does not match pattern.*" - it: should fail if S3 is enabled but no bucket is specified set: config: From 4b0a26698f5be93d2e72804f3095989ef363e0f5 Mon Sep 17 00:00:00 2001 From: "Benjamin R. J. Schwedler" Date: Thu, 4 Jun 2026 15:49:44 -0500 Subject: [PATCH 3/3] Make errorPattern regexes case-insensitive Go regex is case-sensitive by default. The old Helm schema error format uses uppercase 'Does not match pattern'; the new format uses lowercase. Add (?i) to both patterns so they match either wording. --- charts/posit-chronicle/tests/configmap_fail_test.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/charts/posit-chronicle/tests/configmap_fail_test.yaml b/charts/posit-chronicle/tests/configmap_fail_test.yaml index 9164c140..78c4ed24 100644 --- a/charts/posit-chronicle/tests/configmap_fail_test.yaml +++ b/charts/posit-chronicle/tests/configmap_fail_test.yaml @@ -27,7 +27,7 @@ tests: ServiceLogLevel: INVALID asserts: - failedTemplate: - errorPattern: ".*ServiceLogLevel.*does not match pattern.*" + errorPattern: "(?i).*ServiceLogLevel.*does not match pattern.*" - it: should fail for invalid log level values set: config: @@ -35,7 +35,7 @@ tests: ServiceLogFormat: INVALID asserts: - failedTemplate: - errorPattern: ".*ServiceLogFormat.*does not match pattern.*" + errorPattern: "(?i).*ServiceLogFormat.*does not match pattern.*" - it: should fail if S3 is enabled but no bucket is specified set: config: