Skip to content

Commit

Permalink
chore: add run one use case example
Browse files Browse the repository at this point in the history
  • Loading branch information
jfrery committed Apr 17, 2024
1 parent 5621f00 commit 845f933
Show file tree
Hide file tree
Showing 4 changed files with 259 additions and 4 deletions.
140 changes: 140 additions & 0 deletions .github/workflows/run_one_use_cases_example.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
name: Run One Use Case Example
on:
workflow_dispatch:
inputs:
use_case:
# --- refresh_use_cases_list.py: refresh list of use cases currently available [START] ---
# --- do not edit, auto generated part by `make refresh_use_cases_list` ---
- cifar/cifar_brevitas_finetuning
- cifar/cifar_brevitas_training
- credit_scoring
- disease_prediction
- federated_learning
- hybrid_model
- llm
- sentiment_analysis_with_transformer
- titanic
# --- refresh_use_cases_list.py: refresh list of use cases currently available [END] ---
required: true

concurrency:
group: ${{ github.ref }}
cancel-in-progress: true

env:
ACTION_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}

jobs:
start-runner-linux:
name: Start EC2 runner
runs-on: ubuntu-20.04
outputs:
label-38: ${{ steps.start-ec2-runner-38.outputs.label }}
ec2-instance-id-38: ${{ steps.start-ec2-runner-38.outputs.ec2-instance-id || '' }}
steps:
- name: Checkout Code
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608

- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@8c3f20df09ac63af7b3ae3d7c91f105f857d8497
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ secrets.AWS_REGION }}

- name: Start EC2 runner python 38
id: start-ec2-runner-38
uses: machulav/ec2-github-runner@4e0303de215db88e1c489e07a15ca4d867f488ea
with:
mode: start
github-token: ${{ secrets.EC2_RUNNER_BOT_TOKEN }}
ec2-image-id: ${{ secrets.AWS_EC2_AMI }}
ec2-instance-type: "m6i.metal"
subnet-id: ${{ secrets.AWS_EC2_SUBNET_ID }}
security-group-id: ${{ secrets.AWS_EC2_SECURITY_GROUP_ID }}

run-use-case-examples:
needs: [start-runner-linux]
runs-on: ${{ needs.start-runner-linux.outputs.label-38 }}
container:
image: ubuntu:20.04
defaults:
run:
shell: bash
steps:

- name: Set up Environment
run: |
# Setup commands if any, for example, installing dependencies, etc.
apt-get update && apt-get install -y python3-venv make git git-lfs binutils
- name: Checkout Code
uses: actions/checkout@v4
with:
lfs: true

- name: Run One Use Case Example Script
run: |
make run_one_use_case_example USE_CASE=${{ github.event.inputs.use_case }}
stop-runner-linux:
name: Stop EC2 runner
needs: [run-use-case-examples, start-runner-linux]
runs-on: ubuntu-20.04
if: ${{ always() && (needs.start-runner-linux.result != 'skipped') }}
steps:
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@8c3f20df09ac63af7b3ae3d7c91f105f857d8497
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ secrets.AWS_REGION }}

- name: Stop EC2 runner python 38
uses: machulav/ec2-github-runner@4e0303de215db88e1c489e07a15ca4d867f488ea
if: ${{ always() && needs.start-runner-linux.outputs.ec2-instance-id-38 }}
with:
github-token: ${{ secrets.EC2_RUNNER_BOT_TOKEN }}
label: ${{ needs.start-runner-linux.outputs.label-38 }}
ec2-instance-id: ${{ needs.start-runner-linux.outputs.ec2-instance-id-38 }}
mode: stop

send-report:
if: ${{ always() }}
needs:
[
start-runner-linux,
run-use-case-examples,
stop-runner-linux,
]
name: Send Slack notification
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v4

- name: Prepare whole job status
if: ${{ always() }}
continue-on-error: true
env:
NEEDS_JSON: ${{ toJSON(needs) }}
run: |
echo "${NEEDS_JSON}" > /tmp/needs_context.json
JOB_STATUS=$(python3 ./script/actions_utils/actions_combine_status.py \
--needs_context_json /tmp/needs_context.json)
echo "JOB_STATUS=${JOB_STATUS}" >> "$GITHUB_ENV"
- name: Slack Notification
if: ${{ always() }}
continue-on-error: true
uses: rtCamp/action-slack-notify@b24d75fe0e728a4bf9fc42ee217caa686d141ee8
env:
SLACK_CHANNEL: ${{ secrets.SLACK_CHANNEL }}
SLACK_ICON: https://pbs.twimg.com/profile_images/1274014582265298945/OjBKP9kn_400x400.png
SLACK_COLOR: ${{ env.JOB_STATUS || 'failure' }}
SLACK_MESSAGE: "Full run of use case examples finished with status ${{ env.JOB_STATUS || 'failure' }} \
(${{ env.ACTION_RUN_URL }})\n\
- start-runner-linux: ${{ needs.start-runner-linux.result || 'Did not run.'}}\n\n\
- run-use-case-examples: ${{ needs.run-use-case-examples.result || 'Did not run.' }}\n\n\
- stop-runner-linux: ${{ needs.stop-runner-linux.result || 'Did not run.'}}"
SLACK_USERNAME: ${{ secrets.BOT_USERNAME }}
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
4 changes: 2 additions & 2 deletions .github/workflows/run_use_cases_examples.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ jobs:
apt-get update && apt-get install -y python3-venv make git git-lfs binutils
- name: Checkout Code
uses: actions/checkout@v4
uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633
with:
lfs: true

Expand Down Expand Up @@ -95,7 +95,7 @@ jobs:
name: Send Slack notification
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2 # Update to the latest stable version
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633

- name: Prepare whole job status
if: ${{ always() }}
Expand Down
12 changes: 10 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ spcc:

PCC_DEPS := check_python_format check_finalize_nb python_linting mypy_ci pydocstyle shell_lint
PCC_DEPS += check_version_coherence check_licenses check_nbqa check_supported_ops
PCC_DEPS += check_refresh_notebooks_list check_mdformat
PCC_DEPS += check_refresh_notebooks_list check_refresh_use_cases_list check_mdformat
PCC_DEPS += check_unused_images check_utils_use_case gitleaks

.PHONY: pcc_internal
Expand Down Expand Up @@ -532,10 +532,18 @@ jupyter_execute_parallel:
refresh_notebooks_list:
poetry run python script/actions_utils/refresh_notebooks_list.py .github/workflows/refresh-one-notebook.yaml

.PHONY: refresh_use_cases_list # Refresh the list of use cases currently available
refresh_use_cases_list:
poetry run python script/actions_utils/refresh_use_cases_list.py .github/workflows/run_one_use_cases_example.yaml

.PHONY: check_refresh_notebooks_list # Check if the list of notebooks currently available hasn't change
check_refresh_notebooks_list:
poetry run python script/actions_utils/refresh_notebooks_list.py .github/workflows/refresh-one-notebook.yaml --check

.PHONY: check_refresh_use_cases_list # Check if the list of use cases currently available hasn't change
check_refresh_use_cases_list:
poetry run python script/actions_utils/refresh_use_cases_list.py .github/workflows/run_one_use_cases_example.yaml --check

.PHONY: release_docker # Build a docker release image
release_docker:
EV_FILE="$$(mktemp tmp.docker.XXXX)" && \
Expand Down Expand Up @@ -825,7 +833,7 @@ clean_pycache:
clean_sklearn_cache:
rm -rf ~/scikit_learn_data

.PHONY: run_one_use_case_example # Run one use-case example (USE_CASE, eg use_case_examples/hybrid_model)
.PHONY: run_one_use_case_example # Run one use-case example (USE_CASE, e.g. hybrid_model)
run_one_use_case_example:
USE_CASE=$(USE_CASE) ./script/make_utils/run_use_case_examples.sh

Expand Down
107 changes: 107 additions & 0 deletions script/actions_utils/refresh_use_cases_list.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import argparse
from pathlib import Path

SCRIPT_NAME = Path(__file__).name
USE_CASES_DIRS = [Path(r"use_case_examples")]

SMALL_TAB = " "
TAB = SMALL_TAB * 4

# Headers for updating sections
SECTION_HEADERS = {
"use_cases": {
"start": TAB
+ f"# --- {SCRIPT_NAME}: refresh list of use cases currently available [START] ---",
"end": TAB
+ f"# --- {SCRIPT_NAME}: refresh list of use cases currently available [END] ---",
},
"paths": {
"start": SMALL_TAB
+ f"# --- {SCRIPT_NAME}: refresh list of use case paths currently available [START] ---",
"end": SMALL_TAB
+ f"# --- {SCRIPT_NAME}: refresh list of use case paths currently available [END] ---",
},
}


def no_edit_message(indent):
"""Generates no edit message with appropriate indentation."""
return indent + "# --- do not edit, auto generated part by `make refresh_use_cases_list` ---\n"


def find_use_cases_with_makefile():
"""Finds directories containing a Makefile, indicating a valid use case."""
use_case_paths = []
for use_cases_dir in USE_CASES_DIRS:
for use_cases_path in use_cases_dir.rglob("*"):
if use_cases_path.is_dir() and (use_cases_path / "Makefile").exists():
relative_path = Path(*use_cases_path.parts[1:])
use_case_paths.append(relative_path)
use_case_paths.sort(key=lambda path: path.as_posix().lower())
return use_case_paths


def update_section(lines, start_header, end_header, new_content, indent):
"""Updates specific sections of the file with new content between start and end headers."""
new_lines = []
in_update_section = False

for line in lines:
if line.startswith(start_header):
in_update_section = True
new_lines.append(line)
new_lines.append(no_edit_message(indent))
new_lines.extend(new_content)
elif line.startswith(end_header):
in_update_section = False
new_lines.append(line)
elif not in_update_section:
new_lines.append(line)

return new_lines


def main(file_to_update, check_mode=False):
use_case_paths = find_use_cases_with_makefile()

with open(file_to_update, "r", encoding="utf-8") as file:
lines = file.readlines()

# Update use case descriptions
use_cases_content = [TAB + f"- {path.as_posix()}\n" for path in use_case_paths]
lines = update_section(
lines,
SECTION_HEADERS["use_cases"]["start"],
SECTION_HEADERS["use_cases"]["end"],
use_cases_content,
TAB,
)

# Update use case paths
use_case_paths_content = [
SMALL_TAB + f'{path.stem}: "{path.as_posix()}"\n' for path in use_case_paths
]
lines = update_section(
lines,
SECTION_HEADERS["paths"]["start"],
SECTION_HEADERS["paths"]["end"],
use_case_paths_content,
SMALL_TAB,
)

if check_mode:
with open(file_to_update, "r", encoding="utf-8") as file:
assert (
file.readlines() == lines
), "List of use cases is not up to date. Please run `make refresh_use_cases_list`."
else:
with open(file_to_update, "w", encoding="utf-8") as file:
file.writelines(lines)


if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Update list of currently available use cases")
parser.add_argument("--check", action="store_true", help="flag to enable just checking mode")
parser.add_argument("file_to_update", type=str, help=".yaml file to update")
args = parser.parse_args()
main(args.file_to_update, check_mode=args.check)

0 comments on commit 845f933

Please sign in to comment.