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
135 changes: 135 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
on:
pull_request_target:
paths:
- quiche/Cargo.toml

name: Release Checks

permissions:
# Draft releases are only visible to tokens with push access.
contents: write
pull-requests: read

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
cancel-in-progress: true

jobs:
quiche_release_draft:
name: Check quiche release draft
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Check quiche release draft
uses: actions/github-script@v7
with:
script: |
const pr = context.payload.pull_request;
const manifestPath = 'quiche/Cargo.toml';

async function getManifest(owner, repo, ref) {
const response = await github.rest.repos.getContent({
owner,
repo,
path: manifestPath,
ref,
});

return Buffer.from(
response.data.content,
response.data.encoding,
).toString('utf8');
}

function packageVersion(manifest) {
let inPackageSection = false;

for (const line of manifest.split(/\r?\n/)) {
const section = line.match(/^\s*\[([^\]]+)\]\s*$/);

if (section) {
if (section[1] === 'package') {
inPackageSection = true;
continue;
}

if (inPackageSection) {
break;
}

continue;
}

if (!inPackageSection) {
continue;
}

const version = line.match(/^\s*version\s*=\s*"([^"]+)"\s*$/);

if (version) {
return version[1];
}
}

throw new Error(`No package version found in ${manifestPath}`);
}

const baseManifest = await getManifest(
pr.base.repo.owner.login,
pr.base.repo.name,
pr.base.sha,
);

const headManifest = await getManifest(
pr.head.repo.owner.login,
pr.head.repo.name,
pr.head.sha,
);

const baseVersion = packageVersion(baseManifest);
const headVersion = packageVersion(headManifest);

if (baseVersion === headVersion) {
core.info(`quiche version is unchanged at ${headVersion}`);
return;
}

core.info(
`quiche version changes from ${baseVersion} to ${headVersion}`,
);

const releases = await github.paginate(
github.rest.repos.listReleases,
{
owner: context.repo.owner,
repo: context.repo.repo,
per_page: 100,
},
);

// quiche releases use the version as the tag name, without a crate
// prefix. Release PRs are not tagged until after they are merged, so
// check GitHub release drafts rather than git tags.
const releaseTag = headVersion;
const release = releases.find(
(release) => release.tag_name === releaseTag,
);

if (!release) {
core.setFailed(
`No GitHub release draft exists for quiche ${headVersion}. ` +
`Create a draft release for the future ${releaseTag} tag before ` +
`merging this release PR.`,
);
return;
}

if (!release.draft) {
core.setFailed(
`GitHub release ${release.html_url} exists for quiche ` +
`${headVersion}, but it is not a draft.`,
);
return;
}

core.info(`Found GitHub release draft: ${release.html_url}`);
Loading