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

bt forgejo_actions #404

Open
wants to merge 5 commits into
base: master
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
5 changes: 5 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ RUN pacman -Syu --noconfirm \
pacman -Scc --noconfirm
RUN git clone https://github.com/RagnarGrootKoerkamp/BAPCtools /opt/bapctools && \
ln -sfn /opt/bapctools/bin/tools.py /usr/bin/bt && ln -sfn /opt/bapctools/third_party/checktestdata /usr/bin/checktestdata
# TODO: Roll this into the big install above on a bigger update.
RUN pacman -Syu --noconfirm \
texlive-langeuropean \
&& \
pacman -Scc --noconfirm
RUN mkdir /data
WORKDIR /data
ENTRYPOINT ["/bin/bt"]
2 changes: 1 addition & 1 deletion bin/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand Down
90 changes: 89 additions & 1 deletion bin/skel.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -327,3 +330,88 @@ def problem_source_dir(problem):
problem = problem_obj.name
print('\n')
print(substitute(problem_yml, locals()), end='')


def create_forgejo_actions(contest, problems):
if Path('.git').is_dir():
contest_path = Path('.')
forgejo = Path('.forgejo')
elif Path('../.git').is_dir():
contest_path = Path(contest)
forgejo = Path('../.forgejo')
else:
fatal('.git and ../.git not found after changing to contest directory.')

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 = (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 = (src / 'problem.yaml').read_text()
for problem_obj in problems:
problem = problem_obj.name
problem_path = contest_path / problem
problem_workflow = substitute(problem_workflow_source, locals())
problem_workflow_target = forgejo / Path(f'workflows/{contest}/{problem}.yaml')
problem_workflow_target.parent.mkdir(parents=True, exist_ok=True)
problem_workflow_target.write_text(problem_workflow)


# 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')
nest = False
elif Path('../.git').is_dir():
contest_path = Path(contest)
github = Path('../.github')
nest = True
else:
fatal('.git and ../.git not found after changing to contest directory.')

# Copy the contest-level workflow.
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')
else:
contest_workflow_target = github / Path(f'workflows/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_docker_bt/problem.yaml'
).read_text()
for problem_obj in problems:
problem = problem_obj.name
problem_path = contest_path / problem
problem_workflow = substitute(problem_workflow_source, locals())
if nest:
problem_workflow_target = github / Path(f'workflows/{contest}_{problem}.yaml')
else:
problem_workflow_target = github / Path(f'workflows/{problem}.yaml')
problem_workflow_target.parent.mkdir(parents=True, exist_ok=True)
problem_workflow_target.write_text(problem_workflow)
31 changes: 30 additions & 1 deletion bin/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -738,9 +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.'
)

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.'
)

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.'
Expand Down Expand Up @@ -937,6 +958,14 @@ def run_parsed_arguments(args):
skel.create_gitlab_jobs(contest, problems)
return

if action == 'forgejo_actions':
skel.create_forgejo_actions(contest, problems)
return

if action == 'github_actions':
skel.create_github_actions(contest, problems)
return

if action == 'skel':
skel.copy_skel_dir(problems)
return
Expand Down
43 changes: 42 additions & 1 deletion doc/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ 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 gitlabci [--latest-bt]`](#gitlabci)
- [`bt forgejo_actions [--latest-bt]`](#forgejo_actions)
- [`bt github_actions`](#github_actions)
- Exporting
- [`bt samplezip`](#samplezip)
- [`bt zip [--skip] [--force] [--kattis] [--no-solutions]`](#zip)
Expand Down Expand Up @@ -387,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:

```
Expand Down Expand Up @@ -459,6 +464,42 @@ We use the following configuration for the gitlab runners:
"/tmp" = "rw,exec"
```

## `forgejo_actions`

`bt forgejo_actions` writes Forgejo Actions workflows for the current contest to
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 <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
increase the memory limit of the container and mount `/tmp` to memory.
```
container:
options: --memory=4g --memory-swap=4g --tmpfs /tmp:exec
```
and use the following label in `.runner`:
```json
{
"labels": [
"bapctools-docker:docker://ragnargrootkoerkamp/bapctools"
]
}
```

## `github_actions`

`bt github_actions` writes Github Actions workflows for the current contest to
the `.github` directory in the root of the git repository.
When there are multiple contests, run `bt github_actions` once for each
contest (either in the contest directory, or by passing `--contest <contest>`).

The generated workflows are similar to those for `bt gitlabci` described above.

# Exporting

## `samplezip`
Expand Down
26 changes: 26 additions & 0 deletions skel/forgejo_actions_docker_bt/contest.yaml
Original file line number Diff line number Diff line change
@@ -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
19 changes: 19 additions & 0 deletions skel/forgejo_actions_docker_bt/problem.yaml
Original file line number Diff line number Diff line change
@@ -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%}
27 changes: 27 additions & 0 deletions skel/forgejo_actions_latest_bt/contest.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
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
- uses: ./.forgejo/actions/setup
- 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
20 changes: 20 additions & 0 deletions skel/forgejo_actions_latest_bt/problem.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
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
- uses: ./.forgejo/actions/setup
- run: |
./bt all --cp --error --no-bar --force --jobs 0 --problem {%problem_path%}
8 changes: 8 additions & 0 deletions skel/forgejo_actions_latest_bt/setup.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
name: Setup BAPCtools
runs:
using: "composite"
steps:
- name: update BAPCtools
run: |
git -C /opt/hostedtoolcache/BAPCtools pull --ff-only || git clone https://github.com/RagnarGrootKoerkamp/BAPCtools.git /opt/hostedtoolcache/BAPCtools
ln -s /opt/hostedtoolcache/BAPCtools/bin/tools.py bt
7 changes: 7 additions & 0 deletions skel/gitlab_ci/header_docker_bt.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
image:
name: ragnargrootkoerkamp/bapctools
entrypoint: [""]

default:
before_script:
- ln -s /usr/bin/bt bt
File renamed without changes.
Loading