Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
141 changes: 141 additions & 0 deletions .github/workflows/diagnose-token.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
name: diagnose-token

# Diagnostic: isolate whether the default GITHUB_TOKEN can create a branch ref,
# a tag ref, and a release in this repo. Mirrors the token context that the
# release-please job uses (push/PR event, same repo, contents: write).
# Temporary — delete once we've identified what release creation is blocked on.

on:
pull_request:
branches:
- master
push:
branches:
- diagnose-token-tag-permissions
workflow_dispatch:

permissions:
contents: write
pull-requests: write

jobs:
diagnose:
runs-on: ubuntu-latest
steps:
- uses: actions/github-script@v7
with:
script: |
const sha = context.sha;
const id = context.runId;
const owner = context.repo.owner;
const repo = context.repo.repo;
const results = [];

async function probe(label, fn, cleanup) {
try {
const res = await fn();
results.push(`✅ ${label}: OK`);
if (cleanup) {
try { await cleanup(res); } catch (e) { core.warning(`cleanup failed for ${label}: ${e.status} ${e.message}`); }
}
} catch (e) {
results.push(`❌ ${label}: ${e.status} ${e.message}`);
}
}

// 1. Control: create a branch ref (refs/heads/...) — PRs already prove this works.
await probe(
'create branch ref (refs/heads)',
() => github.rest.git.createRef({ owner, repo, ref: `refs/heads/zzz-diag-branch-${id}`, sha }),
() => github.rest.git.deleteRef({ owner, repo, ref: `heads/zzz-diag-branch-${id}` })
);

// 2. Create a tag ref (refs/tags/...) directly.
await probe(
'create tag ref (refs/tags)',
() => github.rest.git.createRef({ owner, repo, ref: `refs/tags/zzz-diag-tag-${id}`, sha }),
() => github.rest.git.deleteRef({ owner, repo, ref: `tags/zzz-diag-tag-${id}` })
);

// 3. Create a release (auto-creates its tag) — non-version tag name.
await probe(
'create release, non-version tag (zzz-diag-release)',
() => github.rest.repos.createRelease({ owner, repo, tag_name: `zzz-diag-release-${id}`, target_commitish: sha, name: 'diagnostic', body: 'diagnostic', draft: false, prerelease: true }),
async (res) => {
await github.rest.repos.deleteRelease({ owner, repo, release_id: res.data.id });
await github.rest.git.deleteRef({ owner, repo, ref: `tags/zzz-diag-release-${id}` });
}
);

// 4. Create a VERSION-style tag ref (v*) — does a ruleset target release tags?
await probe(
'create version tag ref (refs/tags/v0.0.0-diag)',
() => github.rest.git.createRef({ owner, repo, ref: `refs/tags/v0.0.0-diag-${id}`, sha }),
() => github.rest.git.deleteRef({ owner, repo, ref: `tags/v0.0.0-diag-${id}` })
);

// 5. Create a release with a VERSION-style tag — the shape release-please uses.
await probe(
'create release, version tag (v0.0.0-diag)',
() => github.rest.repos.createRelease({ owner, repo, tag_name: `v0.0.0-diag-${id}`, target_commitish: sha, name: 'diagnostic', body: 'diagnostic', draft: false, prerelease: true, make_latest: 'false' }),
async (res) => {
await github.rest.repos.deleteRelease({ owner, repo, release_id: res.data.id });
await github.rest.git.deleteRef({ owner, repo, ref: `tags/v0.0.0-diag-${id}` });
}
);

// 6. Exact release-please mirror: non-prerelease, make_latest=true.
await probe(
'create release, EXACT release-please shape (make_latest=true)',
() => github.rest.repos.createRelease({ owner, repo, tag_name: `v0.0.0-diaglatest-${id}`, target_commitish: sha, name: 'diagnostic', body: 'diagnostic', draft: false, prerelease: false, make_latest: 'true' }),
async (res) => {
await github.rest.repos.deleteRelease({ owner, repo, release_id: res.data.id });
await github.rest.git.deleteRef({ owner, repo, ref: `tags/v0.0.0-diaglatest-${id}` });
}
);

// 7. EXACT release-please target: #1318 merge SHA as target_commitish (throwaway tag).
const prSha = 'aee8ca60d93729893070c4d71fc22305cadefcb6';
await probe(
'create release @ #1318 merge SHA (throwaway tag)',
() => github.rest.repos.createRelease({ owner, repo, tag_name: `v0.0.0-diagpr-${id}`, target_commitish: prSha, name: 'diagnostic', body: 'diagnostic', draft: false, prerelease: false, make_latest: 'false' }),
async (res) => {
await github.rest.repos.deleteRelease({ owner, repo, release_id: res.data.id });
await github.rest.git.deleteRef({ owner, repo, ref: `tags/v0.0.0-diagpr-${id}` });
}
);

// 8/9. Releases at USER-authored non-tip master commits (control for "bot-authored commit" theory).
for (const c of [
{ label: 'user commit 330e8397 (David)', sha: '330e8397926aca76adc4fceabbd5a9be6c5021c8', tag: 'diaguser1' },
{ label: 'user commit 008dc2f4 (gregbaroni)', sha: '008dc2f4', tag: 'diaguser2' },
]) {
await probe(
`create release @ ${c.label}`,
() => github.rest.repos.createRelease({ owner, repo, tag_name: `v0.0.0-${c.tag}-${id}`, target_commitish: c.sha, name: 'diagnostic', body: 'diagnostic', draft: false, prerelease: false, make_latest: 'false' }),
async (res) => {
await github.rest.repos.deleteRelease({ owner, repo, release_id: res.data.id });
await github.rest.git.deleteRef({ owner, repo, ref: `tags/v0.0.0-${c.tag}-${id}` });
}
);
}

// 10/11. Disambiguate "non-tip" vs "protected master".
for (const c of [
{ label: 'master HEAD (tip of protected branch)', sha: 'bdc4670e86a1a0408b5953a882285cbaaa9d3fae', tag: 'diagmastertip' },
{ label: 'non-tip commit on MY feature branch', sha: 'ef4e8d9fdeb2cf04fca4bf3e2c002c93488f6c4b', tag: 'diagbranchnontip' },
]) {
await probe(
`create release @ ${c.label}`,
() => github.rest.repos.createRelease({ owner, repo, tag_name: `v0.0.0-${c.tag}-${id}`, target_commitish: c.sha, name: 'diagnostic', body: 'diagnostic', draft: false, prerelease: false, make_latest: 'false' }),
async (res) => {
await github.rest.repos.deleteRelease({ owner, repo, release_id: res.data.id });
await github.rest.git.deleteRef({ owner, repo, ref: `tags/v0.0.0-${c.tag}-${id}` });
}
);
}

const summary = `event=${context.eventName}\n` + results.join('\n');
core.notice(`Token write probes:\n${summary}`);
await core.summary.addHeading('GITHUB_TOKEN write probes').addRaw('\n```\n' + summary + '\n```\n').write();
console.log('\n=== RESULTS ===\n' + summary + '\n');
Loading