diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml new file mode 100644 index 000000000..46270c440 --- /dev/null +++ b/.github/workflows/pipeline.yml @@ -0,0 +1,87 @@ +name: Pipeline + + +on: + pull_request: + branches: ['*'] + types: [opened, synchronize, reopened, labeled, unlabeled, ready_for_review, converted_to_draft, edited] + +jobs: + labels-for-repertoire-changes: + name: Labels for repertoire changes + outputs: + repertoire-changed: ${{ steps.compare-repertoire.outputs.repertoire-changed }} + pipeline-label: ${{ steps.check-labels.outputs.pipeline-label }} + runs-on: ubuntu-latest + steps: + - name: Checkout merged UnicodeData.txt + uses: actions/checkout@v3 + with: + path: merged + sparse-checkout: unicodetools/data/ucd/dev/UnicodeData.txt + - name: Checkout base UnicodeData.txt + uses: actions/checkout@v3 + with: + ref: ${{ github.event.pull_request.base.sha }} + path: base + sparse-checkout: unicodetools/data/ucd/dev/UnicodeData.txt + - name: Compare repertoire + id: compare-repertoire + run: | + # Look for changes affecting the first two fields of UnicodeData.txt (code point and name). + sed 's/^\([^;]*;[^;]*\);.*$/\1/' merged/unicodetools/data/ucd/dev/UnicodeData.txt > merged-repertoire.txt + sed 's/^\([^;]*;[^;]*\);.*$/\1/' base/unicodetools/data/ucd/dev/UnicodeData.txt > base-repertoire.txt + if diff base-repertoire.txt merged-repertoire.txt + then echo "repertoire-changed=false" >> "$GITHUB_OUTPUT" + else echo "repertoire-changed=true" >> "$GITHUB_OUTPUT" + fi + - name: Checkout Python scripts + uses: actions/checkout@v3 + with: + sparse-checkout: py/pipeline-workflow + - name: Check pipeline labels + id: check-labels + if: steps.compare-repertoire.outputs.repertoire-changed == 'true' + run: python3 py/pipeline-workflow/compare-repertoire.py + l2-document: + needs: labels-for-repertoire-changes + if: ${{ always() && needs.labels-for-repertoire-changes.outputs.repertoire-changed == 'true' }} + name: Proposal document + runs-on: ubuntu-latest + steps: + - name: Checkout Python scripts + uses: actions/checkout@v3 + with: + sparse-checkout: py/pipeline-workflow + - name: Check L2 document + run: | + python3 py/pipeline-workflow/check-l2-document.py + utc-decision: + needs: labels-for-repertoire-changes + if: needs.labels-for-repertoire-changes.outputs.repertoire-changed == 'true' && needs.labels-for-repertoire-changes.outputs.pipeline-label != 'pipeline-recommended-to-UTC' + name: UTC decision + runs-on: ubuntu-latest + steps: + - name: Checkout Python scripts + uses: actions/checkout@v3 + with: + sparse-checkout: py/pipeline-workflow + - name: Check UTC decision + run: python3 py/pipeline-workflow/check-utc-decision.py + draft-unless-approved: + needs: labels-for-repertoire-changes + if: needs.labels-for-repertoire-changes.outputs.repertoire-changed == 'true' + name: Draft unless approved + runs-on: ubuntu-latest + steps: + - name: Checkout Python scripts and DerivedAge.txt + uses: actions/checkout@v3 + with: + sparse-checkout: | + py/pipeline-workflow + unicodetools/data/ucd/dev/DerivedAge.txt + - name: Check draft status + env: + PIPELINE_LABEL: ${{ needs.labels-for-repertoire-changes.outputs.pipeline-label }} + run: python3 py/pipeline-workflow/check-draft-status.py + diff --git a/docs/pipeline.md b/docs/pipeline.md index 0da43bd39..f8df415c7 100644 --- a/docs/pipeline.md +++ b/docs/pipeline.md @@ -62,6 +62,9 @@ PR preparation: - [ ] UTC decisions — Cite _in extenso_ - [ ] data-for-new — Set label - [ ] pipeline-* — Set label +- [ ] PR button — Set to DRAFT pull request + - unless approved for the upcoming version +- [ ] PR button — Press ## Scripts diff --git a/py/pipeline-workflow/check-draft-status.py b/py/pipeline-workflow/check-draft-status.py new file mode 100644 index 000000000..c1bd2e091 --- /dev/null +++ b/py/pipeline-workflow/check-draft-status.py @@ -0,0 +1,19 @@ + +import os +import json + +pipeline_label = os.environ['PIPELINE_LABEL'] + +with open("unicodetools/data/ucd/dev/DerivedAge.txt", 'r') as f: + version = f.readline().strip().replace("# DerivedAge-", "").replace(".0.txt", "") + +if pipeline_label != "pipeline-" + version: + with open(os.environ['GITHUB_EVENT_PATH'], 'r') as f: + event = json.load(f) + print(event) + draft = event['pull_request']['draft'] + if not draft: + print("::error title=PR must be draft::" + "PRs for character additions must be draft unless approved for " + "the upcoming version of Unicode.") + exit(1) diff --git a/py/pipeline-workflow/check-l2-document.py b/py/pipeline-workflow/check-l2-document.py new file mode 100644 index 000000000..11e421817 --- /dev/null +++ b/py/pipeline-workflow/check-l2-document.py @@ -0,0 +1,14 @@ + +import os +import json +import re + +with open(os.environ['GITHUB_EVENT_PATH'], 'r') as f: + event = json.load(f) +print(event) +pr_body = event['pull_request']['body'] +if not re.search(r"L2/\d\d-\d\d\d", pr_body): + print("::error title=Need proposal document::" + "PRs for character additions must include a link to an L2 document in" + " the PR description.") + exit(1) diff --git a/py/pipeline-workflow/check-utc-decision.py b/py/pipeline-workflow/check-utc-decision.py new file mode 100644 index 000000000..1b98d63af --- /dev/null +++ b/py/pipeline-workflow/check-utc-decision.py @@ -0,0 +1,14 @@ + +import os +import json +import re + +with open(os.environ['GITHUB_EVENT_PATH'], 'r') as f: + event = json.load(f) +print(event) +pr_body = event['pull_request']['body'] +if not re.search(r"UTC-\d\d\d-[MC]\d", pr_body): + print("::error title=Need UTC decision::" + "PRs for approved or provisionally assigned must include a link to a " + "UTC decision.") + exit(1) diff --git a/py/pipeline-workflow/compare-repertoire.py b/py/pipeline-workflow/compare-repertoire.py new file mode 100644 index 000000000..f420cb08e --- /dev/null +++ b/py/pipeline-workflow/compare-repertoire.py @@ -0,0 +1,21 @@ + +import os +import json + +with open(os.environ['GITHUB_EVENT_PATH'], 'r') as f: + event = json.load(f) +print(event) +labels = event['pull_request']['labels'] +pipeline_labels = [label for label in labels if label['name'].startswith('pipeline-')] +if not pipeline_labels: + print("::error title=Missing pipeline label::" + "PRs for character additions must have a pipeline label.") + exit(1) +if len(pipeline_labels) > 1: + print("::error title=Multiple pipeline labels::" + "Only one pipeline-* label must be applied.") + exit(1) +label = pipeline_labels[0] +print("Labeled", label) +with open(os.environ['GITHUB_OUTPUT'], 'a') as f: + print("pipeline-label=" + label['name'], file=f)