prepare-assignment 0.2.1__tar.gz → 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- prepare_assignment-0.4.0/.github/ISSUE_TEMPLATE/bug_report.md +18 -0
- prepare_assignment-0.4.0/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
- prepare_assignment-0.4.0/.github/dependabot.yml +25 -0
- prepare_assignment-0.4.0/.github/workflows/pr-title.yml +39 -0
- prepare_assignment-0.4.0/.github/workflows/pypi-publish.yml +45 -0
- prepare_assignment-0.4.0/.github/workflows/release.yml +33 -0
- prepare_assignment-0.4.0/.github/workflows/semantic-release.yml +57 -0
- prepare_assignment-0.4.0/.github/workflows/test.yml +63 -0
- prepare_assignment-0.4.0/.gitignore +165 -0
- prepare_assignment-0.4.0/.releaserc.json +9 -0
- prepare_assignment-0.4.0/PKG-INFO +208 -0
- prepare_assignment-0.4.0/README.md +187 -0
- prepare_assignment-0.4.0/prepare_assignment/cli/main.py +129 -0
- {prepare_assignment-0.2.1 → prepare_assignment-0.4.0}/prepare_assignment/cli/task.py +3 -3
- prepare_assignment-0.4.0/prepare_assignment/core/check.py +142 -0
- {prepare_assignment-0.2.1 → prepare_assignment-0.4.0}/prepare_assignment/core/command.py +52 -9
- prepare_assignment-0.4.0/prepare_assignment/core/expression.py +175 -0
- {prepare_assignment-0.2.1 → prepare_assignment-0.4.0}/prepare_assignment/core/main.py +15 -9
- prepare_assignment-0.4.0/prepare_assignment/core/preparer.py +297 -0
- prepare_assignment-0.4.0/prepare_assignment/core/runner.py +237 -0
- prepare_assignment-0.4.0/prepare_assignment/core/shell.py +126 -0
- prepare_assignment-0.4.0/prepare_assignment/core/subsituter.py +74 -0
- {prepare_assignment-0.2.1 → prepare_assignment-0.4.0}/prepare_assignment/core/task_handler.py +31 -13
- {prepare_assignment-0.2.1 → prepare_assignment-0.4.0}/prepare_assignment/core/validator.py +9 -24
- prepare_assignment-0.4.0/prepare_assignment/core/versions.py +124 -0
- {prepare_assignment-0.2.1 → prepare_assignment-0.4.0}/prepare_assignment/data/config.py +1 -0
- prepare_assignment-0.4.0/prepare_assignment/data/constants.py +12 -0
- {prepare_assignment-0.2.1 → prepare_assignment-0.4.0}/prepare_assignment/data/errors.py +14 -0
- prepare_assignment-0.4.0/prepare_assignment/data/job_environment.py +26 -0
- {prepare_assignment-0.2.1 → prepare_assignment-0.4.0}/prepare_assignment/data/prepare.py +20 -5
- {prepare_assignment-0.2.1 → prepare_assignment-0.4.0}/prepare_assignment/data/task_definition.py +11 -10
- {prepare_assignment-0.2.1 → prepare_assignment-0.4.0}/prepare_assignment/data/task_properties.py +2 -2
- prepare_assignment-0.4.0/prepare_assignment/data/types.py +26 -0
- {prepare_assignment-0.2.1 → prepare_assignment-0.4.0}/prepare_assignment/schemas/config.schema.json +14 -1
- prepare_assignment-0.4.0/prepare_assignment/schemas/prepare.schema.json +116 -0
- {prepare_assignment-0.2.1 → prepare_assignment-0.4.0}/prepare_assignment/schemas/task.schema.json +37 -1
- {prepare_assignment-0.2.1 → prepare_assignment-0.4.0}/prepare_assignment/utils/config.py +2 -4
- prepare_assignment-0.4.0/prepare_assignment/utils/files.py +40 -0
- {prepare_assignment-0.2.1 → prepare_assignment-0.4.0}/prepare_assignment/utils/logger.py +13 -0
- prepare_assignment-0.4.0/prepare_assignment/utils/resources.py +14 -0
- {prepare_assignment-0.2.1 → prepare_assignment-0.4.0}/prepare_assignment/utils/tasks.py +1 -1
- prepare_assignment-0.4.0/pyproject.toml +48 -0
- prepare_assignment-0.4.0/tests/__init__.py +0 -0
- prepare_assignment-0.4.0/tests/core/__init__.py +0 -0
- prepare_assignment-0.4.0/tests/core/test_check.py +205 -0
- prepare_assignment-0.4.0/tests/core/test_command.py +180 -0
- prepare_assignment-0.4.0/tests/core/test_expression.py +288 -0
- prepare_assignment-0.4.0/tests/core/test_preparer.py +285 -0
- prepare_assignment-0.4.0/tests/core/test_resolve_version.py +197 -0
- prepare_assignment-0.4.0/tests/core/test_runner.py +573 -0
- prepare_assignment-0.4.0/tests/core/test_runner_process.py +290 -0
- prepare_assignment-0.4.0/tests/core/test_shell.py +145 -0
- prepare_assignment-0.4.0/tests/core/test_substituter.py +132 -0
- prepare_assignment-0.4.0/tests/core/test_task_handler.py +95 -0
- prepare_assignment-0.4.0/tests/core/test_validator.py +181 -0
- prepare_assignment-0.4.0/tests/data/__init__.py +0 -0
- prepare_assignment-0.4.0/tests/data/test_prepare.py +66 -0
- prepare_assignment-0.4.0/tests/data/test_types.py +27 -0
- prepare_assignment-0.4.0/tests/test_main.py +88 -0
- prepare_assignment-0.4.0/tests/testproject/prepare.yml +22 -0
- prepare_assignment-0.4.0/tests/testproject/solution/pom.xml +19 -0
- prepare_assignment-0.4.0/tests/testproject/solution/src/main/java/gradelist/AssessmentResult.java +36 -0
- prepare_assignment-0.4.0/tests/testproject/solution/src/main/java/gradelist/GradeList.java +40 -0
- prepare_assignment-0.4.0/tests/testproject/solution/src/main/java/gradelist/Test.java +3 -0
- prepare_assignment-0.4.0/tests/testproject/solution/src/test/java/gradelist/AssessmentResultTest.java +65 -0
- prepare_assignment-0.4.0/tests/testproject/solution/src/test/java/gradelist/GradeListTest.java +67 -0
- prepare_assignment-0.4.0/tests/utils/__init__.py +0 -0
- prepare_assignment-0.4.0/tests/utils/test_config.py +30 -0
- prepare_assignment-0.4.0/tests/utils/test_default_validator.py +39 -0
- prepare_assignment-0.4.0/tests/utils/test_files.py +46 -0
- prepare_assignment-0.4.0/tests/utils/test_logger.py +115 -0
- prepare_assignment-0.4.0/tests/utils/test_paths.py +98 -0
- prepare_assignment-0.4.0/tests/utils/test_resources.py +14 -0
- prepare_assignment-0.4.0/uv.lock +972 -0
- prepare_assignment-0.2.1/PKG-INFO +0 -129
- prepare_assignment-0.2.1/README.md +0 -99
- prepare_assignment-0.2.1/prepare_assignment/cli/main.py +0 -61
- prepare_assignment-0.2.1/prepare_assignment/core/preparer.py +0 -244
- prepare_assignment-0.2.1/prepare_assignment/core/runner.py +0 -130
- prepare_assignment-0.2.1/prepare_assignment/core/subsituter.py +0 -102
- prepare_assignment-0.2.1/prepare_assignment/data/constants.py +0 -32
- prepare_assignment-0.2.1/prepare_assignment/data/job_environment.py +0 -14
- prepare_assignment-0.2.1/prepare_assignment/schemas/prepare.schema.json +0 -51
- prepare_assignment-0.2.1/prepare_assignment/schemas/task.schema.json_template +0 -22
- prepare_assignment-0.2.1/prepare_assignment/utils/executables.py +0 -24
- prepare_assignment-0.2.1/pyproject.toml +0 -42
- {prepare_assignment-0.2.1 → prepare_assignment-0.4.0}/LICENSE +0 -0
- {prepare_assignment-0.2.1 → prepare_assignment-0.4.0}/prepare_assignment/__init__.py +0 -0
- {prepare_assignment-0.2.1 → prepare_assignment-0.4.0}/prepare_assignment/__main__.py +0 -0
- {prepare_assignment-0.2.1 → prepare_assignment-0.4.0}/prepare_assignment/cli/__init__.py +0 -0
- {prepare_assignment-0.2.1 → prepare_assignment-0.4.0}/prepare_assignment/cli/tasks.py +0 -0
- {prepare_assignment-0.2.1 → prepare_assignment-0.4.0}/prepare_assignment/core/__init__.py +0 -0
- {prepare_assignment-0.2.1 → prepare_assignment-0.4.0}/prepare_assignment/data/__init__.py +0 -0
- {prepare_assignment-0.2.1 → prepare_assignment-0.4.0}/prepare_assignment/utils/__init__.py +0 -0
- {prepare_assignment-0.2.1 → prepare_assignment-0.4.0}/prepare_assignment/utils/default_validator.py +0 -0
- {prepare_assignment-0.2.1 → prepare_assignment-0.4.0}/prepare_assignment/utils/dependency.py +0 -0
- {prepare_assignment-0.2.1 → prepare_assignment-0.4.0}/prepare_assignment/utils/paths.py +0 -0
- {prepare_assignment-0.2.1 → prepare_assignment-0.4.0}/prepare_assignment/utils/virtual_env.py +0 -0
- {prepare_assignment-0.2.1 → prepare_assignment-0.4.0}/prepare_assignment/utils/yml_loader.py +0 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Bug report
|
|
3
|
+
about: Create a report to help us improve
|
|
4
|
+
title: '[Bug] '
|
|
5
|
+
labels: ["bug"]
|
|
6
|
+
assignees: ''
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Describe the bug
|
|
10
|
+
A clear and concise description of what the bug is.
|
|
11
|
+
|
|
12
|
+
## Expected behavior
|
|
13
|
+
A clear and concise description of what you expected to happen.
|
|
14
|
+
|
|
15
|
+
## To Reproduce
|
|
16
|
+
Steps to reproduce the behavior:
|
|
17
|
+
|
|
18
|
+
1.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Feature request
|
|
3
|
+
about: Suggest an idea for this project
|
|
4
|
+
title: ''
|
|
5
|
+
labels: ''
|
|
6
|
+
assignees: ''
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
**Is your feature request related to a problem? Please describe.**
|
|
11
|
+
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
|
12
|
+
|
|
13
|
+
**Describe the solution you'd like**
|
|
14
|
+
A clear and concise description of what you want to happen.
|
|
15
|
+
|
|
16
|
+
**Describe alternatives you've considered**
|
|
17
|
+
A clear and concise description of any alternative solutions or features you've considered.
|
|
18
|
+
|
|
19
|
+
**Additional context**
|
|
20
|
+
Add any other context or screenshots about the feature request here.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
- package-ecosystem: "uv"
|
|
4
|
+
directory: "/"
|
|
5
|
+
schedule:
|
|
6
|
+
interval: "weekly"
|
|
7
|
+
# PR titles must follow Conventional Commits (checked by pr-title.yml)
|
|
8
|
+
commit-message:
|
|
9
|
+
prefix: "build"
|
|
10
|
+
include: "scope"
|
|
11
|
+
groups:
|
|
12
|
+
python-dependencies:
|
|
13
|
+
patterns:
|
|
14
|
+
- "*"
|
|
15
|
+
- package-ecosystem: "github-actions"
|
|
16
|
+
directory: "/"
|
|
17
|
+
schedule:
|
|
18
|
+
interval: "weekly"
|
|
19
|
+
commit-message:
|
|
20
|
+
prefix: "ci"
|
|
21
|
+
include: "scope"
|
|
22
|
+
groups:
|
|
23
|
+
github-actions:
|
|
24
|
+
patterns:
|
|
25
|
+
- "*"
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
name: PR title
|
|
2
|
+
|
|
3
|
+
# With squash merging the PR title becomes the commit subject on main, which is
|
|
4
|
+
# what semantic-release parses to pick the next version. An unparseable title
|
|
5
|
+
# is therefore a release that silently does not happen.
|
|
6
|
+
on:
|
|
7
|
+
pull_request:
|
|
8
|
+
branches: [main]
|
|
9
|
+
types: [opened, edited, synchronize, reopened]
|
|
10
|
+
|
|
11
|
+
concurrency:
|
|
12
|
+
group: pr-title-${{ github.event.pull_request.number }}
|
|
13
|
+
cancel-in-progress: true
|
|
14
|
+
|
|
15
|
+
permissions:
|
|
16
|
+
pull-requests: read
|
|
17
|
+
|
|
18
|
+
jobs:
|
|
19
|
+
lint:
|
|
20
|
+
name: conventional title
|
|
21
|
+
runs-on: ubuntu-latest
|
|
22
|
+
steps:
|
|
23
|
+
- uses: amannn/action-semantic-pull-request@v6
|
|
24
|
+
env:
|
|
25
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
26
|
+
with:
|
|
27
|
+
# The types already in use on main, plus revert.
|
|
28
|
+
types: |
|
|
29
|
+
feat
|
|
30
|
+
fix
|
|
31
|
+
docs
|
|
32
|
+
refactor
|
|
33
|
+
test
|
|
34
|
+
ci
|
|
35
|
+
style
|
|
36
|
+
chore
|
|
37
|
+
perf
|
|
38
|
+
build
|
|
39
|
+
revert
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
name: PyPI publish
|
|
2
|
+
|
|
3
|
+
# Reusable build and publish. Two callers pass a version in:
|
|
4
|
+
# - release.yml on a human-pushed v* tag
|
|
5
|
+
# - semantic-release.yml after semantic-release cuts a new version
|
|
6
|
+
#
|
|
7
|
+
# It lives here rather than in either caller because a tag pushed with
|
|
8
|
+
# GITHUB_TOKEN does not trigger workflows, so semantic-release cannot rely on
|
|
9
|
+
# release.yml's tag trigger to publish the version it just cut.
|
|
10
|
+
on:
|
|
11
|
+
workflow_call:
|
|
12
|
+
inputs:
|
|
13
|
+
version:
|
|
14
|
+
description: Version to build and publish, without the leading v (e.g. 1.2.3).
|
|
15
|
+
required: true
|
|
16
|
+
type: string
|
|
17
|
+
|
|
18
|
+
permissions:
|
|
19
|
+
contents: read
|
|
20
|
+
|
|
21
|
+
jobs:
|
|
22
|
+
publish:
|
|
23
|
+
name: build & publish
|
|
24
|
+
runs-on: ubuntu-latest
|
|
25
|
+
|
|
26
|
+
steps:
|
|
27
|
+
- uses: actions/checkout@v7
|
|
28
|
+
|
|
29
|
+
- name: Install uv
|
|
30
|
+
uses: astral-sh/setup-uv@v10.1.0
|
|
31
|
+
with:
|
|
32
|
+
python-version: "3.12"
|
|
33
|
+
|
|
34
|
+
# The version is not committed back to main, so the version in
|
|
35
|
+
# pyproject.toml is stale. Set the released version just for this build.
|
|
36
|
+
- name: Set version
|
|
37
|
+
run: uv version "${{ inputs.version }}" --frozen
|
|
38
|
+
|
|
39
|
+
- name: Build
|
|
40
|
+
run: uv build
|
|
41
|
+
|
|
42
|
+
- name: Publish
|
|
43
|
+
run: uv publish
|
|
44
|
+
env:
|
|
45
|
+
UV_PUBLISH_TOKEN: ${{ secrets.PYPI_TOKEN }}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
# Fires only on tags pushed by a human: a manual tag cut as an escape hatch.
|
|
4
|
+
# Routine releases come from semantic-release.yml, whose GITHUB_TOKEN-pushed
|
|
5
|
+
# tags deliberately do not trigger this workflow — that is what keeps a
|
|
6
|
+
# release from being published twice.
|
|
7
|
+
on:
|
|
8
|
+
push:
|
|
9
|
+
tags: ["v*"]
|
|
10
|
+
|
|
11
|
+
concurrency:
|
|
12
|
+
group: release-${{ github.ref }}
|
|
13
|
+
cancel-in-progress: true
|
|
14
|
+
|
|
15
|
+
permissions:
|
|
16
|
+
contents: read
|
|
17
|
+
|
|
18
|
+
jobs:
|
|
19
|
+
version:
|
|
20
|
+
name: version from tag
|
|
21
|
+
runs-on: ubuntu-latest
|
|
22
|
+
outputs:
|
|
23
|
+
version: ${{ steps.version.outputs.version }}
|
|
24
|
+
steps:
|
|
25
|
+
- id: version
|
|
26
|
+
run: echo "version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT"
|
|
27
|
+
|
|
28
|
+
publish:
|
|
29
|
+
needs: version
|
|
30
|
+
uses: ./.github/workflows/pypi-publish.yml
|
|
31
|
+
with:
|
|
32
|
+
version: ${{ needs.version.outputs.version }}
|
|
33
|
+
secrets: inherit
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
name: Semantic release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
|
|
7
|
+
# Never cancel a release mid-flight: a half-run that has tagged but not yet
|
|
8
|
+
# published would need cleaning up by hand.
|
|
9
|
+
concurrency:
|
|
10
|
+
group: semantic-release-${{ github.ref }}
|
|
11
|
+
cancel-in-progress: false
|
|
12
|
+
|
|
13
|
+
permissions:
|
|
14
|
+
contents: read
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
release:
|
|
18
|
+
name: version
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
permissions:
|
|
21
|
+
contents: write # create the tag and the GitHub release
|
|
22
|
+
issues: write # comment "released in vX.Y.Z" on issues
|
|
23
|
+
pull-requests: write # and on the PRs that fed the release
|
|
24
|
+
outputs:
|
|
25
|
+
published: ${{ steps.semantic.outputs.new_release_published }}
|
|
26
|
+
version: ${{ steps.semantic.outputs.new_release_version }}
|
|
27
|
+
|
|
28
|
+
steps:
|
|
29
|
+
- uses: actions/checkout@v7
|
|
30
|
+
with:
|
|
31
|
+
# semantic-release walks back to the previous tag to decide the bump,
|
|
32
|
+
# so a shallow clone makes it compute the wrong version.
|
|
33
|
+
fetch-depth: 0
|
|
34
|
+
persist-credentials: false
|
|
35
|
+
|
|
36
|
+
- uses: actions/setup-node@v7
|
|
37
|
+
with:
|
|
38
|
+
node-version: 22
|
|
39
|
+
|
|
40
|
+
# Pinned to an exact version: this action publishes no floating major
|
|
41
|
+
# tags, so @v6 would not resolve. All three plugins in .releaserc.json
|
|
42
|
+
# ship with the semantic-release core it bundles.
|
|
43
|
+
- name: Semantic release
|
|
44
|
+
id: semantic
|
|
45
|
+
uses: cycjimmy/semantic-release-action@v6.0.0
|
|
46
|
+
env:
|
|
47
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
48
|
+
|
|
49
|
+
# The tag above was pushed with GITHUB_TOKEN, so it will not trigger
|
|
50
|
+
# release.yml. Publish to PyPI here instead.
|
|
51
|
+
publish:
|
|
52
|
+
needs: release
|
|
53
|
+
if: needs.release.outputs.published == 'true'
|
|
54
|
+
uses: ./.github/workflows/pypi-publish.yml
|
|
55
|
+
with:
|
|
56
|
+
version: ${{ needs.release.outputs.version }}
|
|
57
|
+
secrets: inherit
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
name: Test
|
|
2
|
+
|
|
3
|
+
defaults:
|
|
4
|
+
run:
|
|
5
|
+
shell: bash
|
|
6
|
+
|
|
7
|
+
# Only on pull requests: main only changes through squash-merged PRs, which
|
|
8
|
+
# have already passed these checks.
|
|
9
|
+
on:
|
|
10
|
+
pull_request:
|
|
11
|
+
branches: [ "main" ]
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
test:
|
|
15
|
+
strategy:
|
|
16
|
+
fail-fast: false
|
|
17
|
+
matrix:
|
|
18
|
+
python-version: ["3.11", "3.12", "3.13", "3.14"]
|
|
19
|
+
os: ["ubuntu-latest", "windows-latest", "macos-latest"]
|
|
20
|
+
runs-on: ${{ matrix.os }}
|
|
21
|
+
permissions:
|
|
22
|
+
contents: read
|
|
23
|
+
checks: write
|
|
24
|
+
steps:
|
|
25
|
+
- uses: actions/checkout@v7
|
|
26
|
+
- name: Install uv and Python ${{ matrix.python-version }}
|
|
27
|
+
uses: astral-sh/setup-uv@v10.1.0
|
|
28
|
+
with:
|
|
29
|
+
python-version: ${{ matrix.python-version }}
|
|
30
|
+
enable-cache: true
|
|
31
|
+
cache-dependency-glob: "uv.lock"
|
|
32
|
+
cache-suffix: py${{ matrix.python-version }}
|
|
33
|
+
- name: Install dependencies
|
|
34
|
+
run: uv sync --locked --group test
|
|
35
|
+
- name: Run tests
|
|
36
|
+
env:
|
|
37
|
+
PREPARE_TEST_GIT_MODE: https
|
|
38
|
+
run: uv run pytest --cov --cov-report=xml --junitxml=tests.xml
|
|
39
|
+
- name: Test Report
|
|
40
|
+
uses: mikepenz/action-junit-report@v6
|
|
41
|
+
if: success() || failure()
|
|
42
|
+
with:
|
|
43
|
+
check_name: Test Results (Python ${{ matrix.python-version }}, ${{ matrix.os }})
|
|
44
|
+
report_paths: tests.xml
|
|
45
|
+
|
|
46
|
+
typecheck:
|
|
47
|
+
strategy:
|
|
48
|
+
matrix:
|
|
49
|
+
python-version: [ "3.12" ]
|
|
50
|
+
runs-on: "ubuntu-latest"
|
|
51
|
+
steps:
|
|
52
|
+
- uses: actions/checkout@v7
|
|
53
|
+
- name: Install uv and Python ${{ matrix.python-version }}
|
|
54
|
+
uses: astral-sh/setup-uv@v10.1.0
|
|
55
|
+
with:
|
|
56
|
+
python-version: ${{ matrix.python-version }}
|
|
57
|
+
enable-cache: true
|
|
58
|
+
cache-dependency-glob: "uv.lock"
|
|
59
|
+
cache-suffix: typecheck
|
|
60
|
+
- name: Install dependencies
|
|
61
|
+
run: uv sync --locked --group test
|
|
62
|
+
- name: Type checker
|
|
63
|
+
run: uv run mypy prepare_assignment
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
share/python-wheels/
|
|
24
|
+
*.egg-info/
|
|
25
|
+
.installed.cfg
|
|
26
|
+
*.egg
|
|
27
|
+
MANIFEST
|
|
28
|
+
|
|
29
|
+
# PyInstaller
|
|
30
|
+
# Usually these files are written by a python script from a template
|
|
31
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
32
|
+
*.manifest
|
|
33
|
+
*.spec
|
|
34
|
+
|
|
35
|
+
# Installer logs
|
|
36
|
+
pip-log.txt
|
|
37
|
+
pip-delete-this-directory.txt
|
|
38
|
+
|
|
39
|
+
# Unit test / coverage reports
|
|
40
|
+
htmlcov/
|
|
41
|
+
.tox/
|
|
42
|
+
.nox/
|
|
43
|
+
.coverage
|
|
44
|
+
.coverage.*
|
|
45
|
+
.cache
|
|
46
|
+
nosetests.xml
|
|
47
|
+
coverage.xml
|
|
48
|
+
*.cover
|
|
49
|
+
*.py,cover
|
|
50
|
+
.hypothesis/
|
|
51
|
+
.pytest_cache/
|
|
52
|
+
cover/
|
|
53
|
+
|
|
54
|
+
# Translations
|
|
55
|
+
*.mo
|
|
56
|
+
*.pot
|
|
57
|
+
|
|
58
|
+
# Django stuff:
|
|
59
|
+
*.log
|
|
60
|
+
local_settings.py
|
|
61
|
+
db.sqlite3
|
|
62
|
+
db.sqlite3-journal
|
|
63
|
+
|
|
64
|
+
# Flask stuff:
|
|
65
|
+
instance/
|
|
66
|
+
.webassets-cache
|
|
67
|
+
|
|
68
|
+
# Scrapy stuff:
|
|
69
|
+
.scrapy
|
|
70
|
+
|
|
71
|
+
# Sphinx documentation
|
|
72
|
+
docs/_build/
|
|
73
|
+
|
|
74
|
+
# PyBuilder
|
|
75
|
+
.pybuilder/
|
|
76
|
+
target/
|
|
77
|
+
|
|
78
|
+
# Jupyter Notebook
|
|
79
|
+
.ipynb_checkpoints
|
|
80
|
+
|
|
81
|
+
# IPython
|
|
82
|
+
profile_default/
|
|
83
|
+
ipython_config.py
|
|
84
|
+
|
|
85
|
+
# pyenv
|
|
86
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
87
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
88
|
+
# .python-version
|
|
89
|
+
|
|
90
|
+
# pipenv
|
|
91
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
92
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
93
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
94
|
+
# install all needed dependencies.
|
|
95
|
+
#Pipfile.lock
|
|
96
|
+
|
|
97
|
+
# poetry
|
|
98
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
99
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
100
|
+
# commonly ignored for libraries.
|
|
101
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
102
|
+
#poetry.lock
|
|
103
|
+
|
|
104
|
+
# pdm
|
|
105
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
106
|
+
#pdm.lock
|
|
107
|
+
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
|
108
|
+
# in version control.
|
|
109
|
+
# https://pdm.fming.dev/#use-with-ide
|
|
110
|
+
.pdm.toml
|
|
111
|
+
|
|
112
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
113
|
+
__pypackages__/
|
|
114
|
+
|
|
115
|
+
# Celery stuff
|
|
116
|
+
celerybeat-schedule
|
|
117
|
+
celerybeat.pid
|
|
118
|
+
|
|
119
|
+
# SageMath parsed files
|
|
120
|
+
*.sage.py
|
|
121
|
+
|
|
122
|
+
# Environments
|
|
123
|
+
.env
|
|
124
|
+
.venv
|
|
125
|
+
env/
|
|
126
|
+
venv/
|
|
127
|
+
ENV/
|
|
128
|
+
env.bak/
|
|
129
|
+
venv.bak/
|
|
130
|
+
|
|
131
|
+
# Spyder project settings
|
|
132
|
+
.spyderproject
|
|
133
|
+
.spyproject
|
|
134
|
+
|
|
135
|
+
# Rope project settings
|
|
136
|
+
.ropeproject
|
|
137
|
+
|
|
138
|
+
# mkdocs documentation
|
|
139
|
+
/site
|
|
140
|
+
|
|
141
|
+
# mypy
|
|
142
|
+
.mypy_cache/
|
|
143
|
+
.dmypy.json
|
|
144
|
+
dmypy.json
|
|
145
|
+
|
|
146
|
+
# Pyre type checker
|
|
147
|
+
.pyre/
|
|
148
|
+
|
|
149
|
+
# pytype static type analyzer
|
|
150
|
+
.pytype/
|
|
151
|
+
|
|
152
|
+
# Cython debug symbols
|
|
153
|
+
cython_debug/
|
|
154
|
+
|
|
155
|
+
# PyCharm
|
|
156
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
157
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
158
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
159
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
160
|
+
.idea/
|
|
161
|
+
exampleproject/
|
|
162
|
+
tests.xml
|
|
163
|
+
out.txt
|
|
164
|
+
out/
|
|
165
|
+
.vscode
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: prepare-assignment
|
|
3
|
+
Version: 0.4.0
|
|
4
|
+
Summary: Prepare assignment
|
|
5
|
+
Author-email: Bonajo <m.bonajo@fontys.nl>
|
|
6
|
+
License: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Requires-Python: >=3.11
|
|
9
|
+
Requires-Dist: dacite>=1.9.2
|
|
10
|
+
Requires-Dist: gitpython>=3.1.59
|
|
11
|
+
Requires-Dist: jsonschema>=4.21.1
|
|
12
|
+
Requires-Dist: multipledispatch>=1.0.0
|
|
13
|
+
Requires-Dist: packaging>=24.0
|
|
14
|
+
Requires-Dist: prepare-toolbox==0.4.0
|
|
15
|
+
Requires-Dist: ruamel-yaml>=0.18.5
|
|
16
|
+
Requires-Dist: simpleeval>=1.0.0
|
|
17
|
+
Requires-Dist: treelib>=1.7.0
|
|
18
|
+
Requires-Dist: typer==0.27.2
|
|
19
|
+
Requires-Dist: virtualenv>=20.25.0
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
|
|
22
|
+
# Prepare assignment
|
|
23
|
+
|
|
24
|
+
Prepare assignment is a GitHub Actions inspired helper tool to prepare assignments at Fontys Venlo. The goal is to define jobs inside the `prepare.yml` that indicate how to convert a solution project into a student project.
|
|
25
|
+
|
|
26
|
+
## Dependencies
|
|
27
|
+
|
|
28
|
+
- Git
|
|
29
|
+
- Python >=3.11
|
|
30
|
+
|
|
31
|
+
## Installation
|
|
32
|
+
|
|
33
|
+
Prepare-assignment is available from [PyPI](https://pypi.org/).
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
# To install:
|
|
38
|
+
python3 -m pip install prepare-assignment
|
|
39
|
+
|
|
40
|
+
# To upgrade
|
|
41
|
+
python3 -m pip install --upgrade prepare-assignment
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Executing prepare-assignment
|
|
45
|
+
|
|
46
|
+
To execute a `prepare.yml` simply run `prepare run` from the same directory.
|
|
47
|
+
|
|
48
|
+
### Command line interface
|
|
49
|
+
|
|
50
|
+
Use `prepare --help` to which commands and flags are available.
|
|
51
|
+
|
|
52
|
+
## Example `prepare.yml`
|
|
53
|
+
|
|
54
|
+
First we need to have tasks available that can be executed. Take for example a look at the [remove](https://github.com/prepare-assignment/remove) task.
|
|
55
|
+
|
|
56
|
+
The tests use a [testproject](https://github.com/prepare-assignment/core/tree/tests/testproject), which contains an example of a `prepare.yml`, see below for convenience.
|
|
57
|
+
|
|
58
|
+
```yaml
|
|
59
|
+
name: Test project
|
|
60
|
+
jobs:
|
|
61
|
+
prepare:
|
|
62
|
+
- name: remove out
|
|
63
|
+
uses: remove
|
|
64
|
+
with:
|
|
65
|
+
input:
|
|
66
|
+
- "out"
|
|
67
|
+
- "out.txt"
|
|
68
|
+
force: true
|
|
69
|
+
recursive: true
|
|
70
|
+
- name: codestripper
|
|
71
|
+
id: codestripper
|
|
72
|
+
uses: codestripper
|
|
73
|
+
with:
|
|
74
|
+
include:
|
|
75
|
+
- "**/*.java"
|
|
76
|
+
- "pom.xml"
|
|
77
|
+
working-directory: "solution"
|
|
78
|
+
verbosity: 5
|
|
79
|
+
- name: Test a run command with substitution
|
|
80
|
+
run: echo '${{ tasks.codestripper.outputs.stripped-files }}' > out.txt
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
For people familiar with GitHub Actions this should look very familiar. We have jobs that indicate what should happen to prepare an assignment. The tasks are defined in their own repositories, if the `uses` tag doesn't have a username/organization, it will default to `prepare-assignment`. So for example the `remove` task uses the following repository: [prepare-assignment/remove](https://github.com/prepare-assignment/remove)
|
|
84
|
+
|
|
85
|
+
## Step reference
|
|
86
|
+
|
|
87
|
+
Every step has a `name` and either `uses` (a task) or `run` (a shell command).
|
|
88
|
+
|
|
89
|
+
| Property | Applies to | Description |
|
|
90
|
+
|---------------------|----------------|------------------------------------------------------------------------------------------------------------|
|
|
91
|
+
| `name` | all | Name of the step (required) |
|
|
92
|
+
| `id` | all | Identifier used to reference the outputs of the step: `${{ tasks.<id>.outputs.<name> }}` |
|
|
93
|
+
| `if` | all | Only run the step if the expression is true, see [Conditions](#conditions) |
|
|
94
|
+
| `uses` | task | The task to execute, e.g. `remove`, `remove@v1`, `my-org/my-task@v1.2.0` |
|
|
95
|
+
| `with` | task | The inputs of the task |
|
|
96
|
+
| `run` | run | The command (script) to execute |
|
|
97
|
+
| `shell` | run | `bash` (default), `sh`, `pwsh`, `powershell`, `cmd` or `python` |
|
|
98
|
+
| `working-directory` | all | Directory (relative to the `prepare.yml`) in which the step is executed |
|
|
99
|
+
| `env` | all | Environment variables for this step only, values can contain expressions |
|
|
100
|
+
| `continue-on-error` | all | If `true`, a failure of this step doesn't fail the job |
|
|
101
|
+
|
|
102
|
+
The default shell can be changed in the [config file](#config-file). Using `shell: python` is the most portable
|
|
103
|
+
option, as Python is always available.
|
|
104
|
+
|
|
105
|
+
Like GitHub Actions, the script is written to a temporary file and executed as:
|
|
106
|
+
|
|
107
|
+
| Shell | Command | Behaviour |
|
|
108
|
+
|--------------|-----------------------------------------------------------------|------------------------------------------------------------------|
|
|
109
|
+
| `bash` | `bash --noprofile --norc -eo pipefail <file>` | Stops at the first failing command (also inside a pipe) |
|
|
110
|
+
| `sh` | `sh -e <file>` | Stops at the first failing command |
|
|
111
|
+
| `pwsh` | `pwsh -NoProfile -NonInteractive -Command ". '<file>'"` | Stops at the first error, fails if the last program failed |
|
|
112
|
+
| `powershell` | `powershell -NoProfile -NonInteractive -Command ". '<file>'"` | Same as `pwsh` (Windows PowerShell 5.1) |
|
|
113
|
+
| `cmd` | `cmd /D /E:ON /V:OFF /S /C "CALL "<file>""` | Doesn't stop on errors, the exit code of the last command counts |
|
|
114
|
+
| `python` | `python <file>` | The Python interpreter that runs prepare |
|
|
115
|
+
|
|
116
|
+
```yaml
|
|
117
|
+
- name: Create checksum
|
|
118
|
+
shell: python
|
|
119
|
+
working-directory: out/assignment
|
|
120
|
+
run: |
|
|
121
|
+
import hashlib
|
|
122
|
+
digest = hashlib.sha256(open("pom.xml", "rb").read()).hexdigest()
|
|
123
|
+
open("pom.xml.sha256", "w").write(f"{digest} pom.xml\n")
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Expressions
|
|
127
|
+
|
|
128
|
+
Values can contain expressions: `${{ <expression> }}`. The following contexts are available:
|
|
129
|
+
|
|
130
|
+
- `inputs.<name>`: the inputs of a composite task
|
|
131
|
+
- `env.<NAME>`: environment variables (an unset variable is empty)
|
|
132
|
+
- `tasks.<id>.outputs.<name>`: the outputs of a previous step
|
|
133
|
+
|
|
134
|
+
Referencing something that doesn't exist (e.g. a typo like `inputs.nmae`) fails the step, instead of silently
|
|
135
|
+
evaluating to an empty string. The operators `==`, `!=`, `<`, `>`, `&&`, `||` and `!` and the functions
|
|
136
|
+
`contains`, `startsWith` and `endsWith` are supported.
|
|
137
|
+
|
|
138
|
+
### Conditions
|
|
139
|
+
|
|
140
|
+
Just like GitHub Actions, a step is skipped when a previous step failed, unless its `if` uses one of the status
|
|
141
|
+
functions `success()`, `failure()` or `always()`. So `if: inputs.clean` behaves as `success() && inputs.clean`.
|
|
142
|
+
|
|
143
|
+
```yaml
|
|
144
|
+
- name: Clean up (also when something failed)
|
|
145
|
+
if: always()
|
|
146
|
+
uses: remove
|
|
147
|
+
with:
|
|
148
|
+
input: ["out"]
|
|
149
|
+
force: true
|
|
150
|
+
recursive: true
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Checking for updates
|
|
154
|
+
|
|
155
|
+
`prepare check` shows which of the tasks used in the `prepare.yml` have newer versions (use `--all` to check all
|
|
156
|
+
installed tasks). Tasks that use a moving version (`latest`, `main` or a prefix like `v1`) can be updated with
|
|
157
|
+
`prepare task update <task>`.
|
|
158
|
+
|
|
159
|
+
## Config file
|
|
160
|
+
|
|
161
|
+
It is possible to specify global options in a config file. The location of the config file can be found by running `prepare` without any commands.
|
|
162
|
+
|
|
163
|
+
The following settings are available:
|
|
164
|
+
|
|
165
|
+
```yml
|
|
166
|
+
core:
|
|
167
|
+
git-mode: "ssh|https"
|
|
168
|
+
verbose: int
|
|
169
|
+
debug: int
|
|
170
|
+
shell: "bash|sh|pwsh|powershell|cmd|python" # default shell for run steps (default: bash)
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## Tasks
|
|
174
|
+
|
|
175
|
+
There are three different kind of tasks available:
|
|
176
|
+
|
|
177
|
+
- Run tasks: these execute a shell command (see `shell` below)
|
|
178
|
+
- Python tasks: these execute a python script
|
|
179
|
+
- Composite tasks: these combine multiple tasks into one
|
|
180
|
+
|
|
181
|
+
### Custom tasks
|
|
182
|
+
|
|
183
|
+
It is possible to create custom (python/composite) tasks.
|
|
184
|
+
|
|
185
|
+
1. Create a repository
|
|
186
|
+
2. Define the properties of the task in `task.yml`, these include
|
|
187
|
+
- id*: unique identifier
|
|
188
|
+
- name*: name of the task
|
|
189
|
+
- description*: short description
|
|
190
|
+
- runs*: whether it is a python or composite task
|
|
191
|
+
- inputs: the inputs for the task
|
|
192
|
+
- outputs: the outputs that get set by the task. For composite tasks an output gets its value from an
|
|
193
|
+
expression: `value: ${{ tasks.<id>.outputs.<name> }}`
|
|
194
|
+
3. Validate that the task definition is correct against the [json schema](https://github.com/prepare-assignment/core/blob/main/prepare_assignment/schemas/task.schema.json)
|
|
195
|
+
4. If python task, create a script that implements desired functionality
|
|
196
|
+
|
|
197
|
+
## Releases
|
|
198
|
+
|
|
199
|
+
Releases are automated with [semantic-release](https://semantic-release.gitbook.io/). Pull requests are squash merged, so the PR title becomes the commit on `main` and must follow [Conventional Commits](https://www.conventionalcommits.org/) (checked on every PR):
|
|
200
|
+
|
|
201
|
+
| PR title | Release |
|
|
202
|
+
|----------|---------|
|
|
203
|
+
| `fix: ...` | patch (1.2.3 → 1.2.4) |
|
|
204
|
+
| `feat: ...` | minor (1.2.3 → 1.3.0) |
|
|
205
|
+
| `feat!: ...` or a `BREAKING CHANGE:` footer | major (1.2.3 → 2.0.0) |
|
|
206
|
+
| `docs:`, `chore:`, `ci:`, `build:`, `refactor:`, `test:`, `style:`, `perf:` | no release |
|
|
207
|
+
|
|
208
|
+
On every merge to `main` the next version is determined, tagged (`vX.Y.Z`), a GitHub release is created and the package is published to PyPI. The version is set during the build and is not committed, so the version in `pyproject.toml` is not the released version.
|