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

Add CI pipeline #5

Open
wants to merge 1 commit into
base: solution
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions .github/workflows/push_ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
on:
push:
branches:
- dev
- test-ci
jobs:
build_teaching_and_solution:
runs-on: ubuntu-latest
defaults:
run:
shell: bash -l {0}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- run: |
git config user.name github-actions
git config user.email [email protected]
- name: Cache conda
uses: actions/cache@v3
env:
# Increase this value to reset cache if etc/example-environment.yml has not changed
CACHE_NUMBER: 2
with:
path: ~/conda_pkgs_dir
key:
Ubuntu-python_3.10-${{ env.CACHE_NUMBER }}-${{ hashFiles('etc/example-environment.yml') }}
- uses: conda-incubator/setup-miniconda@v2
with:
python-version: '3.10'
miniforge-variant: Mambaforge
use-mamba: true
auto-update-conda: true
channels: conda-forge
auto-activate-base: false
environment-file: environment.yml
activate-environment: cadet_workshop
- name: Generate teaching and solution branches
run: |
python ./workshop_git_tools/process_repo.py --commit --push
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ results_*
*.egg-info
.idea
tests/tmp*
setup-miniconda-patched-environment.yml
86 changes: 42 additions & 44 deletions workshop_git_tools/process_repo.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,9 @@ def run_command(command):
return subprocess.run(command, shell=True, check=True)


def create_solution(run=False, commit=False, push=False, n_cores=1, on_fail_restore_dev=False):
def create_solution(run=False, commit=False, push=False, n_cores=1, on_fail_restore_dev=False, base_branch="dev",
target_branch="solution"
):
"""Create solution files.

Parameters
Expand All @@ -134,6 +136,10 @@ def create_solution(run=False, commit=False, push=False, n_cores=1, on_fail_rest
Number of cpu cores to use for parallelization
on_fail_restore_dev : bool, optional
Reset the repo to dev on failure.
base_branch : str, optional
Branch on which these actions are based. If git is not currently on this branch: abort script.
target_branch : str, optional
Name for the newly created branch.

Returns
-------
Expand All @@ -143,19 +149,16 @@ def create_solution(run=False, commit=False, push=False, n_cores=1, on_fail_rest
current_branch = repo.active_branch.name
repo_root = Path(repo.working_tree_dir) # Gets the root directory of the repo

if current_branch != "dev":
print("Not on dev branch. Skipping create_solution script.")
if current_branch != base_branch:
print(f"Not on {base_branch} branch. Skipping create_solution script.")
return

try:
# Stash everything
run_command("git stash")

# Checkout the 'solution' branch
repo.git.checkout("solution")
repo.git.checkout(target_branch)

# Reset to `dev`
run_command("git reset --hard dev")
# Reset to base_branch
run_command(f"git reset --hard {base_branch}")

# Find all myst files recursively
myst_files = list(repo_root.glob("**/*.md"))
Expand Down Expand Up @@ -185,19 +188,14 @@ def create_solution(run=False, commit=False, push=False, n_cores=1, on_fail_rest
if commit:
# Commit all changes to ipynb files
repo.git.add(".") # Less error-prone than working with path lists
run_command('git commit -m "Update solution"')
run_command(f'git commit -m "Update {target_branch}"')

if push:
# Push files to remote
run_command("git push --force-with-lease --set-upstream origin solution")

# Switch back to dev
repo.git.checkout("dev")
run_command(f"git push --force --set-upstream origin {target_branch}")

try:
repo.git.stash("pop")
except git.GitCommandError as e:
print(e)
# Switch back to base_branch
repo.git.checkout(base_branch)

except Exception as e:
print(f"An error occurred: {e}")
Expand All @@ -206,8 +204,8 @@ def create_solution(run=False, commit=False, push=False, n_cores=1, on_fail_rest
run_command("git restore --staged .")
run_command("git restore .")

# Switch back to dev
repo.git.checkout("dev")
# Switch back to base_branch
repo.git.checkout(base_branch)

try:
repo.git.stash("pop")
Expand All @@ -217,7 +215,8 @@ def create_solution(run=False, commit=False, push=False, n_cores=1, on_fail_rest
raise


def create_teaching(commit=False, push=False, n_cores=1, on_fail_restore_dev=False):
def create_teaching(commit=False, push=False, n_cores=1, on_fail_restore_dev=False, base_branch="dev",
target_branch="teaching"):
"""Create teaching files.

Parameters
Expand All @@ -239,19 +238,16 @@ def create_teaching(commit=False, push=False, n_cores=1, on_fail_restore_dev=Fal
current_branch = repo.active_branch.name
repo_root = Path(repo.working_tree_dir) # Gets the root directory of the repo

if current_branch != "dev":
print("Not on dev branch. Skipping create_solution script.")
if current_branch != base_branch:
print(f"Not on {base_branch} branch. Skipping create_teaching script.")
return

try:
# Stash everything
run_command("git stash")

# Checkout the 'teaching' branch
repo.git.checkout("teaching")
repo.git.checkout(target_branch)

# Reset to `dev`
run_command("git reset --hard dev")
# Reset to base_branch
run_command(f"git reset --hard {base_branch}")

# Find all myst files recursively
myst_files = list(repo_root.glob("**/*.md"))
Expand Down Expand Up @@ -280,23 +276,19 @@ def create_teaching(commit=False, push=False, n_cores=1, on_fail_restore_dev=Fal
if commit:
# Commit all changes to myst files (our source of truth)
repo.git.add(".") # Less error-prone than working with path lists
run_command('git commit -m "Update teaching"')
run_command(f'git commit -m "Update {target_branch}"')

if push:
# Push files to remote
run_command("git push --force-with-lease --set-upstream origin teaching")
run_command(f"git push --force --set-upstream origin {target_branch}")

# Clean up
for ipynb_file in ipynb_files:
os.remove(ipynb_file)

# Switch back to dev
repo.git.checkout("dev")
# Switch back to base_branch
repo.git.checkout(base_branch)

try:
repo.git.stash("pop")
except git.GitCommandError as e:
print(e)

except Exception as e:
print(f"An error occurred: {e}")
Expand All @@ -305,8 +297,8 @@ def create_teaching(commit=False, push=False, n_cores=1, on_fail_restore_dev=Fal
run_command("git restore --staged .")
run_command("git restore .")

# Switch back to dev
repo.git.checkout("dev")
# Switch back to base_branch
repo.git.checkout(base_branch)

try:
repo.git.stash("pop")
Expand Down Expand Up @@ -384,13 +376,15 @@ def convert_ipynb_to_myst_md(ipynb_file_path):
return run_command(f'jupytext --to md:myst "{ipynb_file_path}"')


def setup_teaching_copy(new_repo_dir="CADET-Workshop-teaching"):
def setup_teaching_copy(new_repo_dir="CADET-Workshop-teaching", target_branch="teaching"):
"""Create a copy of this directory and check out the teaching branch in it

Parameters
----------
new_repo_dir : str
Name for the new repo folder.
target_branch : str
Name of the branch to check out in the new repo folder.

Returns
-------
Expand All @@ -414,7 +408,7 @@ def setup_teaching_copy(new_repo_dir="CADET-Workshop-teaching"):
# Clone from this repo to new repo
new_repo = git.Repo.clone_from(repo_root, new_repo_dir)

new_repo.git.checkout("teaching")
new_repo.git.checkout(target_branch)


def delete_dir_contents(dir_path):
Expand Down Expand Up @@ -449,17 +443,21 @@ def main(**kwargs):
parser.add_argument('--n_cores', help='Number of cores to use.')

args = parser.parse_args()
if args.n_cores is None:
args.n_cores = 1

# This isn't great, but for now (and with argparse) the best I could think of
for kwarg_key, kwarg_value in kwargs.items():
if kwarg_value is None:
continue
args.__setattr__(kwarg_key, kwarg_value)

args.run = False
args.commit = True

create_solution(args.run, args.commit, args.push, args.n_cores, args.on_fail_restore_dev)
create_teaching(args.commit, args.push, args.n_cores, args.on_fail_restore_dev)
create_solution(args.run, args.commit, args.push, args.n_cores, args.on_fail_restore_dev, base_branch="test-ci",
target_branch="tmp_solution")
create_teaching(args.commit, args.push, args.n_cores, args.on_fail_restore_dev, base_branch="test-ci",
target_branch="tmp_teaching")


if __name__ == "__main__":
Expand Down
Loading