Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clean up PR previews #1697

Merged
merged 13 commits into from
Jul 13, 2024
34 changes: 34 additions & 0 deletions .github/workflows/pr-cleanup.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# This code is a Qiskit project.
#
# (C) Copyright IBM 2024.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.

name: PR preview cleanup
on:
workflow_dispatch:
push:
branches:
- "main"

jobs:
preview-cleanup:
name: PR preview cleanup
runs-on: ubuntu-latest
if: github.repository_owner == 'Qiskit'
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"

- name: Clean up PR previews
run: scripts/pr_previews/cleanup.py
env:
GH_TOKEN: ${{ github.token }}
2 changes: 0 additions & 2 deletions .github/workflows/pr-preview.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,6 @@ jobs:

- name: Deploy to GitHub Pages
run: scripts/pr_previews/deploy.py ${{ env.PR_PREVIEW_PATH }}
- name: Switch back to original branch
uses: actions/checkout@v4

- name: Determine deployment result
run: scripts/pr_previews/poll_deployment.py ${{ env.PR_PREVIEW_URL }}
Expand Down
60 changes: 60 additions & 0 deletions scripts/pr_previews/cleanup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#!/usr/bin/env python3

# This code is a Qiskit project.
#
# (C) Copyright IBM 2024.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.

import json
import logging
import shutil
from pathlib import Path
frankharkins marked this conversation as resolved.
Show resolved Hide resolved

logger = logging.getLogger(__name__)

from utils import configure_logging, run_subprocess, setup_git_account, switch_branch


def main() -> None:
setup_git_account()

with switch_branch("gh-pages"):
delete_closed_pr_folders()

changed_files = run_subprocess(["git", "status", "--porcelain"]).stdout.strip()
frankharkins marked this conversation as resolved.
Show resolved Hide resolved
if not changed_files:
logger.info("No changed files detected, so no push made to gh-pages")
return

run_subprocess(["git", "add", "."])
run_subprocess(["git", "commit", "-m", f"Clean up PR previews"])
run_subprocess(["git", "push"])
frankharkins marked this conversation as resolved.
Show resolved Hide resolved
logger.info("Pushed updates to gh-pages branch")


def get_active_pr_folders() -> set[str]:
raw = run_subprocess(
["gh", "pr", "list", "--state", "open", "--json", "number", "--limit", "1000"]
).stdout
# `raw` is JSON string of form: { number: int }[]
return {f"pr-{obj['number']}" for obj in json.loads(raw)}


def delete_closed_pr_folders() -> None:
active_pr_folders = get_active_pr_folders()
for folder in Path(".").glob("pr-*"):
if folder.name not in active_pr_folders:
logger.info(f"Deleting {folder}")
shutil.rmtree(folder)


if __name__ == "__main__":
configure_logging()
main()
31 changes: 11 additions & 20 deletions scripts/pr_previews/deploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

logger = logging.getLogger(__name__)

from utils import configure_logging, run_subprocess
from utils import configure_logging, run_subprocess, setup_git_account, switch_branch


def create_parser() -> ArgumentParser:
Expand All @@ -36,33 +36,24 @@ def main() -> None:
raise AssertionError(
f"Expected {folder} to have been created with the new content"
)

run_subprocess(["git", "config", "user.name", "github-actions[bot]"])
run_subprocess(
["git", "config", "user.email", "github-actions[bot]@users.noreply.github.com"]
)

run_subprocess(["git", "fetch", "origin", "gh-pages"])
setup_git_account()

# Handle if the content folder already exists on gh-pages branch.
run_subprocess(["git", "stash", "--include-untracked"])
run_subprocess(["git", "switch", "gh-pages"])
if folder.exists():
shutil.rmtree(folder)
run_subprocess(["git", "stash", "pop"])
with switch_branch("gh-pages"):
if folder.exists():
shutil.rmtree(folder)
run_subprocess(["git", "stash", "pop"])

changed_files = run_subprocess(["git", "status", "--porcelain"]).stdout.strip()
if not changed_files:
logger.info("No changed files detected, so no push made to gh-pages")
return

changed_files = run_subprocess(["git", "status", "--porcelain"]).stdout.strip()
if changed_files:
run_subprocess(["git", "add", "."])
run_subprocess(["git", "commit", "-m", f"Deploy PR preview for {folder}"])
run_subprocess(["git", "push"])
logger.info("Pushed updates to gh-pages branch")
else:
logger.info("No changed files detected, so no push made to gh-pages")

logger.warning(
"The branch is set to gh-pages. You probably want to `git switch` back to your original branch"
)


if __name__ == "__main__":
Expand Down
16 changes: 16 additions & 0 deletions scripts/pr_previews/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

import logging
import subprocess
from contextlib import contextmanager
from pathlib import Path


Expand All @@ -28,6 +29,21 @@ def configure_logging() -> None:
)


def setup_git_account() -> None:
run_subprocess(["git", "config", "user.name", "github-actions[bot]"])
run_subprocess(
["git", "config", "user.email", "github-actions[bot]@users.noreply.github.com"]
)


@contextmanager
def switch_branch(branchname: str) -> None:
frankharkins marked this conversation as resolved.
Show resolved Hide resolved
run_subprocess(["git", "fetch", "origin", branchname])
run_subprocess(["git", "switch", branchname])
yield
run_subprocess(["git", "checkout", "-"])
frankharkins marked this conversation as resolved.
Show resolved Hide resolved


def run_subprocess(
cmd: list[str],
*,
Expand Down