mirror of
https://github.com/stablyai/orca.git
synced 2026-10-31 00:57:45 +00:00
Overlap native qualification setup with the mobile bundle build (#31336)
* Prepare server native lanes alongside the shared mobile bundle * Expect read-only Actions access in template callers
This commit is contained in:
@@ -221,6 +221,7 @@ jobs:
|
||||
if: needs.orcad-template-support.outputs.ships == 'true'
|
||||
permissions:
|
||||
contents: read
|
||||
actions: read
|
||||
uses: ./.github/workflows/adhoc-orcad-template.yml
|
||||
with:
|
||||
ref: ${{ needs.resolve-ref.outputs.sha }}
|
||||
|
||||
@@ -69,6 +69,9 @@ jobs:
|
||||
retention-days: 7
|
||||
|
||||
qualify:
|
||||
permissions:
|
||||
contents: read
|
||||
actions: read
|
||||
needs: cache
|
||||
if: needs.cache.outputs.hit != 'true'
|
||||
uses: ./.github/workflows/node-server-tests.yml
|
||||
|
||||
@@ -94,6 +94,7 @@ jobs:
|
||||
needs: resolve-main
|
||||
permissions:
|
||||
contents: read
|
||||
actions: read
|
||||
uses: ./.github/workflows/node-server-tests.yml
|
||||
with:
|
||||
ref: ${{ needs.resolve-main.outputs.head_sha }}
|
||||
|
||||
@@ -122,6 +122,7 @@ jobs:
|
||||
if: needs.preflight.outputs.should_build == 'true'
|
||||
permissions:
|
||||
contents: read
|
||||
actions: read
|
||||
uses: ./.github/workflows/node-server-tests.yml
|
||||
with:
|
||||
ref: ${{ needs.preflight.outputs.head_sha }}
|
||||
|
||||
@@ -136,7 +136,10 @@ jobs:
|
||||
fi
|
||||
|
||||
persistence:
|
||||
needs: [changes, mobile_web_bundle]
|
||||
needs: changes
|
||||
permissions:
|
||||
contents: read
|
||||
actions: read
|
||||
concurrency:
|
||||
group: node-server-persistence-${{ matrix.os }}-${{ github.event_name == 'push' && !inputs.build_template && inputs.ref == '' && github.ref || github.run_id }}
|
||||
cancel-in-progress: ${{ github.event_name == 'push' && !inputs.build_template && inputs.ref == '' }}
|
||||
@@ -144,7 +147,6 @@ jobs:
|
||||
# Drafts re-trigger at readiness; inherited caller events must not depend on PR fields.
|
||||
if: >-
|
||||
${{ !cancelled() && needs.changes.outputs.should_run != 'false' &&
|
||||
(needs.changes.outputs.qualification == 'false' || needs.mobile_web_bundle.result == 'success') &&
|
||||
(github.event_name != 'pull_request' || github.event.pull_request.draft != true) }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -211,6 +213,32 @@ jobs:
|
||||
if: runner.os == 'Windows'
|
||||
with:
|
||||
arches: ${{ (inputs.build_template && matrix.os == 'windows-2022') && 'x64 arm64' || (runner.arch == 'ARM64' && 'arm64' || 'x64') }}
|
||||
- name: Wait for the qualified mobile bundle
|
||||
if: needs.changes.outputs.qualification != 'false'
|
||||
uses: actions/github-script@v8
|
||||
with: &mobile-bundle-wait
|
||||
script: |
|
||||
const deadline = Date.now() + 15 * 60_000
|
||||
while (Date.now() < deadline) {
|
||||
const jobs = await github.paginate(github.rest.actions.listJobsForWorkflowRun, {
|
||||
...context.repo, run_id: context.runId, filter: 'latest', per_page: 100
|
||||
})
|
||||
const producers = jobs.filter(job => job.name === 'mobile_web_bundle' ||
|
||||
job.name.endsWith(' / mobile_web_bundle'))
|
||||
if (producers.length > 1) throw new Error('Ambiguous mobile bundle producer')
|
||||
const producer = producers[0]
|
||||
if (producer?.status === 'completed') {
|
||||
if (producer.conclusion !== 'success') {
|
||||
throw new Error(`Mobile bundle production did not succeed: ${producer.conclusion}`)
|
||||
}
|
||||
const artifacts = await github.paginate(github.rest.actions.listWorkflowRunArtifacts, {
|
||||
...context.repo, run_id: context.runId, per_page: 100
|
||||
})
|
||||
if (artifacts.some(artifact => artifact.name === 'orcad-mobile-web-bundle' && !artifact.expired)) return
|
||||
}
|
||||
await new Promise(resolve => setTimeout(resolve, 5_000))
|
||||
}
|
||||
throw new Error('Timed out waiting for the qualified mobile bundle')
|
||||
- uses: actions/download-artifact@v8
|
||||
if: needs.changes.outputs.qualification != 'false'
|
||||
with:
|
||||
@@ -351,16 +379,19 @@ jobs:
|
||||
overwrite: true
|
||||
|
||||
linux_glibc_floor:
|
||||
needs: [changes, mobile_web_bundle]
|
||||
needs: changes
|
||||
permissions:
|
||||
contents: read
|
||||
actions: read
|
||||
concurrency:
|
||||
group: node-server-linux_glibc_floor-${{ matrix.os }}-${{ github.event_name == 'push' && !inputs.build_template && inputs.ref == '' && github.ref || github.run_id }}
|
||||
cancel-in-progress: ${{ github.event_name == 'push' && !inputs.build_template && inputs.ref == '' }}
|
||||
# Each Linux lane owns its inputs; the template still requires every lane to pass.
|
||||
if: >-
|
||||
${{ !cancelled() &&
|
||||
needs.mobile_web_bundle.result == 'success' &&
|
||||
needs.changes.outputs.should_run != 'false' &&
|
||||
needs.changes.outputs.qualification != 'false' }}
|
||||
needs.changes.outputs.qualification != 'false' &&
|
||||
(github.event_name != 'pull_request' || github.event.pull_request.draft != true) }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -407,6 +438,9 @@ jobs:
|
||||
pnpm build:orcad-prebuilds
|
||||
pnpm build:orcad-prebuilds --require-slots "$(node config/scripts/build-orcad-prebuilds.mjs --print-slot)"
|
||||
pnpm build:orcad-prebuilds --smoke
|
||||
- name: Wait for the qualified mobile bundle
|
||||
uses: actions/github-script@v8
|
||||
with: *mobile-bundle-wait
|
||||
- uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: orcad-mobile-web-bundle
|
||||
@@ -481,15 +515,18 @@ jobs:
|
||||
overwrite: true
|
||||
|
||||
linux_musl:
|
||||
needs: [changes, mobile_web_bundle]
|
||||
needs: changes
|
||||
permissions:
|
||||
contents: read
|
||||
actions: read
|
||||
concurrency:
|
||||
group: node-server-linux_musl-${{ matrix.os }}-${{ github.event_name == 'push' && !inputs.build_template && inputs.ref == '' && github.ref || github.run_id }}
|
||||
cancel-in-progress: ${{ github.event_name == 'push' && !inputs.build_template && inputs.ref == '' }}
|
||||
if: >-
|
||||
${{ !cancelled() &&
|
||||
needs.mobile_web_bundle.result == 'success' &&
|
||||
needs.changes.outputs.should_run != 'false' &&
|
||||
needs.changes.outputs.qualification != 'false' }}
|
||||
needs.changes.outputs.qualification != 'false' &&
|
||||
(github.event_name != 'pull_request' || github.event.pull_request.draft != true) }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -507,21 +544,19 @@ jobs:
|
||||
id: pnpm-verification
|
||||
with:
|
||||
container-toolchain: 'true'
|
||||
- uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: orcad-mobile-web-bundle
|
||||
path: out/mobile-web
|
||||
- name: Verify native Alpine artifact and persistence
|
||||
- name: Prepare native Alpine artifact
|
||||
env:
|
||||
VERIFICATION_CACHE_PATH: ${{ steps.pnpm-verification.outputs.path }}
|
||||
run: |
|
||||
touch "$VERIFICATION_CACHE_PATH"
|
||||
mkdir -p out/mobile-web
|
||||
# Multi-arch index digest of the tag; re-resolve it whenever NODE_RUNTIME_PIN moves.
|
||||
docker run --rm --init -i \
|
||||
docker run --rm --init --detach --name orcad-alpine \
|
||||
-e ORCA_BACKGROUND_LAUNCH=1 \
|
||||
-v "$VERIFICATION_CACHE_PATH:/root/.cache/pnpm/lockfile-verified.jsonl" \
|
||||
-v "$GITHUB_WORKSPACE:/work" -w /work \
|
||||
node:24.21.0-alpine@sha256:ebfe2f90462722a7a4de65e91990e97fe0d401c70e0e762c5b53302f905ec1c1 sh -s <<'NODE_SERVER_QUALIFICATION'
|
||||
node:24.21.0-alpine@sha256:ebfe2f90462722a7a4de65e91990e97fe0d401c70e0e762c5b53302f905ec1c1 sleep infinity
|
||||
docker exec -i orcad-alpine sh -s <<'NODE_SERVER_PREPARATION'
|
||||
set -eu
|
||||
apk add --no-cache bash git libstdc++ python3 make g++
|
||||
git config --global --add safe.directory /work
|
||||
@@ -530,9 +565,24 @@ jobs:
|
||||
pnpm build:orcad-prebuilds
|
||||
pnpm build:orcad-prebuilds --require-slots "$(node config/scripts/build-orcad-prebuilds.mjs --print-slot)"
|
||||
pnpm build:orcad-prebuilds --smoke
|
||||
NODE_SERVER_PREPARATION
|
||||
- name: Wait for the qualified mobile bundle
|
||||
uses: actions/github-script@v8
|
||||
with: *mobile-bundle-wait
|
||||
- uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: orcad-mobile-web-bundle
|
||||
path: out/mobile-web
|
||||
- name: Verify native Alpine artifact and persistence
|
||||
run: |
|
||||
docker exec -i orcad-alpine sh -s <<'NODE_SERVER_QUALIFICATION'
|
||||
set -eu
|
||||
pnpm build:orcad
|
||||
pnpm test:node-server --artifact
|
||||
NODE_SERVER_QUALIFICATION
|
||||
- name: Clean up the Alpine qualification container
|
||||
if: always()
|
||||
run: docker rm --force orcad-alpine
|
||||
- name: Keep this runner's musl slot for the desktop template
|
||||
if: inputs.build_template
|
||||
uses: actions/upload-artifact@v7
|
||||
|
||||
@@ -1183,6 +1183,7 @@ jobs:
|
||||
if: needs.cut.outputs.should_release == 'true' && needs.cut.outputs.ships_orcad_template == 'true'
|
||||
permissions:
|
||||
contents: read
|
||||
actions: read
|
||||
uses: ./.github/workflows/node-server-tests.yml
|
||||
with:
|
||||
ref: refs/tags/${{ needs.cut.outputs.tag }}
|
||||
|
||||
@@ -39,6 +39,7 @@ jobs:
|
||||
if: inputs.qualification_only
|
||||
permissions:
|
||||
contents: read
|
||||
actions: read
|
||||
uses: ./.github/workflows/node-server-tests.yml
|
||||
with:
|
||||
ref: ${{ github.sha }}
|
||||
|
||||
@@ -34,7 +34,7 @@ describe.each(channels)('$name build ships the orcad template', (channel) => {
|
||||
const template = jobs['orcad-template']
|
||||
expect(template.uses).toBe('./.github/workflows/node-server-tests.yml')
|
||||
expect(template.with).toEqual({ ref: channel.pinnedSha, build_template: true })
|
||||
expect(template.permissions).toEqual({ contents: 'read' })
|
||||
expect(template.permissions).toEqual({ contents: 'read', actions: 'read' })
|
||||
expect(template.secrets).toBeUndefined()
|
||||
expect(mac.steps.find((step) => step.name === 'Checkout').with.ref).toBe(channel.pinnedSha)
|
||||
})
|
||||
|
||||
@@ -571,10 +571,12 @@ it('keeps every platform job and runs them when detection is skipped or fails',
|
||||
expect(workflow.jobs.persistence.strategy.matrix.os).toContain('needs.changes.outputs.runners')
|
||||
for (const jobName of ['linux_glibc_floor', 'linux_musl']) {
|
||||
const job = workflow.jobs[jobName]
|
||||
expect(job.needs).toEqual(['changes', 'mobile_web_bundle'])
|
||||
expect(job.needs).toBe('changes')
|
||||
// The containers never install mobile/, and orcad refuses to build without the page.
|
||||
expect(job.steps.some((step) => step.with?.name === 'orcad-mobile-web-bundle')).toBe(true)
|
||||
expect(job.if).toContain("needs.mobile_web_bundle.result == 'success'")
|
||||
expect(job.steps.some((step) => step.name === 'Wait for the qualified mobile bundle')).toBe(
|
||||
true
|
||||
)
|
||||
expect(job.if).not.toContain('needs.persistence')
|
||||
expect(job.if).toContain("needs.changes.outputs.qualification != 'false'")
|
||||
expect(job.if).toContain("needs.changes.outputs.should_run != 'false'")
|
||||
|
||||
@@ -329,10 +329,7 @@ it('builds server glibc slots on glibc 2.28 and the compat slot on glibc 2.17 (d
|
||||
|
||||
const compat = workflow.jobs.linux_glibc217_compat
|
||||
expect(compat.needs).toBe('changes')
|
||||
// Only the floor builds orcad, so only it waits for the page.
|
||||
expect(compat.if).toContain(
|
||||
floor.if.slice(0, -3).replace(" && needs.mobile_web_bundle.result == 'success'", '')
|
||||
)
|
||||
expect(compat.if).toContain(floor.if.slice(0, -3))
|
||||
expect(compat.if).toContain("needs.changes.outputs.native_compatibility != 'false'")
|
||||
expect(compat.if).toContain(
|
||||
"github.event_name != 'pull_request' || inputs.build_template || inputs.ref != ''"
|
||||
|
||||
@@ -21,17 +21,17 @@ function context({ qualification, producer = 'success', event = 'pull_request',
|
||||
it.each([
|
||||
{ qualification: 'true', producer: 'success', expected: true },
|
||||
{ qualification: '', producer: 'success', expected: true },
|
||||
{ qualification: 'true', producer: 'failure', expected: false },
|
||||
{ qualification: 'true', producer: 'cancelled', expected: false },
|
||||
{ qualification: 'true', producer: 'skipped', expected: false },
|
||||
{ qualification: '', producer: 'skipped', expected: false },
|
||||
{ qualification: 'true', producer: 'failure', expected: true },
|
||||
{ qualification: 'true', producer: 'cancelled', expected: true },
|
||||
{ qualification: 'true', producer: 'skipped', expected: true },
|
||||
{ qualification: '', producer: 'skipped', expected: true },
|
||||
{ qualification: 'false', producer: 'skipped', expected: true },
|
||||
{ qualification: 'false', producer: 'skipped', draft: true, expected: false },
|
||||
{ producer: 'success', event: 'workflow_dispatch', expected: true },
|
||||
{ producer: 'success', event: 'schedule', expected: true }
|
||||
])('preserves mobile producer failure and test-only behavior: %j', (scenario) => {
|
||||
])('starts native setup independently while retaining test-only behavior: %j', (scenario) => {
|
||||
const ctx = context(scenario)
|
||||
expect(persistence.needs).toEqual(['changes', 'mobile_web_bundle'])
|
||||
expect(persistence.needs).toBe('changes')
|
||||
expect(shouldPersist(ctx).coerceString()).toBe(String(scenario.expected))
|
||||
expect(shouldPersist(ctx, true).coerceString()).toBe('false')
|
||||
})
|
||||
@@ -111,3 +111,121 @@ it('avoids template download-cache transfers while retaining native and verifica
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const mobileWait = persistence.steps.find(
|
||||
(step) => step.name === 'Wait for the qualified mobile bundle'
|
||||
)
|
||||
const AsyncFunction = Object.getPrototypeOf(async () => {}).constructor
|
||||
|
||||
function waitForMobile(snapshots) {
|
||||
let now = 0
|
||||
let index = 0
|
||||
const calls = []
|
||||
const github = {
|
||||
rest: { actions: { listJobsForWorkflowRun: 'jobs', listWorkflowRunArtifacts: 'artifacts' } },
|
||||
async paginate(endpoint, input) {
|
||||
calls.push({ endpoint, input })
|
||||
return snapshots[Math.min(index, snapshots.length - 1)][endpoint] ?? []
|
||||
}
|
||||
}
|
||||
const execute = new AsyncFunction(
|
||||
'github',
|
||||
'context',
|
||||
'Date',
|
||||
'setTimeout',
|
||||
mobileWait.with.script
|
||||
)
|
||||
return {
|
||||
calls,
|
||||
result: execute(
|
||||
github,
|
||||
{ repo: { owner: 'owner', repo: 'repo' }, runId: 42 },
|
||||
{ now: () => now },
|
||||
(resolve, delay) => {
|
||||
now += delay
|
||||
index++
|
||||
resolve()
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const mobileProducer = (conclusion, prefix = 'orcad-template / qualify / ') => ({
|
||||
name: `${prefix}mobile_web_bundle`,
|
||||
status: conclusion ? 'completed' : 'in_progress',
|
||||
conclusion
|
||||
})
|
||||
const mobileArtifact = { name: 'orcad-mobile-web-bundle', expired: false }
|
||||
|
||||
it.each(['', 'orcad-template / ', 'orcad-template / qualify / '])(
|
||||
'waits for the same-run producer to succeed before accepting its artifact (%s)',
|
||||
async (prefix) => {
|
||||
const { result, calls } = waitForMobile([
|
||||
{ artifacts: [mobileArtifact] },
|
||||
{ jobs: [mobileProducer(undefined, prefix)], artifacts: [mobileArtifact] },
|
||||
{
|
||||
jobs: [mobileProducer('success', prefix)],
|
||||
artifacts: [{ ...mobileArtifact, expired: true }]
|
||||
},
|
||||
{ jobs: [mobileProducer('success', prefix)], artifacts: [mobileArtifact] }
|
||||
])
|
||||
await result
|
||||
expect(calls.filter((call) => call.endpoint === 'jobs')).toHaveLength(4)
|
||||
expect(calls.filter((call) => call.endpoint === 'artifacts')).toHaveLength(2)
|
||||
expect(calls.every((call) => call.input.run_id === 42)).toBe(true)
|
||||
expect(
|
||||
calls
|
||||
.filter((call) => call.endpoint === 'jobs')
|
||||
.every((call) => call.input.filter === 'latest')
|
||||
).toBe(true)
|
||||
}
|
||||
)
|
||||
|
||||
it.each(['failure', 'cancelled', 'skipped', 'timed_out', 'action_required', 'startup_failure'])(
|
||||
'rejects a %s producer even when an earlier attempt left an artifact',
|
||||
async (conclusion) => {
|
||||
await expect(
|
||||
waitForMobile([{ jobs: [mobileProducer(conclusion)], artifacts: [mobileArtifact] }]).result
|
||||
).rejects.toThrow('Mobile bundle production did not succeed')
|
||||
}
|
||||
)
|
||||
|
||||
it('fails closed when the producer is missing or ambiguous', async () => {
|
||||
await expect(waitForMobile([{}]).result).rejects.toThrow('Timed out')
|
||||
await expect(
|
||||
waitForMobile([{ jobs: [mobileProducer('success'), mobileProducer('success', '')] }]).result
|
||||
).rejects.toThrow('Ambiguous')
|
||||
})
|
||||
|
||||
it('prepares every native lane before waiting and builds with the shared page afterward', () => {
|
||||
for (const name of ['persistence', 'linux_glibc_floor', 'linux_musl']) {
|
||||
const job = workflow.jobs[name]
|
||||
const wait = job.steps.findIndex((step) => step.name === mobileWait.name)
|
||||
const download = job.steps.findIndex((step) => step.with?.name === mobileArtifact.name)
|
||||
const prepare = job.steps.findIndex(
|
||||
(step) =>
|
||||
step.uses?.includes('prepare-orcad-prebuilds') ||
|
||||
step.run?.includes('pnpm build:orcad-prebuilds')
|
||||
)
|
||||
expect(job.needs).toBe('changes')
|
||||
expect(prepare).toBeGreaterThan(-1)
|
||||
expect(prepare).toBeLessThan(wait)
|
||||
expect(wait).toBeLessThan(download)
|
||||
expect(job.steps[wait].with.script).toBe(mobileWait.with.script)
|
||||
expect(job.permissions).toEqual({ contents: 'read', actions: 'read' })
|
||||
}
|
||||
const alpine = workflow.jobs.linux_musl.steps
|
||||
const prepare = alpine.find((step) => step.name === 'Prepare native Alpine artifact')
|
||||
const verify = alpine.find(
|
||||
(step) => step.name === 'Verify native Alpine artifact and persistence'
|
||||
)
|
||||
const cleanup = alpine.find((step) => step.name === 'Clean up the Alpine qualification container')
|
||||
expect(prepare.run).toContain('mkdir -p out/mobile-web')
|
||||
expect(prepare.run).toContain('--detach --name orcad-alpine')
|
||||
expect(prepare.run).toContain('docker exec -i orcad-alpine')
|
||||
expect(prepare.run).not.toContain('pnpm build:orcad\n')
|
||||
expect(verify.run).toContain('docker exec -i orcad-alpine')
|
||||
expect(verify.run).toContain('pnpm build:orcad\n')
|
||||
expect(verify.run).toContain('pnpm test:node-server --artifact')
|
||||
expect(cleanup.if).toBe('always()')
|
||||
})
|
||||
|
||||
@@ -19,12 +19,18 @@ const EXPECTED_MATRIX = {
|
||||
'.github/workflows/node-server-tests.yml#changes': { contents: 'read' },
|
||||
'.github/workflows/node-server-tests.yml#desktop_template': { contents: 'read' },
|
||||
'.github/workflows/node-server-tests.yml#linux_glibc217_compat': { contents: 'read' },
|
||||
'.github/workflows/node-server-tests.yml#linux_glibc_floor': { contents: 'read' },
|
||||
'.github/workflows/node-server-tests.yml#linux_musl': { contents: 'read' },
|
||||
'.github/workflows/node-server-tests.yml#linux_glibc_floor': {
|
||||
actions: 'read',
|
||||
contents: 'read'
|
||||
},
|
||||
'.github/workflows/node-server-tests.yml#linux_musl': { actions: 'read', contents: 'read' },
|
||||
'.github/workflows/node-server-tests.yml#mobile_web_bundle': { contents: 'read' },
|
||||
'.github/workflows/node-server-tests.yml#persistence': { contents: 'read' },
|
||||
'.github/workflows/node-server-tests.yml#persistence': { actions: 'read', contents: 'read' },
|
||||
'.github/workflows/release-mac-build.yml#build-mac': { actions: 'read', contents: 'write' },
|
||||
'.github/workflows/release-mac-build.yml#qualification-template': { contents: 'read' },
|
||||
'.github/workflows/release-mac-build.yml#qualification-template': {
|
||||
actions: 'read',
|
||||
contents: 'read'
|
||||
},
|
||||
...Object.fromEntries(
|
||||
[
|
||||
'changes',
|
||||
@@ -36,7 +42,9 @@ const EXPECTED_MATRIX = {
|
||||
'persistence'
|
||||
].map((job) => [
|
||||
`.github/workflows/release-mac-build.yml#qualification-template -> .github/workflows/node-server-tests.yml#${job}`,
|
||||
{ contents: 'read' }
|
||||
['persistence', 'linux_glibc_floor', 'linux_musl'].includes(job)
|
||||
? { actions: 'read', contents: 'read' }
|
||||
: { contents: 'read' }
|
||||
])
|
||||
),
|
||||
[`${RELEASE_WORKFLOW}#build`]: { actions: 'read', contents: 'write' },
|
||||
@@ -54,7 +62,7 @@ const EXPECTED_MATRIX = {
|
||||
{
|
||||
contents: 'read'
|
||||
},
|
||||
[`${RELEASE_WORKFLOW}#orcad-template`]: { contents: 'read' },
|
||||
[`${RELEASE_WORKFLOW}#orcad-template`]: { actions: 'read', contents: 'read' },
|
||||
[`${RELEASE_WORKFLOW}#orcad-template -> .github/workflows/node-server-tests.yml#changes`]: {
|
||||
contents: 'read'
|
||||
},
|
||||
@@ -68,9 +76,11 @@ const EXPECTED_MATRIX = {
|
||||
},
|
||||
[`${RELEASE_WORKFLOW}#orcad-template -> .github/workflows/node-server-tests.yml#linux_glibc_floor`]:
|
||||
{
|
||||
actions: 'read',
|
||||
contents: 'read'
|
||||
},
|
||||
[`${RELEASE_WORKFLOW}#orcad-template -> .github/workflows/node-server-tests.yml#linux_musl`]: {
|
||||
actions: 'read',
|
||||
contents: 'read'
|
||||
},
|
||||
[`${RELEASE_WORKFLOW}#orcad-template -> .github/workflows/node-server-tests.yml#mobile_web_bundle`]:
|
||||
@@ -78,6 +88,7 @@ const EXPECTED_MATRIX = {
|
||||
contents: 'read'
|
||||
},
|
||||
[`${RELEASE_WORKFLOW}#orcad-template -> .github/workflows/node-server-tests.yml#persistence`]: {
|
||||
actions: 'read',
|
||||
contents: 'read'
|
||||
},
|
||||
[`${RELEASE_WORKFLOW}#post-release-e2e`]: { actions: 'write' },
|
||||
@@ -237,7 +248,11 @@ describe('release-cut token permissions', () => {
|
||||
expect(tagJobs.map(([jobName]) => jobName).sort()).toEqual(RELEASE_TAG_EXECUTION_JOBS)
|
||||
for (const [jobName] of tagJobs) {
|
||||
if (!PUBLISH_TAG_JOBS.has(jobName)) {
|
||||
expect(matrix[`${RELEASE_WORKFLOW}#${jobName}`]).toEqual({ contents: 'read' })
|
||||
expect(matrix[`${RELEASE_WORKFLOW}#${jobName}`]).toEqual(
|
||||
jobName === 'orcad-template'
|
||||
? { actions: 'read', contents: 'read' }
|
||||
: { contents: 'read' }
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user