Skip to content

Commit

Permalink
Merge pull request #45 from mislav/same-repo-flow
Browse files Browse the repository at this point in the history
Fix scenario with generated GITHUB_TOKEN
  • Loading branch information
mislav committed Jan 31, 2023
2 parents dfea670 + cebe858 commit ab7aa39
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 13 deletions.
53 changes: 52 additions & 1 deletion src/edit-github-blob-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ test('edit-github-blob via pull request', async (t) => {
t.is('https://github.com/OWNER/REPO/pull/123', url)
})

test('edit-github-blob with pushTo', async (t) => {
test('edit-github-blob with pushTo a fork', async (t) => {
let newBranchName: string
const stubbedFetch = function (url: string, options: fetchOptions) {
function route(method: string, path: string): boolean {
Expand Down Expand Up @@ -223,3 +223,54 @@ test('edit-github-blob with pushTo', async (t) => {
})
t.is('https://github.com/OWNER/REPO/pull/123', url)
})

test('edit-github-blob with pushTo the base repo', async (t) => {
const stubbedFetch = function (url: string, options: fetchOptions) {
function route(method: string, path: string): boolean {
return (
method.toUpperCase() === options.method.toUpperCase() &&
`https://github.com/gitapi/${path}` === url
)
}

if (route('GET', 'repos/OWNER/REPO')) {
return replyJSON(200, {
default_branch: 'main',
permissions: { push: false },
})
} else if (route('GET', 'repos/OWNER/REPO/branches/main')) {
return replyJSON(200, {
commit: { sha: 'COMMITSHA' },
protected: false,
})
} else if (
route('GET', `repos/OWNER/REPO/contents/formula%2Ftest.rb?ref=main`)
) {
return replyJSON(200, {
content: Buffer.from(`old content`).toString('base64'),
})
} else if (route('PUT', 'repos/OWNER/REPO/contents/formula%2Ftest.rb')) {
const payload = JSON.parse(options.body || '')
t.is(payload.branch, 'main')
t.is(payload.message, 'Update formula/test.rb')
t.is(
Buffer.from(payload.content, 'base64').toString('utf8'),
'OLD CONTENT'
)
return replyJSON(200, {
commit: { html_url: 'https://github.com/OWNER/REPO/commit/NEWSHA' },
})
}
throw `not stubbed: ${options.method} ${url}`
}

const url = await editGithubBlob({
apiClient: api('ATOKEN', { fetch: stubbedFetch, logRequests: false }),
owner: 'OWNER',
repo: 'REPO',
pushTo: { owner: 'OWNER', repo: 'REPO' },
filePath: 'formula/test.rb',
replace: (oldContent) => oldContent.toUpperCase(),
})
t.is(url, 'https://github.com/OWNER/REPO/commit/NEWSHA')
})
26 changes: 14 additions & 12 deletions src/edit-github-blob.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,25 +41,29 @@ export default async function (params: Options): Promise<string> {
owner: params.owner,
repo: params.repo,
}
let headRepo = baseRepo
let headRepo = params.pushTo == null ? baseRepo : params.pushTo
const filePath = params.filePath
const api = params.apiClient.rest

const repoRes = await api.repos.get(baseRepo)
const makeFork =
params.pushTo == null &&
(repoRes.data.permissions == null || !repoRes.data.permissions.push)
const inFork =
makeFork ||
`${baseRepo.owner}/${baseRepo.repo}`.toLowerCase() !=
`${headRepo.owner}/${headRepo.repo}`.toLowerCase()

const baseBranch = params.branch ? params.branch : repoRes.data.default_branch
let headBranch = baseBranch
const branchRes = await api.repos.getBranch({
...baseRepo,
branch: baseBranch,
})
const needsBranch =
inFork || branchRes.data.protected || params.makePR === true

const needsFork =
repoRes.data.permissions == null ||
!repoRes.data.permissions.push ||
params.pushTo != null
if (params.pushTo != null) {
headRepo = params.pushTo
} else if (needsFork) {
if (makeFork) {
const res = await Promise.all([
api.repos.createFork(baseRepo),
api.users.getAuthenticated(),
Expand All @@ -70,12 +74,10 @@ export default async function (params: Options): Promise<string> {
}
}

const needsBranch =
needsFork || branchRes.data.protected || params.makePR === true
if (needsBranch) {
const timestamp = Math.round(Date.now() / 1000)
headBranch = `update-${basename(filePath)}-${timestamp}`
if (needsFork) {
if (inFork) {
try {
await api.repos.mergeUpstream({
...headRepo,
Expand All @@ -89,7 +91,7 @@ export default async function (params: Options): Promise<string> {
}
}
}
await retry(needsFork ? 6 : 0, 5000, async () => {
await retry(makeFork ? 6 : 0, 5000, async () => {
await api.git.createRef({
...headRepo,
ref: `refs/heads/${headBranch}`,
Expand Down
9 changes: 9 additions & 0 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,15 @@ export async function prepareEdit(
if (pushToSpec) {
const [pushToOwner, pushToRepo] = pushToSpec.split('/')
pushTo = { owner: pushToOwner, repo: pushToRepo }
} else if (
owner.toLowerCase() == context.repo.owner.toLowerCase() &&
repo.toLowerCase() == context.repo.repo.toLowerCase()
) {
// If the homebrew-tap to update is the same repository that is running the Actions workflow,
// explicitly set the same repository as the push-to target to skip any attempt of making a
// fork of the repository. This is because a generated GITHUB_TOKEN would still appear as it
// doesn't have permissions to push to homebrew-tap, even though it does.
pushTo = context.repo
}
const formulaName = getInput('formula-name') || ctx.repo.repo.toLowerCase()
const branch = getInput('base-branch')
Expand Down

0 comments on commit ab7aa39

Please sign in to comment.