Dashboard › publish › Session 1b6s9EggNI14
1b6s9EggNI14NX00LREAD ONLY. In /home/byk/Code/getsentry/publish, compare HEAD/current worktree/origin/main for only these upstream-overlapping workflow files: .github/workflows/ci-poller.yml, .github/workflows/publish.yml, .github/workflows/cocoapods-keepalive.yml, plus upstream workflow tests under src/modules/tests/ci-poller-workflow.js and publish-workflow.js. Explain every origin/main behavior that must be integrated into the current dirty worktree, identify conflicts with current security hardening, and propose exact merged step ordering/variables. Do not edit files. Return concise file-specific guidance and security risks.
<path>/home/byk/Code/getsentry/publish</path> <type>directory</type> <entries> .eslintrc.js .git/ .github/ .gitignore .lore.md AGENTS.md auto-approve-repos.txt docs/ LICENSE node_modules/ package.json README.md src/ vitest.config.js yarn.lock (15 entries) </entries>
## main...origin/main [behind 1] M .github/workflows/ci-poller.yml M .github/workflows/cocoapods-keepalive.yml M .github/workflows/publish.yml
83d210b29553ea6f4d97508821724a834c43856e 7c60ddb7f43040fe8fbfea70efc833f689c04e75 7c60ddb (origin/main, origin/HEAD) feat: accept workspace publish requests
.github/workflows/ci-poller.yml | 62 +++++---- .github/workflows/cocoapods-keepalive.yml | 2 +- .github/workflows/publish.yml | 84 ++++++------ src/modules/__tests__/ci-poller-workflow.js | 197 ++++++++++++++++++++++++++++ src/modules/__tests__/publish-workflow.js | 156 ++++++++++++++++++++++ 5 files changed, 435 insertions(+), 66 deletions(-) .github/workflows/ci-poller.yml | 195 ++++++++++++++++++++++++++---- .github/workflows/cocoapods-keepalive.yml | 3 +- .github/workflows/publish.yml | 139 +++++++++++++++++++-- 3 files changed, 304 insertions(+), 33 deletions(-) .github/workflows/ci-poller.yml | 245 ++++++++++++++++++++++------ .github/workflows/cocoapods-keepalive.yml | 1 - .github/workflows/publish.yml | 219 +++++++++++++++++++------ src/modules/__tests__/ci-poller-workflow.js | 197 ---------------------- src/modules/__tests__/publish-workflow.js | 156 ------------------ 5 ...
<path>/home/byk/Code/getsentry/publish/.github/workflows/ci-poller.yml</path> <type>file</type> <content> 1: name: CI Status Poller 2: 3: on: 4: schedule: 5: - cron: "*/5 * * * *" 6: repository_dispatch: 7: types: [ci-poller] 8: workflow_run: 9: workflows: [Run CI Status Poller] 10: types: [completed] 11: 12: permissions: 13: contents: read 14: issues: write 15: 16: jobs: 17: check-ci: 18: runs-on: ubuntu-latest 19: environment: production 20: # Skip entirely (no runner provisioned) when there's nothing to check. 21: # Set to "true" by ci-pending.yml, reset to "false" here when done. 22: # repository_dispatch and a successful main-branch run of the protected 23: # workflow_dispatch relay are the trusted manual-recovery paths. 24: if: >- 25: vars.CI_POLLER_HAS_PENDING == 'true' 26: || github.event_name == 'repository_dispatch' 27: || ( 28: github.event_name == 'workflow_run' 29: && ...
<path>/home/byk/Code/getsentry/publish/.github/workflows/publish.yml</path>
<type>file</type>
<content>
1: name: Publish
2: on:
3: issues:
4: types: [labeled]
5:
6: concurrency:
7: # Use the issue title (e.g. "publish: getsentry/foo@1.2.3") so duplicate
8: # issues for the same repo@version share a concurrency group.
9: group: ${{ github.event.issue.title }}
10: cancel-in-progress: false
11:
12: permissions:
13: contents: read
14: issues: write
15: packages: write
16:
17: jobs:
18: # When accepted is added to a publish issue:
19: # - Add ci-pending (and remove ci-failed if retrying)
20: # - Enable the poller via CI_POLLER_HAS_PENDING=true
21: # - Comment on the issue
22: # - Trigger the poller immediately so we don't wait for the next cron tick
23: # The publish job below requires ci-ready, so it will not fire until the
24: # poller flips ci-pending → ci-ready (which also prevents publishing without
25: # CI verification in the ...
<path>/home/byk/Code/getsentry/publish/.github/workflows/cocoapods-keepalive.yml</path>
<type>file</type>
<content>
1: name: CocoaPods Token Keep-Alive
2:
3: on:
4: schedule:
5: # CocoaPods sessions currently expire after 3 days of inactivity (VALIDITY_LENGTH)
6: # This runs every day at midnight UTC to keep the current token alive
7: # See: https://github.com/CocoaPods/trunk.cocoapods.org/blob/a1869790e9ae2229b6985b6af4532da814202558/app/models/session.rb#L9
8: - cron: "0 0 * * *" # Runs every day at midnight UTC
9:
10: permissions:
11: contents: read
12:
13: jobs:
14: keepalive:
15: name: Refresh CocoaPods Session
16: runs-on: macos-15
17: environment: production
18: env:
19: COCOAPODS_TRUNK_TOKEN: ${{ secrets.COCOAPODS_TRUNK_TOKEN }}
20:
21: steps:
22: - name: Install CocoaPods
23: run: gem install cocoapods
24: - name: Print CocoaPods Version
25: run: pod --version
26: - name: Refresh CocoaPods ...
diff --git a/.github/workflows/ci-poller.yml b/.github/workflows/ci-poller.yml
index a3db430..487e9da 100644
--- a/.github/workflows/ci-poller.yml
+++ b/.github/workflows/ci-poller.yml
@@ -1,314 +1,324 @@
name: CI Status Poller
on:
schedule:
- cron: "*/5 * * * *"
workflow_dispatch:
inputs:
attempt:
description: Self-dispatch attempt counter (internal use)
required: false
default: "0"
permissions:
contents: read
issues: read
jobs:
check-ci:
runs-on: ubuntu-latest
environment: production
# Skip entirely (no runner provisioned) when there's nothing to check.
# Set to "true" by ci-pending.yml, reset to "false" here when done.
# Always allow workflow_dispatch for manual recovery.
if: vars.CI_POLLER_HAS_PENDING == 'true' || github.event_name == 'workflow_dispatch'
concurrency:
group: ci-status-poller
cancel-in-progress: false
steps:
# sentry-internal-app token ...
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index cff6bc3..2635ea6 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -20,293 +20,299 @@ jobs:
# - Enable the poller via CI_POLLER_HAS_PENDING=true
# - Comment on the issue
# - Trigger the poller immediately so we don't wait for the next cron tick
# The publish job below requires ci-ready, so it will not fire until the
# poller flips ci-pending → ci-ready (which also prevents publishing without
# CI verification in the auto-approve race).
waiting-for-ci:
runs-on: ubuntu-latest
name: Waiting for CI
environment: production
if: >-
github.event.label.name == 'accepted'
&& github.event.issue.state == 'open'
&& startsWith(github.event.issue.title, 'publish: ')
steps:
- name: Get auth token
id: token
uses: actions/create-github-app-token@v3
with:
client-id: ${{ ...
diff --git a/.github/workflows/cocoapods-keepalive.yml b/.github/workflows/cocoapods-keepalive.yml
index 21c0696..9c11b0e 100644
--- a/.github/workflows/cocoapods-keepalive.yml
+++ b/.github/workflows/cocoapods-keepalive.yml
@@ -1,28 +1,28 @@
-name: "CocoaPods Token Keep-Alive"
+name: CocoaPods Token Keep-Alive
on:
schedule:
# CocoaPods sessions currently expire after 3 days of inactivity (VALIDITY_LENGTH)
# This runs every day at midnight UTC to keep the current token alive
# See: https://github.com/CocoaPods/trunk.cocoapods.org/blob/a1869790e9ae2229b6985b6af4532da814202558/app/models/session.rb#L9
- cron: "0 0 * * *" # Runs every day at midnight UTC
workflow_dispatch:
permissions:
contents: read
jobs:
keepalive:
name: Refresh CocoaPods Session
runs-on: macos-15
environment: production
env:
COCOAPODS_TRUNK_TOKEN: ${{ secrets.COCOAPODS_TRUNK_TOKEN }}
steps:
- name: Install CocoaPods
run: gem ...
diff --git a/.github/workflows/cocoapods-keepalive.yml b/.github/workflows/cocoapods-keepalive.yml
index 21c0696..ffa5982 100644
--- a/.github/workflows/cocoapods-keepalive.yml
+++ b/.github/workflows/cocoapods-keepalive.yml
@@ -1,28 +1,27 @@
-name: "CocoaPods Token Keep-Alive"
+name: CocoaPods Token Keep-Alive
on:
schedule:
# CocoaPods sessions currently expire after 3 days of inactivity (VALIDITY_LENGTH)
# This runs every day at midnight UTC to keep the current token alive
# See: https://github.com/CocoaPods/trunk.cocoapods.org/blob/a1869790e9ae2229b6985b6af4532da814202558/app/models/session.rb#L9
- cron: "0 0 * * *" # Runs every day at midnight UTC
- workflow_dispatch:
permissions:
contents: read
jobs:
keepalive:
name: Refresh CocoaPods Session
runs-on: macos-15
environment: production
env:
COCOAPODS_TRUNK_TOKEN: ${{ secrets.COCOAPODS_TRUNK_TOKEN }}
steps:
- name: Install CocoaPods
run: gem ...
import {
mkdtempSync,
mkdirSync,
readFileSync,
readdirSync,
rmSync,
writeFileSync,
} from "fs";
import { tmpdir } from "os";
import { join } from "path";
import { spawnSync } from "child_process";
import { afterEach, expect, test } from "vitest";
const temporaryDirectories = [];
const INITIAL_REVISION = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
const UPDATED_REVISION = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
function getPollerScript() {
const workflow = readFileSync(
join(__dirname, "../../../.github/workflows/ci-poller.yml"),
"utf8"
);
const section = workflow.match(
/ {6}- name: Check CI status for ci-pending issues[\s\S]*? {8}run: \|\n(?<script>[\s\S]*?)\n {6}- name: Check for remaining pending issues/
);
if (!section?.groups?.script) {
throw new Error("Missing CI poller workflow script");
}
return section.groups.script.replace(/^ {10}/gm, "");
}
function writeExecutable(path, content) {
writeFileSync(path, content, { mode: ...
import { spawnSync } from "child_process";
import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "fs";
import { tmpdir } from "os";
import { join } from "path";
import { afterEach, expect, test } from "vitest";
const { resolvePublishLocation } = require("../publish-location.js");
const temporaryDirectories = [];
function getWorkflow() {
return readFileSync(
join(__dirname, "../../../.github/workflows/publish.yml"),
"utf8"
);
}
function getSetTargetsScript() {
const workflow = getWorkflow();
const section = workflow.match(
/ {6}- name: Set targets[\s\S]*? {8}run: \|\n(?<script>[\s\S]*?)\n {6}- uses: docker:\/\/getsentry\/craft:latest/
);
if (!section?.groups?.script) {
throw new Error("Missing Set targets workflow script");
}
return section.groups.script.replace(/^ {10}/gm, "");
}
function runSetTargets({ path, repo, version, workspace = "" }) {
const directory = mkdtempSync(join(tmpdir(), "publish-workflow-test-"));
...
diff --git a/.github/workflows/ci-poller.yml b/.github/workflows/ci-poller.yml
index a3db430..f734db7 100644
--- a/.github/workflows/ci-poller.yml
+++ b/.github/workflows/ci-poller.yml
@@ -1,314 +1,463 @@
name: CI Status Poller
on:
schedule:
- cron: "*/5 * * * *"
- workflow_dispatch:
- inputs:
- attempt:
- description: Self-dispatch attempt counter (internal use)
- required: false
- default: "0"
+ repository_dispatch:
+ types: [ci-poller]
+ workflow_run:
+ workflows: [Run CI Status Poller]
+ types: [completed]
permissions:
contents: read
- issues: read
+ issues: write
jobs:
check-ci:
runs-on: ubuntu-latest
environment: production
# Skip entirely (no runner provisioned) when there's nothing to check.
# Set to "true" by ci-pending.yml, reset to "false" here when done.
- # Always allow workflow_dispatch for manual recovery.
- if: vars.CI_POLLER_HAS_PENDING == 'true' || github.event_name == ...
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index cff6bc3..9ff9a9d 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -1,310 +1,433 @@
name: Publish
on:
issues:
types: [labeled]
concurrency:
# Use the issue title (e.g. "publish: getsentry/foo@1.2.3") so duplicate
# issues for the same repo@version share a concurrency group.
group: ${{ github.event.issue.title }}
cancel-in-progress: false
permissions:
contents: read
issues: write
packages: write
jobs:
# When accepted is added to a publish issue:
# - Add ci-pending (and remove ci-failed if retrying)
# - Enable the poller via CI_POLLER_HAS_PENDING=true
# - Comment on the issue
# - Trigger the poller immediately so we don't wait for the next cron tick
# The publish job below requires ci-ready, so it will not fire until the
# poller flips ci-pending → ci-ready (which also prevents publishing without
# CI ...
origin/main:.github/workflows/ci-poller.yml:51: - name: Check out publish controller
origin/main:.github/workflows/ci-poller.yml:54: path: .__publish__
origin/main:.github/workflows/ci-poller.yml:96: (
origin/main:.github/workflows/ci-poller.yml:99: body_file=$(mktemp)
origin/main:.github/workflows/ci-poller.yml:100: resolver_output_file=""
origin/main:.github/workflows/ci-poller.yml:101: updated_body_file=""
origin/main:.github/workflows/ci-poller.yml:102: trap 'for file in "${body_file:-}" "${resolver_output_file:-}" "${updated_body_file:-}"; do [[ -z "$file" ]] || rm -f "$file"; done' EXIT
origin/main:.github/workflows/ci-poller.yml:105: if ! publish_input=$(PUBLISH_ISSUE_BODY_FILE="$body_file" PUBLISH_TITLE="$title" \
origin/main:.github/workflows/ci-poller.yml:106: node .__publish__/src/publish/resolve-ci-poller-input.js); then
origin/main:.github/workflows/ci-poller.yml:150: ...
origin/main:.github/workflows/publish.yml:120: uses: actions/checkout@v7
origin/main:.github/workflows/publish.yml:138: - name: Resolve CI-approved release revision
origin/main:.github/workflows/publish.yml:139: id: release-revision
origin/main:.github/workflows/publish.yml:142: PUBLISH_ISSUE_BODY: ${{ github.event.issue.body }}
origin/main:.github/workflows/publish.yml:143: run: node .__publish__/src/publish/resolve-release-revision.js
origin/main:.github/workflows/publish.yml:146: if: steps.inputs.outcome == 'success' && steps.release-revision.outcome == 'success'
origin/main:.github/workflows/publish.yml:159: - uses: actions/checkout@v7
origin/main:.github/workflows/publish.yml:164: ref: ${{ steps.release-revision.outputs.revision }}
origin/main:.github/workflows/publish.yml:169: - name: Resolve publish location
origin/main:.github/workflows/publish.yml:173: PUBLISH_REPOSITORY_DIRECTORY: ...
origin/main:src/modules/__tests__/ci-poller-workflow.js:43: const temporaryFiles = join(directory, "temporary-files");
origin/main:src/modules/__tests__/ci-poller-workflow.js:47: mkdirSync(temporaryFiles);
origin/main:src/modules/__tests__/ci-poller-workflow.js:134: TEMPORARY_FILES: temporaryFiles,
origin/main:src/modules/__tests__/ci-poller-workflow.js:142: temporaryFiles: readdirSync(temporaryFiles).filter(file => file !== "counter"),
origin/main:src/modules/__tests__/ci-poller-workflow.js:152:test("skips an issue without editing it when the poller resolver fails", () => {
origin/main:src/modules/__tests__/ci-poller-workflow.js:157: expect(poller.temporaryFiles).toEqual([]);
origin/main:src/modules/__tests__/ci-poller-workflow.js:160:test("skips an issue without editing it when the rewrite response has no body", () => {
origin/main:src/modules/__tests__/ci-poller-workflow.js:165: ...