diff --git a/.github/workflows/sync-upstream-tag.yml b/.github/workflows/sync-upstream-tag.yml new file mode 100644 index 00000000..027b4e33 --- /dev/null +++ b/.github/workflows/sync-upstream-tag.yml @@ -0,0 +1,152 @@ +name: Open PR for latest upstream ScopeSim tag + +on: + workflow_dispatch: + schedule: + # Weekly on Monday at 09:17 UTC + - cron: "17 9 * * 1" + +permissions: + contents: write + pull-requests: write + +concurrency: + group: sync-upstream-scopesim-tag + cancel-in-progress: false + +env: + UPSTREAM_REPO: AstarVienna/ScopeSim + BASE_BRANCH: main + TAG_PATTERN: "v[0-9]*" + +jobs: + open-pr: + name: Open PR from latest upstream tag + runs-on: ubuntu-latest + + steps: + - name: Checkout Caltech fork + uses: actions/checkout@v4 + with: + ref: ${{ env.BASE_BRANCH }} + fetch-depth: 0 + + - name: Configure git + run: | + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + + - name: Find latest upstream stable tag + id: upstream + shell: bash + run: | + set -euo pipefail + + latest_tag="$( + git ls-remote --tags --refs "https://github.com/${UPSTREAM_REPO}.git" "${TAG_PATTERN}" \ + | awk '{ sub("refs/tags/", "", $2); print $2 }' \ + | grep -E '^v[0-9]+(\.[0-9]+)+$' \ + | sort -V \ + | tail -n 1 + )" + + if [[ -z "${latest_tag}" ]]; then + echo "No stable upstream tag found." + exit 1 + fi + + echo "Latest upstream tag: ${latest_tag}" + echo "tag=${latest_tag}" >> "$GITHUB_OUTPUT" + + - name: Fetch upstream tag and branches + shell: bash + run: | + set -euo pipefail + + git remote add upstream "https://github.com/${UPSTREAM_REPO}.git" || \ + git remote set-url upstream "https://github.com/${UPSTREAM_REPO}.git" + + git fetch --quiet origin "${BASE_BRANCH}:refs/remotes/origin/${BASE_BRANCH}" + git fetch --quiet upstream "refs/tags/${{ steps.upstream.outputs.tag }}:refs/tags/${{ steps.upstream.outputs.tag }}" + git fetch --quiet upstream "${BASE_BRANCH}:refs/remotes/upstream/${BASE_BRANCH}" + + - name: Check whether fork already contains latest upstream tag + id: check + shell: bash + run: | + set -euo pipefail + + tag="${{ steps.upstream.outputs.tag }}" + + if git merge-base --is-ancestor "${tag}" "origin/${BASE_BRANCH}"; then + echo "Fork ${BASE_BRANCH} already contains upstream ${tag}." + echo "needs_pr=false" >> "$GITHUB_OUTPUT" + else + echo "Fork ${BASE_BRANCH} does not contain upstream ${tag}." + echo "needs_pr=true" >> "$GITHUB_OUTPUT" + fi + + - name: Push sync branch at upstream tag + if: steps.check.outputs.needs_pr == 'true' + id: branch + shell: bash + run: | + set -euo pipefail + + tag="${{ steps.upstream.outputs.tag }}" + branch="sync/upstream-${tag}" + + git checkout -B "${branch}" "${tag}" + git push --force-with-lease origin "${branch}" + + echo "branch=${branch}" >> "$GITHUB_OUTPUT" + + - name: Open or update PR + if: steps.check.outputs.needs_pr == 'true' + shell: bash + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + set -euo pipefail + + tag="${{ steps.upstream.outputs.tag }}" + branch="${{ steps.branch.outputs.branch }}" + title="Sync ScopeSim with upstream ${tag}" + + body="$(cat <