From 2edde37948e594cabfea1f632d19f0285ac2ee31 Mon Sep 17 00:00:00 2001 From: Justin Gordon Date: Sat, 9 May 2026 12:09:58 -1000 Subject: [PATCH 1/3] Update HorizontalForm.res with demo text --- .../comments/rescript/CommentForm/forms/HorizontalForm.res | 1 + 1 file changed, 1 insertion(+) diff --git a/client/app/bundles/comments/rescript/CommentForm/forms/HorizontalForm.res b/client/app/bundles/comments/rescript/CommentForm/forms/HorizontalForm.res index 2a64a0ca3..95be2da01 100644 --- a/client/app/bundles/comments/rescript/CommentForm/forms/HorizontalForm.res +++ b/client/app/bundles/comments/rescript/CommentForm/forms/HorizontalForm.res @@ -8,6 +8,7 @@ let make = (~author, ~handleAuthorChange, ~text, ~handleTextChange, ~handleSubmi
Date: Wed, 20 May 2026 21:01:57 -1000 Subject: [PATCH 2/3] Regenerate cpflow GitHub Actions --- .../cpflow-build-docker-image/action.yml | 4 +-- .../cpflow-setup-environment/action.yml | 14 ++++++--- .../actions/cpflow-wait-for-health/action.yml | 7 ++--- .../workflows/cpflow-delete-review-app.yml | 9 ++++-- .../workflows/cpflow-deploy-review-app.yml | 29 ++++++++++++------- .github/workflows/cpflow-deploy-staging.yml | 2 ++ .github/workflows/cpflow-review-app-help.yml | 4 +-- 7 files changed, 42 insertions(+), 27 deletions(-) diff --git a/.github/actions/cpflow-build-docker-image/action.yml b/.github/actions/cpflow-build-docker-image/action.yml index 8a7a94ebf..c5b4faf38 100644 --- a/.github/actions/cpflow-build-docker-image/action.yml +++ b/.github/actions/cpflow-build-docker-image/action.yml @@ -52,7 +52,7 @@ runs: chmod 700 ~/.ssh if [[ -n "${DOCKER_BUILD_SSH_KNOWN_HOSTS}" ]]; then - printf '%s\n' "${DOCKER_BUILD_SSH_KNOWN_HOSTS}" | tr -d '\r' > ~/.ssh/known_hosts + printf '%s\n' "${DOCKER_BUILD_SSH_KNOWN_HOSTS}" > ~/.ssh/known_hosts else printf '%s\n' \ 'github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl' \ @@ -62,7 +62,7 @@ runs: fi chmod 600 ~/.ssh/known_hosts - printf '%s\n' "${DOCKER_BUILD_SSH_KEY}" | tr -d '\r' > ~/.ssh/cpflow_build_key + printf '%s\n' "${DOCKER_BUILD_SSH_KEY}" > ~/.ssh/cpflow_build_key chmod 600 ~/.ssh/cpflow_build_key - name: Build Docker image diff --git a/.github/actions/cpflow-setup-environment/action.yml b/.github/actions/cpflow-setup-environment/action.yml index 3659559e4..e337fb2f7 100644 --- a/.github/actions/cpflow-setup-environment/action.yml +++ b/.github/actions/cpflow-setup-environment/action.yml @@ -14,16 +14,22 @@ inputs: from .ruby-version, .tool-versions, or the Gemfile. required: false default: "" + # GitHub parses double-brace expression snippets inside action metadata (including + # `description:`) while loading the composite action, and the `vars` context is not + # available in that phase. Keep these descriptions in plain prose - reference repo + # variables by NAME only, never with literal GitHub Actions expression syntax. cpln_cli_version: description: >- - @controlplane/cli version. Empty string falls back to the action's pinned default - so callers can pass `${{ vars.CPLN_CLI_VERSION }}` unconditionally. + @controlplane/cli version. Empty string falls back to the action's pinned default, + so callers can wire this input to the CPLN_CLI_VERSION repository variable + unconditionally. required: false default: "" cpflow_version: description: >- - cpflow gem version. Empty string falls back to the action's pinned default - so callers can pass `${{ vars.CPFLOW_VERSION }}` unconditionally. + cpflow gem version. Empty string falls back to the action's pinned default, + so callers can wire this input to the CPFLOW_VERSION repository variable + unconditionally. required: false default: "" diff --git a/.github/actions/cpflow-wait-for-health/action.yml b/.github/actions/cpflow-wait-for-health/action.yml index 60c92a9b4..703477233 100644 --- a/.github/actions/cpflow-wait-for-health/action.yml +++ b/.github/actions/cpflow-wait-for-health/action.yml @@ -61,15 +61,12 @@ runs: for attempt in $(seq 1 "${CPFLOW_MAX_RETRIES}"); do echo "Health check attempt ${attempt}/${CPFLOW_MAX_RETRIES}" - workload_stderr="$(mktemp)" - if ! workload_json="$(cpln workload get "${CPFLOW_WORKLOAD_NAME}" --gvc "${CPFLOW_APP_NAME}" --org "${CPFLOW_ORG}" -o json 2>"${workload_stderr}")"; then + if ! workload_json="$(cpln workload get "${CPFLOW_WORKLOAD_NAME}" --gvc "${CPFLOW_APP_NAME}" --org "${CPFLOW_ORG}" -o json 2>&1)"; then echo "::error::Workload '${CPFLOW_WORKLOAD_NAME}' not found in GVC '${CPFLOW_APP_NAME}'. Set PRIMARY_WORKLOAD to the correct workload name." >&2 - cat "${workload_stderr}" >&2 - rm -f "${workload_stderr}" + printf '%s\n' "${workload_json}" >&2 echo "healthy=false" >> "$GITHUB_OUTPUT" exit 1 fi - rm -f "${workload_stderr}" endpoint="$(echo "${workload_json}" | jq -r '.status.endpoint // empty')" if [[ -n "${endpoint}" ]]; then diff --git a/.github/workflows/cpflow-delete-review-app.yml b/.github/workflows/cpflow-delete-review-app.yml index b450a9a27..ffdc45f44 100644 --- a/.github/workflows/cpflow-delete-review-app.yml +++ b/.github/workflows/cpflow-delete-review-app.yml @@ -113,13 +113,18 @@ jobs: cpln_org: ${{ vars.CPLN_ORG_STAGING }} review_app_prefix: ${{ vars.REVIEW_APP_PREFIX }} + # Finalizer still runs after delete failures, but only after config validation + # created the initial PR comment and workflow link env vars it updates. - name: Finalize delete status if: always() && steps.config.outputs.ready == 'true' uses: actions/github-script@v7 + env: + COMMENT_ID: ${{ steps.create-comment.outputs.comment-id }} + JOB_STATUS: ${{ job.status }} with: script: | - const commentId = Number("${{ steps.create-comment.outputs.comment-id }}"); - const success = "${{ job.status }}" === "success"; + const commentId = Number(process.env.COMMENT_ID); + const success = process.env.JOB_STATUS === "success"; const body = success ? [ `✅ Review app for PR #${process.env.PR_NUMBER} is deleted`, diff --git a/.github/workflows/cpflow-deploy-review-app.yml b/.github/workflows/cpflow-deploy-review-app.yml index b0515c549..f4b029fd4 100644 --- a/.github/workflows/cpflow-deploy-review-app.yml +++ b/.github/workflows/cpflow-deploy-review-app.yml @@ -119,11 +119,9 @@ jobs: same_repo="true" fi - { - echo "PR_NUMBER=$pr_number" - echo "APP_NAME=${REVIEW_APP_PREFIX}-$pr_number" - echo "PR_SHA=$pr_sha" - } >> "$GITHUB_ENV" + echo "PR_NUMBER=$pr_number" >> "$GITHUB_ENV" + echo "APP_NAME=${REVIEW_APP_PREFIX}-$pr_number" >> "$GITHUB_ENV" + echo "PR_SHA=$pr_sha" >> "$GITHUB_ENV" echo "same_repo=${same_repo}" >> "$GITHUB_OUTPUT" - name: Validate review app deployment source @@ -305,9 +303,11 @@ jobs: - name: Update PR comment with build status if: steps.config.outputs.ready == 'true' && steps.source.outputs.allowed == 'true' && (steps.check-app.outputs.exists == 'true' || steps.setup-review-app.outcome == 'success') uses: actions/github-script@v7 + env: + COMMENT_ID: ${{ steps.create-comment.outputs.comment-id }} with: script: | - const commentId = Number("${{ steps.create-comment.outputs.comment-id }}"); + const commentId = Number(process.env.COMMENT_ID); if (!Number.isFinite(commentId) || commentId <= 0) { core.warning("Skipping PR comment update because no comment id was created."); return; @@ -344,9 +344,11 @@ jobs: - name: Update PR comment with deploy status if: steps.config.outputs.ready == 'true' && steps.source.outputs.allowed == 'true' && (steps.check-app.outputs.exists == 'true' || steps.setup-review-app.outcome == 'success') uses: actions/github-script@v7 + env: + COMMENT_ID: ${{ steps.create-comment.outputs.comment-id }} with: script: | - const commentId = Number("${{ steps.create-comment.outputs.comment-id }}"); + const commentId = Number(process.env.COMMENT_ID); if (!Number.isFinite(commentId) || commentId <= 0) { core.warning("Skipping PR comment update because no comment id was created."); return; @@ -398,12 +400,17 @@ jobs: - name: Finalize deployment status if: always() && steps.config.outputs.ready == 'true' && steps.source.outputs.allowed == 'true' && (steps.check-app.outputs.exists == 'true' || steps.setup-review-app.outcome == 'success') uses: actions/github-script@v7 + env: + COMMENT_ID: ${{ steps.create-comment.outputs.comment-id }} + DEPLOYMENT_ID: ${{ steps.init-deployment.outputs.result }} + APP_URL: ${{ steps.workload.outputs.workload_url }} + JOB_STATUS: ${{ job.status }} with: script: | - const commentId = Number("${{ steps.create-comment.outputs.comment-id }}"); - const deploymentId = "${{ steps.init-deployment.outputs.result }}"; - const appUrl = "${{ steps.workload.outputs.workload_url }}"; - const success = "${{ job.status }}" === "success"; + const commentId = Number(process.env.COMMENT_ID); + const deploymentId = process.env.DEPLOYMENT_ID; + const appUrl = process.env.APP_URL; + const success = process.env.JOB_STATUS === "success"; if (deploymentId) { await github.rest.repos.createDeploymentStatus({ diff --git a/.github/workflows/cpflow-deploy-staging.yml b/.github/workflows/cpflow-deploy-staging.yml index d00e68eaf..076145d6b 100644 --- a/.github/workflows/cpflow-deploy-staging.yml +++ b/.github/workflows/cpflow-deploy-staging.yml @@ -56,6 +56,8 @@ jobs: - name: Checkout repository if: steps.check-branch.outputs.is_deployable == 'true' uses: actions/checkout@v4 + with: + persist-credentials: false - name: Validate required secrets and variables if: steps.check-branch.outputs.is_deployable == 'true' diff --git a/.github/workflows/cpflow-review-app-help.yml b/.github/workflows/cpflow-review-app-help.yml index 74626217b..f590ea607 100644 --- a/.github/workflows/cpflow-review-app-help.yml +++ b/.github/workflows/cpflow-review-app-help.yml @@ -28,13 +28,11 @@ jobs: const body = [ "# Review app commands", "", - "Repo owners, members, and collaborators can use these commands:", - "", "- `+review-app-deploy` - create or redeploy this PR's review app.", "- `+review-app-delete` - delete this PR's review app and temporary resources.", "- `+review-app-help` - show setup details and workflow behavior.", "", - "For setup details, repo owners, members, and collaborators can comment `+review-app-help`." + "For setup details, comment `+review-app-help`." ].join("\n"); await github.rest.issues.createComment({ From 190cb191e0c96bddb471a784d248497cca8cb9cc Mon Sep 17 00:00:00 2001 From: Justin Gordon Date: Wed, 20 May 2026 21:08:04 -1000 Subject: [PATCH 3/3] Revert "Regenerate cpflow GitHub Actions" This reverts commit 3b13adb32edff77e70b032293cdd3175418ce85a. --- .../cpflow-build-docker-image/action.yml | 4 +-- .../cpflow-setup-environment/action.yml | 14 +++------ .../actions/cpflow-wait-for-health/action.yml | 7 +++-- .../workflows/cpflow-delete-review-app.yml | 9 ++---- .../workflows/cpflow-deploy-review-app.yml | 29 +++++++------------ .github/workflows/cpflow-deploy-staging.yml | 2 -- .github/workflows/cpflow-review-app-help.yml | 4 ++- 7 files changed, 27 insertions(+), 42 deletions(-) diff --git a/.github/actions/cpflow-build-docker-image/action.yml b/.github/actions/cpflow-build-docker-image/action.yml index c5b4faf38..8a7a94ebf 100644 --- a/.github/actions/cpflow-build-docker-image/action.yml +++ b/.github/actions/cpflow-build-docker-image/action.yml @@ -52,7 +52,7 @@ runs: chmod 700 ~/.ssh if [[ -n "${DOCKER_BUILD_SSH_KNOWN_HOSTS}" ]]; then - printf '%s\n' "${DOCKER_BUILD_SSH_KNOWN_HOSTS}" > ~/.ssh/known_hosts + printf '%s\n' "${DOCKER_BUILD_SSH_KNOWN_HOSTS}" | tr -d '\r' > ~/.ssh/known_hosts else printf '%s\n' \ 'github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl' \ @@ -62,7 +62,7 @@ runs: fi chmod 600 ~/.ssh/known_hosts - printf '%s\n' "${DOCKER_BUILD_SSH_KEY}" > ~/.ssh/cpflow_build_key + printf '%s\n' "${DOCKER_BUILD_SSH_KEY}" | tr -d '\r' > ~/.ssh/cpflow_build_key chmod 600 ~/.ssh/cpflow_build_key - name: Build Docker image diff --git a/.github/actions/cpflow-setup-environment/action.yml b/.github/actions/cpflow-setup-environment/action.yml index e337fb2f7..3659559e4 100644 --- a/.github/actions/cpflow-setup-environment/action.yml +++ b/.github/actions/cpflow-setup-environment/action.yml @@ -14,22 +14,16 @@ inputs: from .ruby-version, .tool-versions, or the Gemfile. required: false default: "" - # GitHub parses double-brace expression snippets inside action metadata (including - # `description:`) while loading the composite action, and the `vars` context is not - # available in that phase. Keep these descriptions in plain prose - reference repo - # variables by NAME only, never with literal GitHub Actions expression syntax. cpln_cli_version: description: >- - @controlplane/cli version. Empty string falls back to the action's pinned default, - so callers can wire this input to the CPLN_CLI_VERSION repository variable - unconditionally. + @controlplane/cli version. Empty string falls back to the action's pinned default + so callers can pass `${{ vars.CPLN_CLI_VERSION }}` unconditionally. required: false default: "" cpflow_version: description: >- - cpflow gem version. Empty string falls back to the action's pinned default, - so callers can wire this input to the CPFLOW_VERSION repository variable - unconditionally. + cpflow gem version. Empty string falls back to the action's pinned default + so callers can pass `${{ vars.CPFLOW_VERSION }}` unconditionally. required: false default: "" diff --git a/.github/actions/cpflow-wait-for-health/action.yml b/.github/actions/cpflow-wait-for-health/action.yml index 703477233..60c92a9b4 100644 --- a/.github/actions/cpflow-wait-for-health/action.yml +++ b/.github/actions/cpflow-wait-for-health/action.yml @@ -61,12 +61,15 @@ runs: for attempt in $(seq 1 "${CPFLOW_MAX_RETRIES}"); do echo "Health check attempt ${attempt}/${CPFLOW_MAX_RETRIES}" - if ! workload_json="$(cpln workload get "${CPFLOW_WORKLOAD_NAME}" --gvc "${CPFLOW_APP_NAME}" --org "${CPFLOW_ORG}" -o json 2>&1)"; then + workload_stderr="$(mktemp)" + if ! workload_json="$(cpln workload get "${CPFLOW_WORKLOAD_NAME}" --gvc "${CPFLOW_APP_NAME}" --org "${CPFLOW_ORG}" -o json 2>"${workload_stderr}")"; then echo "::error::Workload '${CPFLOW_WORKLOAD_NAME}' not found in GVC '${CPFLOW_APP_NAME}'. Set PRIMARY_WORKLOAD to the correct workload name." >&2 - printf '%s\n' "${workload_json}" >&2 + cat "${workload_stderr}" >&2 + rm -f "${workload_stderr}" echo "healthy=false" >> "$GITHUB_OUTPUT" exit 1 fi + rm -f "${workload_stderr}" endpoint="$(echo "${workload_json}" | jq -r '.status.endpoint // empty')" if [[ -n "${endpoint}" ]]; then diff --git a/.github/workflows/cpflow-delete-review-app.yml b/.github/workflows/cpflow-delete-review-app.yml index ffdc45f44..b450a9a27 100644 --- a/.github/workflows/cpflow-delete-review-app.yml +++ b/.github/workflows/cpflow-delete-review-app.yml @@ -113,18 +113,13 @@ jobs: cpln_org: ${{ vars.CPLN_ORG_STAGING }} review_app_prefix: ${{ vars.REVIEW_APP_PREFIX }} - # Finalizer still runs after delete failures, but only after config validation - # created the initial PR comment and workflow link env vars it updates. - name: Finalize delete status if: always() && steps.config.outputs.ready == 'true' uses: actions/github-script@v7 - env: - COMMENT_ID: ${{ steps.create-comment.outputs.comment-id }} - JOB_STATUS: ${{ job.status }} with: script: | - const commentId = Number(process.env.COMMENT_ID); - const success = process.env.JOB_STATUS === "success"; + const commentId = Number("${{ steps.create-comment.outputs.comment-id }}"); + const success = "${{ job.status }}" === "success"; const body = success ? [ `✅ Review app for PR #${process.env.PR_NUMBER} is deleted`, diff --git a/.github/workflows/cpflow-deploy-review-app.yml b/.github/workflows/cpflow-deploy-review-app.yml index f4b029fd4..b0515c549 100644 --- a/.github/workflows/cpflow-deploy-review-app.yml +++ b/.github/workflows/cpflow-deploy-review-app.yml @@ -119,9 +119,11 @@ jobs: same_repo="true" fi - echo "PR_NUMBER=$pr_number" >> "$GITHUB_ENV" - echo "APP_NAME=${REVIEW_APP_PREFIX}-$pr_number" >> "$GITHUB_ENV" - echo "PR_SHA=$pr_sha" >> "$GITHUB_ENV" + { + echo "PR_NUMBER=$pr_number" + echo "APP_NAME=${REVIEW_APP_PREFIX}-$pr_number" + echo "PR_SHA=$pr_sha" + } >> "$GITHUB_ENV" echo "same_repo=${same_repo}" >> "$GITHUB_OUTPUT" - name: Validate review app deployment source @@ -303,11 +305,9 @@ jobs: - name: Update PR comment with build status if: steps.config.outputs.ready == 'true' && steps.source.outputs.allowed == 'true' && (steps.check-app.outputs.exists == 'true' || steps.setup-review-app.outcome == 'success') uses: actions/github-script@v7 - env: - COMMENT_ID: ${{ steps.create-comment.outputs.comment-id }} with: script: | - const commentId = Number(process.env.COMMENT_ID); + const commentId = Number("${{ steps.create-comment.outputs.comment-id }}"); if (!Number.isFinite(commentId) || commentId <= 0) { core.warning("Skipping PR comment update because no comment id was created."); return; @@ -344,11 +344,9 @@ jobs: - name: Update PR comment with deploy status if: steps.config.outputs.ready == 'true' && steps.source.outputs.allowed == 'true' && (steps.check-app.outputs.exists == 'true' || steps.setup-review-app.outcome == 'success') uses: actions/github-script@v7 - env: - COMMENT_ID: ${{ steps.create-comment.outputs.comment-id }} with: script: | - const commentId = Number(process.env.COMMENT_ID); + const commentId = Number("${{ steps.create-comment.outputs.comment-id }}"); if (!Number.isFinite(commentId) || commentId <= 0) { core.warning("Skipping PR comment update because no comment id was created."); return; @@ -400,17 +398,12 @@ jobs: - name: Finalize deployment status if: always() && steps.config.outputs.ready == 'true' && steps.source.outputs.allowed == 'true' && (steps.check-app.outputs.exists == 'true' || steps.setup-review-app.outcome == 'success') uses: actions/github-script@v7 - env: - COMMENT_ID: ${{ steps.create-comment.outputs.comment-id }} - DEPLOYMENT_ID: ${{ steps.init-deployment.outputs.result }} - APP_URL: ${{ steps.workload.outputs.workload_url }} - JOB_STATUS: ${{ job.status }} with: script: | - const commentId = Number(process.env.COMMENT_ID); - const deploymentId = process.env.DEPLOYMENT_ID; - const appUrl = process.env.APP_URL; - const success = process.env.JOB_STATUS === "success"; + const commentId = Number("${{ steps.create-comment.outputs.comment-id }}"); + const deploymentId = "${{ steps.init-deployment.outputs.result }}"; + const appUrl = "${{ steps.workload.outputs.workload_url }}"; + const success = "${{ job.status }}" === "success"; if (deploymentId) { await github.rest.repos.createDeploymentStatus({ diff --git a/.github/workflows/cpflow-deploy-staging.yml b/.github/workflows/cpflow-deploy-staging.yml index 076145d6b..d00e68eaf 100644 --- a/.github/workflows/cpflow-deploy-staging.yml +++ b/.github/workflows/cpflow-deploy-staging.yml @@ -56,8 +56,6 @@ jobs: - name: Checkout repository if: steps.check-branch.outputs.is_deployable == 'true' uses: actions/checkout@v4 - with: - persist-credentials: false - name: Validate required secrets and variables if: steps.check-branch.outputs.is_deployable == 'true' diff --git a/.github/workflows/cpflow-review-app-help.yml b/.github/workflows/cpflow-review-app-help.yml index f590ea607..74626217b 100644 --- a/.github/workflows/cpflow-review-app-help.yml +++ b/.github/workflows/cpflow-review-app-help.yml @@ -28,11 +28,13 @@ jobs: const body = [ "# Review app commands", "", + "Repo owners, members, and collaborators can use these commands:", + "", "- `+review-app-deploy` - create or redeploy this PR's review app.", "- `+review-app-delete` - delete this PR's review app and temporary resources.", "- `+review-app-help` - show setup details and workflow behavior.", "", - "For setup details, comment `+review-app-help`." + "For setup details, repo owners, members, and collaborators can comment `+review-app-help`." ].join("\n"); await github.rest.issues.createComment({