forked from metaregistrar/php-epp-client
-
Notifications
You must be signed in to change notification settings - Fork 0
89 lines (75 loc) · 4.03 KB
/
Copy pathupstream-sync.yml
File metadata and controls
89 lines (75 loc) · 4.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
---
# Opens a PR that brings changes from the upstream metaregistrar/php-epp-client
# into this fork, keeping the local Exonet patches. Merge the PR manually with
# "Create a merge commit". A squash merge replays upstream's content under a new
# single-parent commit, so upstream never becomes an ancestor of master. That
# freezes the merge base and makes every later sync PR replay commits that
# already landed, plus add/add conflicts on files the fork never touched.
name: Upstream sync
on:
schedule:
- cron: '0 6 * * 1' # Mondays 06:00 UTC
workflow_dispatch:
permissions:
contents: read
env:
UPSTREAM: metaregistrar/php-epp-client
UPSTREAM_BRANCH: master
jobs:
upstream-sync:
name: Open upstream sync PR
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
# App token so the branch/PR are created as the app (and the PR triggers
# CI). Needs the app installed on this repo with contents: write +
# pull-requests: write.
- name: Generate app token
id: app-token
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
with:
client-id: ${{ secrets.RELEASE_APP_CLIENT_ID }}
private-key: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}
permission-contents: write
permission-pull-requests: write
- name: Checkout fork
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
token: ${{ steps.app-token.outputs.token }}
fetch-depth: 0
- name: Open an upstream sync PR
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
run: |
set -euo pipefail
git remote add upstream "https://github.com/${UPSTREAM}.git"
git fetch --no-tags --quiet upstream "${UPSTREAM_BRANCH}"
upstream_sha="$(git rev-parse --short "upstream/${UPSTREAM_BRANCH}")"
branch="upstream-sync/${upstream_sha}"
# Ancestry is the source of truth for "already synced". It only stays
# reliable while sync PRs land as merge commits.
if git merge-base --is-ancestor "upstream/${UPSTREAM_BRANCH}" HEAD; then
echo "Already synced ${UPSTREAM}@${upstream_sha}. Nothing to do."
exit 0
fi
# Don't reopen a sync that was already proposed and then closed.
# -R pins THIS fork, since gh resolves fork context to the upstream parent.
if [ -n "$(gh pr list -R "${GITHUB_REPOSITORY}" --head "${branch}" --state all --json number --jq '.[].number' | head -n1)" ]; then
echo "A PR for ${UPSTREAM}@${upstream_sha} already exists. Nothing to do."
exit 0
fi
# Mirror upstream onto a feature branch. Merging that branch records
# upstream as a parent of master, so the next run diffs against this
# sync rather than an ancient common ancestor.
git push --force origin "upstream/${UPSTREAM_BRANCH}:refs/heads/${branch}"
body="Automated sync of upstream [\`${UPSTREAM}\`](https://github.com/${UPSTREAM}) into this fork. Merge with **Create a merge commit**, not \"Squash and merge\", so upstream stays an ancestor of \`master\`. Squashing freezes the merge base and makes later sync PRs replay commits that already landed, along with phantom conflicts. The local Exonet patches are preserved. Resolve any conflicts in favour of the patches. Upstream: ${UPSTREAM}@${upstream_sha}."
# Create the PR in THIS fork. `gh pr create` defaults the base repo to the
# upstream parent for forks (which the app token can't touch -> "Resource
# not accessible by integration"), so hit the fork's pulls API directly.
url="$(gh api --method POST "repos/${GITHUB_REPOSITORY}/pulls" \
-f "title=Sync with upstream ${UPSTREAM}@${upstream_sha}" \
-f "head=${branch}" \
-f "base=master" \
-f "body=${body}" \
--jq '.html_url')"
echo "Opened ${url}. Review it and merge it manually with \"Create a merge commit\"."