blob: aab3c67717639d657172283be16cc3c9c2bf35a4 [file] [edit]
# Copyright 2013 The Flutter Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# Privileged half of the code freeze check.
#
# Runs after `freeze.yml` fails and leaves an explanatory comment on the pull
# request. The artifact produced by `freeze.yml` is UNTRUSTED (a pull request
# can modify that workflow), so the PR number is only used after binding it to
# the triggering run's head commit, and the comment text is fixed.
name: Material and Cupertino Code Freeze Comment
on:
# Safe because this only consumes an artifact from the triggering run as
# untrusted data (validated and bound to the PR's head SHA); no PR code is
# checked out or executed.
workflow_run: # zizmor: ignore[dangerous-triggers]
workflows: [Material and Cupertino Code Freeze]
types: [completed]
permissions:
contents: read
jobs:
comment:
name: Comment on frozen changes
runs-on: ubuntu-latest
# Only a failed check can need a comment, so passing runs never allocate a runner.
if: >-
github.repository == 'flutter/flutter' &&
github.event.workflow_run.conclusion == 'failure' &&
github.event.workflow_run.event == 'pull_request' &&
github.event.workflow_run.path == '.github/workflows/freeze.yml'
permissions:
actions: read
pull-requests: write
steps:
- name: Download freeze metadata
id: download
# The check may have failed for a reason other than frozen changes, in
# which case there is no artifact.
continue-on-error: true
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: freeze-metadata
path: ${{ runner.temp }}/freeze-metadata
run-id: ${{ github.event.workflow_run.id }}
github-token: ${{ github.token }}
- name: Comment on frozen changes
if: steps.download.outcome == 'success'
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
METADATA_PATH: ${{ runner.temp }}/freeze-metadata/metadata.json
with:
github-token: ${{ github.token }}
script: |
const fs = require('fs');
const run = context.payload.workflow_run;
const metadata = JSON.parse(fs.readFileSync(process.env.METADATA_PATH, 'utf8'));
const prNumberString = String(metadata.pr_number ?? '');
if (!/^[1-9][0-9]*$/.test(prNumberString)) {
core.setFailed('Artifact contains an invalid PR number.');
return;
}
const issueNumber = Number(prNumberString);
// Bind the artifact to the pull request that actually triggered the run.
const { data: pr } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: issueNumber,
});
if (pr.head.sha !== run.head_sha || pr.head.repo?.full_name !== run.head_repository?.full_name) {
core.notice(`PR #${issueNumber} has changed since the check ran; skipping.`);
return;
}
if (pr.labels.some(label => label.name === 'override code freeze')) {
core.notice(`PR #${issueNumber} has the 'override code freeze' label; skipping.`);
return;
}
const comments = await github.paginate(github.rest.issues.listComments, {
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNumber,
});
const issueUrl = 'https://github.com/flutter/flutter/issues/188444';
const alreadyCommented = comments.some(comment =>
comment.body && comment.body.includes(issueUrl)
);
if (!alreadyCommented) {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNumber,
body: 'This pull request contains changes to Material or Cupertino, which are currently frozen in this repository.\n\n' +
'Changes should be made in `material_ui` and/or `cupertino_ui` in the [flutter/packages](https://github.com/flutter/packages) repository.\n\n' +
'Please refer to https://github.com/flutter/flutter/issues/188444 for instructions.',
});
}