diff --git a/bin/config.py b/bin/config.py index 07ff9e02..23ce2948 100644 --- a/bin/config.py +++ b/bin/config.py @@ -96,7 +96,7 @@ grep -Ev '^(h|jobs|time|verbose)$' | sed "s/^/'/;s/$/',/" | tr '\n' ' ' | sed 's/^/args_list = [/;s/, $/]\n/' """ # fmt: off -args_list = ['1', 'add', 'all', 'answer', 'api', 'author', 'check_deterministic', 'clean', 'colors', 'contest', 'contest_id', 'contestname', 'cp', 'default_solution', 'depth', 'directory', 'error', 'force', 'force_build', 'input', 'interaction', 'interactive', 'invalid', 'kattis', 'language', 'memory', 'move_to', 'no_bar', 'no_generate', 'no_solution', 'no_solutions', 'no_testcase_sanity_checks', 'no_timelimit', 'no_validators', 'no_visualizer', 'open', 'order', 'order_from_ccs', 'overview', 'password', 'post_freeze', 'problem', 'problemname', 'remove', 'reorder', 'samples', 'sanitizer', 'skel', 'skip', 'sort', 'submissions', 'table', 'testcases', 'timelimit', 'timeout', 'token', 'tree', 'username', 'validation', 'watch', 'web', 'write'] +args_list = ['1', 'add', 'all', 'answer', 'api', 'author', 'check_deterministic', 'clean', 'colors', 'contest', 'contest_id', 'contestname', 'cp', 'default_solution', 'depth', 'directory', 'error', 'force', 'force_build', 'input', 'interaction', 'interactive', 'invalid', 'kattis', 'language', 'latest_bt', 'memory', 'move_to', 'no_bar', 'no_generate', 'no_solution', 'no_solutions', 'no_testcase_sanity_checks', 'no_timelimit', 'no_validators', 'no_visualizer', 'open', 'order', 'order_from_ccs', 'overview', 'password', 'post_freeze', 'problem', 'problemname', 'remove', 'reorder', 'samples', 'sanitizer', 'skel', 'skip', 'sort', 'submissions', 'table', 'testcases', 'timelimit', 'timeout', 'token', 'tree', 'username', 'validation', 'watch', 'web', 'write'] # fmt: on diff --git a/bin/skel.py b/bin/skel.py index ad0c8036..5e636e8f 100644 --- a/bin/skel.py +++ b/bin/skel.py @@ -312,7 +312,10 @@ def create_gitlab_jobs(contest, problems): def problem_source_dir(problem): return problem.path.resolve().relative_to(Path('..').resolve()) - header_yml = (config.tools_root / 'skel/gitlab_ci/header.yaml').read_text() + if config.args.latest_bt: + header_yml = (config.tools_root / 'skel/gitlab_ci/header_latest_bt.yaml').read_text() + else: + header_yml = (config.tools_root / 'skel/gitlab_ci/header_docker_bt.yaml').read_text() print(substitute(header_yml, locals())) contest_yml = (config.tools_root / 'skel/gitlab_ci/contest.yaml').read_text() @@ -339,21 +342,27 @@ def create_forgejo_actions(contest, problems): else: fatal('.git and ../.git not found after changing to contest directory.') - # Copy the 'setup' action: - setup_action_source = config.tools_root / 'skel/forgejo_actions/setup.yaml' - setup_action_target = forgejo / Path('actions/setup/action.yml') - setup_action_target.parent.mkdir(parents=True, exist_ok=True) - shutil.copy(setup_action_source, setup_action_target) + if config.args.latest_bt: + src = config.tools_root / 'skel/forgejo_actions_latest_bt' + else: + src = config.tools_root / 'skel/forgejo_actions_docker_bt' + + if config.args.latest_bt: + # Copy the 'setup' action: + setup_action_source = src / 'setup.yaml' + setup_action_target = forgejo / Path('actions/setup/action.yml') + setup_action_target.parent.mkdir(parents=True, exist_ok=True) + shutil.copy(setup_action_source, setup_action_target) # Copy the contest-level workflow. - contest_workflow_source = (config.tools_root / 'skel/forgejo_actions/contest.yaml').read_text() + contest_workflow_source = (src / 'contest.yaml').read_text() contest_workflow = substitute(contest_workflow_source, locals()) contest_workflow_target = forgejo / Path(f'workflows/{contest}/contest.yaml') contest_workflow_target.parent.mkdir(parents=True, exist_ok=True) contest_workflow_target.write_text(contest_workflow) # Copy the problem-level workflows. - problem_workflow_source = (config.tools_root / 'skel/forgejo_actions/problem.yaml').read_text() + problem_workflow_source = (src / 'problem.yaml').read_text() for problem_obj in problems: problem = problem_obj.name problem_path = contest_path / problem @@ -366,6 +375,9 @@ def create_forgejo_actions(contest, problems): # Differences with forgejo: # - flat structure, with all workflows directly in `.github/workflows`. def create_github_actions(contest, problems): + if config.args.latest_bt: + fatal('Caching the latest BAPCtools is not supported for github actions.') + if Path('.git').is_dir(): contest_path = Path('.') github = Path('.github') @@ -377,14 +389,10 @@ def create_github_actions(contest, problems): else: fatal('.git and ../.git not found after changing to contest directory.') - # Copy the 'setup' action: - setup_action_source = config.tools_root / 'skel/forgejo_actions/setup.yaml' - setup_action_target = github / Path('actions/setup/action.yml') - setup_action_target.parent.mkdir(parents=True, exist_ok=True) - shutil.copy(setup_action_source, setup_action_target) - # Copy the contest-level workflow. - contest_workflow_source = (config.tools_root / 'skel/forgejo_actions/contest.yaml').read_text() + contest_workflow_source = ( + config.tools_root / 'skel/forgejo_actions_docker_bt/contest.yaml' + ).read_text() contest_workflow = substitute(contest_workflow_source, locals()) if nest: contest_workflow_target = github / Path(f'workflows/{contest}.yaml') @@ -394,7 +402,9 @@ def create_github_actions(contest, problems): contest_workflow_target.write_text(contest_workflow) # Copy the problem-level workflows. - problem_workflow_source = (config.tools_root / 'skel/forgejo_actions/problem.yaml').read_text() + problem_workflow_source = ( + config.tools_root / 'skel/forgejo_actions_docker_bt/problem.yaml' + ).read_text() for problem_obj in problems: problem = problem_obj.name problem_path = contest_path / problem diff --git a/bin/tools.py b/bin/tools.py index 071389cb..cea31557 100755 --- a/bin/tools.py +++ b/bin/tools.py @@ -738,21 +738,30 @@ def build_parser(): 'samplezip', parents=[global_parser], help='Create zip file of all samples.' ) - subparsers.add_parser( + gitlab_parser = subparsers.add_parser( 'gitlabci', parents=[global_parser], help='Print a list of jobs for the given contest.' ) + gitlab_parser.add_argument( + '--latest-bt', action='store_true', help='Cache the latest version of BAPCtools.' + ) - subparsers.add_parser( + forgejo_parser = subparsers.add_parser( 'forgejo_actions', parents=[global_parser], help='Setup Forgejo Actions workflows in .forgejo.', ) + forgejo_parser.add_argument( + '--latest-bt', action='store_true', help='Cache the latest version of BAPCtools.' + ) - subparsers.add_parser( + github_parser = subparsers.add_parser( 'github_actions', parents=[global_parser], help='Setup Github Actions workflows in .github.', ) + github_parser.add_argument( + '--latest-bt', action='store_true', help='Cache the latest version of BAPCtools.' + ) exportparser = subparsers.add_parser( 'export', parents=[global_parser], help='Export the problem or contest to DOMjudge.' diff --git a/doc/commands.md b/doc/commands.md index d9b96033..d90e9390 100644 --- a/doc/commands.md +++ b/doc/commands.md @@ -30,8 +30,8 @@ This lists all subcommands and their most important options. - [`bt new_problem [problemname] [--author AUTHOR] [--validation {default,custom,custom interactive}] [--skel SKEL]`](#new_problem) - [`bt skel [--skel SKEL] directory [directory ...]`](#skel) - [`bt rename_problem [problemname]`](#rename_problem) - - [`bt gitlabci`](#gitlabci) - - [`bt forgejo_actions`](#forgejo_actions) + - [`bt gitlabci [--latest-bt]`](#gitlabci) + - [`bt forgejo_actions [--latest-bt]`](#forgejo_actions) - [`bt github_actions`](#github_actions) - Exporting - [`bt samplezip`](#samplezip) @@ -389,6 +389,9 @@ Do not forget to pass a `--problem` to rename when running this from a contest d `bt gitlabici` prints configuration for Gitlab Continuous Integration to the terminal. This can be piped into the `.gitlab-ci.yml` file in the root of the repository. When there are multiple contests, just append the `bt gitlabci` of each of them, but deduplicate the top level `image:` and `default:` keys. +Use the `--latest-bt` flag to pull the latest version of BAPCtools before each +run. By default, the version in the docker image is used. + Example output: ``` @@ -468,6 +471,9 @@ the `.forgejo` directory in the root of the git repository. When there are multiple contests, run `bt forgejo_actions` once for each contest (either in the contest directory, or by passing `--contest `). +Use the `--latest-bt` flag to pull the latest version of BAPCtools before each +run. By default, the version in the docker image is used. + The generated workflows are similar to those for `bt gitlabci` described above. For smooth operation, use the following in the forgejo runner `config.yaml` to diff --git a/skel/forgejo_actions_docker_bt/contest.yaml b/skel/forgejo_actions_docker_bt/contest.yaml new file mode 100644 index 00000000..d23cc3b1 --- /dev/null +++ b/skel/forgejo_actions_docker_bt/contest.yaml @@ -0,0 +1,26 @@ +name: {%contest%} PDFs +on: + push: + branches: + - master + paths: + - {%contest_path%}/*/problem_statement/** +jobs: + build_pdfs: + name: {%contest%} PDFs + runs-on: bapctools-docker + container: + image: ragnargrootkoerkamp/bapctools + steps: + - uses: actions/checkout@v4 + - run: | + bt pdf --cp --error --no-bar --contest {%contest_path%} + bt solutions --cp --error --no-bar --contest {%contest_path%} + + - uses: actions/upload-artifact@v3 + with: + name: pdfs + path: | + {%contest_path%}/contest*.pdf + {%contest_path%}/solution*.pdf + retention-days: 7 diff --git a/skel/forgejo_actions_docker_bt/problem.yaml b/skel/forgejo_actions_docker_bt/problem.yaml new file mode 100644 index 00000000..3ce7b43b --- /dev/null +++ b/skel/forgejo_actions_docker_bt/problem.yaml @@ -0,0 +1,19 @@ +name: {%problem_path%} +on: + push: + branches: + - master + paths: + - {%problem_path%}/** + - "!{%problem_path%}/problem_statement/**" + - "!{%problem_path%}/attachments/**" +jobs: + verify: + name: Verify {%problem%} + runs-on: bapctools-docker + container: + image: ragnargrootkoerkamp/bapctools + steps: + - uses: actions/checkout@v4 + - run: | + bt all --cp --error --no-bar --force --jobs 0 --problem {%problem_path%} diff --git a/skel/forgejo_actions/contest.yaml b/skel/forgejo_actions_latest_bt/contest.yaml similarity index 100% rename from skel/forgejo_actions/contest.yaml rename to skel/forgejo_actions_latest_bt/contest.yaml diff --git a/skel/forgejo_actions/problem.yaml b/skel/forgejo_actions_latest_bt/problem.yaml similarity index 100% rename from skel/forgejo_actions/problem.yaml rename to skel/forgejo_actions_latest_bt/problem.yaml diff --git a/skel/forgejo_actions/setup.yaml b/skel/forgejo_actions_latest_bt/setup.yaml similarity index 100% rename from skel/forgejo_actions/setup.yaml rename to skel/forgejo_actions_latest_bt/setup.yaml diff --git a/skel/gitlab_ci/header_docker_bt.yaml b/skel/gitlab_ci/header_docker_bt.yaml new file mode 100644 index 00000000..20c890b3 --- /dev/null +++ b/skel/gitlab_ci/header_docker_bt.yaml @@ -0,0 +1,7 @@ +image: + name: ragnargrootkoerkamp/bapctools + entrypoint: [""] + +default: + before_script: + - ln -s /usr/bin/bt bt diff --git a/skel/gitlab_ci/header.yaml b/skel/gitlab_ci/header_latest_bt.yaml similarity index 100% rename from skel/gitlab_ci/header.yaml rename to skel/gitlab_ci/header_latest_bt.yaml