Skip to content

Commit

Permalink
Add test for guard
Browse files Browse the repository at this point in the history
  • Loading branch information
hanseartic committed Dec 18, 2024
1 parent 72a3e3b commit 69cd778
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 36 deletions.
24 changes: 23 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
version: [20]
version: [20, 22]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
Expand All @@ -28,3 +28,25 @@ jobs:
- uses: ./
with:
token: ${{ github.token }}

test_guard:
name: Test Action guard
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
- uses: ./
with:
token: ${{ github.token }}
id: run-guard
continue-on-error: true
- if: ${{ (success() || failure()) && steps.run-guard.outcome == 'failure' }}
run: |
echo "Guard failed as expected"
- if: ${{ (success() || failure()) && steps.run-guard.outcome != 'failure' }}
run: |
echo "Guard did not fail as expected"
exit 1
2 changes: 1 addition & 1 deletion index.guard.js

Large diffs are not rendered by default.

112 changes: 78 additions & 34 deletions index.guard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,44 +7,88 @@ type Release = {
prerelease: boolean
tag_name: string
}
type ReleasePage = {
pages: number,
releases: Release[],
}

const [ owner, repo ] = process.env.GITHUB_ACTION_REPOSITORY?.split('/') ?? [ undefined, undefined ]

async function getReleases(): Promise<Release[]> {
const octokit = new Octokit({auth: core.getInput('token') || process.env.GITHUB_TOKEN})
const getRepo = () => {
const actionRepo = (process.env.GITHUB_ACTION_REPOSITORY != ''
? process.env.GITHUB_ACTION_REPOSITORY
: process.env.GITHUB_REPOSITORY) ?? ''
const [ owner, repo ] = actionRepo?.split('/') ?? [ undefined, undefined ]
if (!owner || !repo) {
core.debug('Failed to determine github action repository.')
return []
}
return octokit.rest.repos.listReleases({ owner, repo })
.then(({ data }) => data
.map((release): Release => ({
html_url: release.html_url,
draft: release.draft,
prerelease: release.prerelease,
tag_name: release.tag_name,
}))
)

return { actionRepo, owner, repo }
}

core.setFailed('Must use a tagged release of this action! See summary for more details.')
getReleases()
.then((releases) => {
if (releases.length === 0) {
core.debug(`No releases for this action (${process.env.GITHUB_ACTION_REPOSITORY}) found on GitHub.`)
return
}
const suggestedVersion = releases.find((release: Release) => !release.prerelease && !release.draft)?.tag_name ?? releases[0].tag_name
return core.summary
.addHeading('🏷️ Only tagged releases of this action can be used in workflows', 3)
.addRaw('Only tagged releases of this action can be used, e.g.\n', true)
.addRaw('```yaml', true)
.addRaw(`- uses: ${process.env.GITHUB_ACTION_REPOSITORY}@${suggestedVersion}`, true)
.addRaw('```\n', true)
.addRaw('----\nThe following releases are available:', true)
.addRaw(releases.map((release) => `* [${release.tag_name}](${release.html_url})`).join('\n'), true)
.write({overwrite: true})
})
.catch(() => {
core.debug('Failed to fetch releases from GitHub.')
const getToken = () => {
const token = core.getInput('token') || process.env.GITHUB_TOKEN
if (!token) {
core.debug('No GitHub token found. Trying to access API publicly.')
}
return token
}
const getReleases = async (): Promise<ReleasePage> => {
const octokit = new Octokit({
auth: getToken(),
})
const { owner, repo } = getRepo()
if (!owner || !repo) {
return { releases: [], pages: 0 }
}
return octokit.rest.repos.listReleases({ owner, repo, per_page: 10 })
.then(( { data, headers } ) => {
const pages = /page=(\d+)>; rel="last"/.exec(headers.link ?? '')
const releases = data
.map((release): Release => ({
draft: release.draft,
html_url: release.html_url,
prerelease: release.prerelease,
tag_name: release.tag_name,
}))
return { releases, pages: pages ? parseInt(pages[1]) : 1 }
})
}
const isProdRelease = (release: Release) => !release.prerelease && !release.draft
const releaseToMarkdownLink = (release: Release) => `* [${release.tag_name}](${release.html_url})`

const guard = async () => {
const { pages, releases} = await getReleases()
.catch((error) => {
core.warning('Failed to fetch releases from GitHub. Turn on debug messaging for more information.')
core.error(error.message ?? error)
return { pages: 0, releases: [] }
})

const { actionRepo } = getRepo()
if (releases.length === 0) {
core.debug(`No releases for this action (${actionRepo}) found on GitHub.`)
return undefined
}
const suggestedVersion = (releases.find(isProdRelease) ?? releases[0]).tag_name
const releaseLinks = releases.map(releaseToMarkdownLink)
if (pages > 1) {
releaseLinks.push(`* [...](${releases[0].html_url.split('/releases/')[0]}/releases?page=2)`)
}

core.summary
.addHeading('🏷️ Only tagged releases of this action can be used in workflows', 3)
.addRaw('Only tagged releases of this action can be used, e.g.\n', true)
.addRaw('```yaml', true)
.addRaw(`- uses: ${actionRepo}@${suggestedVersion}`, true)
.addRaw('```\n', true)
.addRaw('----\nThe following releases are available:', true)
.addRaw(releaseLinks.join('\n'), true)

return suggestedVersion
}
const suggestedVersion = await guard()
let errorMessage = suggestedVersion
? `A tagged release (e.g. ${suggestedVersion}) of this action must be used!`
: 'A tagged release of this action must be used! Could not determine suggested version.'

core.setFailed(errorMessage + core.summary.isEmptyBuffer() ? '' : ' See summary for more details.')
core.summary.isEmptyBuffer() || void core.summary.write({overwrite: true})

0 comments on commit 69cd778

Please sign in to comment.