Skip to content
Merged
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
240 changes: 2 additions & 238 deletions .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,241 +1,5 @@
[![CI](https://github.com/git-mastery/exercises/actions/workflows/ci.yml/badge.svg)](https://github.com/git-mastery/exercises/actions/workflows/ci.yml)

# Contributing an exercise
# Contributing to Exercises

## Before contributing

If you are proposing a new exercise (i.e., not implementing an [already approved exercise proposal](https://github.com/git-mastery/exercises/issues?q=is%3Aissue%20state%3Aopen%20label%3A%22exercise%20discussion%22%20label%3A%22help%20wanted%22)) make sure that you have done the following:
- [ ] Create an [exercise discussion](https://github.com/git-mastery/exercises/issues/new?template=exercise_discussion.yaml)
- [ ] Obtained approval on the exercise
- [ ] File a [remote repository request](https://github.com/git-mastery/exercises/issues/new?template=request_exercise_repository.yaml)

## Prerequisites

- Bash environment
- Python 3.13
- Github CLI [installed and authenticated](https://github.com/cli/cli#installation) for testing the download script

## Setup

1. Fork this repository
2. Clone the fork

```bash
git clone https://github.com/<username>/exercises
```

3. Setup a virtual environment

```bash
python -m venv venv
```

4. Activate the virtual environment

```bash
source venv/bin/activate
```

If you are using Windows, you should run the following instead:

```bash
source venv/Scripts/activate
```

5. Install all dependencies

```bash
pip install -r requirements.txt
```

## Create a new exercise

Use the provided `new.sh` script to generate the scaffolding for a new exercise:

```bash
./new.sh
```

This script will prompt you for:

1. The name of the exercise -- likely to be specified in the corresponding exercise discussion
2. The exercise tags (split by space) -- likely to be specified in the corresponding exercise discussion
3. The exercise configuration (read the [`.gitmastery-exercise.json` configuration](#gitmastery-exercisejson-configuration) section for more info on this)

> [!TIP]
> You should use kebab case for the exercise name.

It then generates the following directory structure:

```text
<exercise name>
├── .gitmastery-exercise.json
├── README.md
├── __init__.py
├── download.py
├── res
│ └── ...
├── tests
│ ├── specs
│ │ └── base.yml
│ └── test_verify.py
└── verify.py
```

- `.gitmastery-exercise.json`: contains the exercise configuration
- `README.md`: contains the instructions for the exercise for the students to attempt
- `download.py`: contains the download instructions to setup the student's exercise
- `verify.py`: contains the verification script for the exercise attempt
- `res/`: contains resources that are available to students (see this section about [types of resources](#types-of-resources))
- `tests/specs/`: contains specification files written using [`repo-smith`](https://github.com/git-mastery/git-autograder)
- `tests/test_verify.py`: contains unit tests for verification script

### `.gitmastery-exercise.json` configuration

The `.gitmastery-exercise.json` is used to tell the [Git-Mastery app](https://git-mastery.github.io/app) how to setup the student's exercise.

The `new.sh` script should have already generated one for you, but you may change your mind with the configuration and modify the file directly:

- `exercise_name`: raw exercise name that will be indexed; recommended to use [kebab case](https://developer.mozilla.org/en-US/docs/Glossary/Kebab_case)
- `tags`: used during indexing on the [exercise directory](https://git-mastery.github.io/exercises)
- `requires_git`: performs a check to ensure that Git is installed and the user has already configured their `user.name` and `user.email`
- `requires_github`: performs a check to ensure that Github CLI is installed and the user has already authenticated themselves
- `base_files`: specifies the files from `res/` to be downloaded into the exercise root; typically used for the `answers.txt` (more about grading types [here]())
- `exercise_repo`: controls the sub-folder that is generated; this is where students work on the exercise
- `repo_type`: `local` or `remote`; if `remote`, then the sub-folder is generated from a remote repository
- `repo_name`: name of the sub-folder; required for both `repo_type`
- `init`: determines if `git init` is run for the sub-folder; required only for `local`
- `create_fork`: determines if a fork is created on the user's Github account; required only for `remote`
- `repo_title`: name of the remote repository to fork + clone; required only for `remote`

## Designing download process

The `download.py` contains the instructions to setup the local repository.

This is the sequence in which the Git-Mastery app downloads an exercise for a student:

```mermaid
flowchart
a[Download exercise] --> b[Create exercise folder]
b --> c[Download base files to exercise root]
c --> d[Check Git if toggled]
d --> e[Check Github if toggled]
e -- local --> f[Create local repo folder with repo_name]
e -- remote --> g[Fork repository if toggled]
g --> h[Clone repository with repo_name]
f --> i[Download resources]
h --> i
i --> j[Create initial commit if init toggled]
j --> k[Execute download function]
```

As a result, the `download` function is the last step after you have already setup the folder structures and downloaded the base files and resources.

The default download script comes with a helper function to `run_command` to run local commands.

> [!NOTE]
> You should be using OS-agnostic commands in the download script

The initial download script also includes a command to attach a tag as the "start tag". This is only useful if you want to iterate through the user's commits in your verification script. Otherwise, this can be removed.

Refer to existing `download.py` for reference on how to setup the download script.

### What students see

When a student downloads an exercise, they will see the following folder structure:

```text
<exercise name>
├── .gitmastery-exercise.json
├── README.md
└── <sub folder name>
├── .git
└── ...
```

The root of the exercise will contain the `README.md` and `.gitmastery-exercise.json` configured from your template.

It also contains the sub-folder configured in `.gitmastery-exercise.json`, which is where students will attempt the exercise.

### Types of resources

There are two distinct types of resources:

1. Base files: configured through the `base_files` property in `.gitmastery-exercise.json` in your template; files located in `res/` are downloaded to the root of the exercise folder

```text
<exercise name>
├── .gitmastery-exercise.json
├── README.md
├── <base files> <-- here
└── <sub folder name>
├── .git
└── ...
```

2. Resources: configured through the `__resources__` field in `download.py`; supporting files for the exercise with files located in `res/` downloaded into the sub folder

```text
<exercise name>
├── .gitmastery-exercise.json
├── README.md
├── <base files>
└── <sub folder name>
├── .git
└── <resources> <-- here
```

### Testing downloads

To test that your download script works, we have provided a script to simulate the download process in this repository for you to verify.

```bash
./test-download.sh <your exercise folder>
```

You can find the downloaded repository under the `test-downloads/` folder.

> [!NOTE]
> If you wish to support a remote repository and require the Git-Mastery team to create a new repository, create an issue and we will assess the request accordingly


## Designing verification process

The verification process is controlled by the `verify.py`:

```mermaid
flowchart
a[Verify exercise] --> b["Check if in exercise (using .gitmastery-exercise.json)"]
b -- not in exercise --> c[Cancel]
b -- in exercise --> d[Execute verification script on exercise folder]
```

The [`git-autograder`](https://github.com/git-mastery/git-autograder) is built as a wrapper around [`GitPython`](https://github.com/gitpython-developers/GitPython). As a result, if you are writing any verification scripts and there is no available helper function with `git-autograder`, you can fall back to the underlying `Repo` object:

```python
def verify(exercise: GitAutograderExercise) -> GitAutograderOutput:
# Access the underlying GitPython repo:
exercise.repo.repo

return exercise.to_output([], GitAutograderStatus.SUCCESSFUL)
```

Refer to existing `verify.py` scripts to understand what are the available helper functions to streamline the grading. Open an issue if there is something that is not yet supported or if you have a question.

### Testing verification

To test the verification, we rely on [`repo-smith`](https://github.com/git-mastery/repo-smith) to simulate exercise states and write unit tests to verify the verification script's behavior. You don't need to simulate the entire flow, just the end states that you require for your verification script.

Refer to existing `test_verify.py` to see examples of unit testing the verification script.

You can run the unit tests of your exercise via:

```bash
./test.sh <your exercise folder>
```

## Submitting the exercise for review

Create a pull request from your fork using the provided pull request template.

Fill in all of the details necessary.
Refer to [developer documentation](https://git-mastery.org/developers/) for instructions on how to set up your development environment and contribute to exercises.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# exercises

For more details, refer to the official developer documentation: https://git-mastery.github.io/developers
For more details, refer to the official developer documentation: https://git-mastery.org/developers/
2 changes: 1 addition & 1 deletion branch_bender/README.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
See https://git-mastery.github.io/lessons/merge/exercise-branch-bender.html
See https://git-mastery.org/lessons/merge/exercise-branch-bender.html
2 changes: 1 addition & 1 deletion branch_compare/README.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
See https://git-mastery.github.io/lessons/branch/exercise-branch-compare.html
See https://git-mastery.org/lessons/branch/exercise-branch-compare.html
2 changes: 1 addition & 1 deletion branch_delete/README.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
See https://git-mastery.github.io/lessons/branchDelete/exercise-branch-delete.html
See https://git-mastery.org/lessons/branchDelete/exercise-branch-delete.html
2 changes: 1 addition & 1 deletion branch_forward/README.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
See https://git-mastery.github.io/lessons/merge/exercise-branch-forward.html
See https://git-mastery.org/lessons/merge/exercise-branch-forward.html
2 changes: 1 addition & 1 deletion branch_previous/README.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
See https://git-mastery.github.io/lessons/branch/exercise-branch-previous.html
See https://git-mastery.org/lessons/branch/exercise-branch-previous.html
2 changes: 1 addition & 1 deletion branch_rename/README.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
See https://git-mastery.github.io/lessons/branchRename/exercise-branch-rename.html
See https://git-mastery.org/lessons/branchRename/exercise-branch-rename.html
2 changes: 1 addition & 1 deletion clone_repo/README.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
See https://git-mastery.github.io/lessons/clone/exercise-clone-repo.html
See https://git-mastery.org/lessons/clone/exercise-clone-repo.html
2 changes: 1 addition & 1 deletion conflict_mediator/README.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
See https://git-mastery.github.io/lessons/mergeConflicts/exercise-conflict-mediator.html
See https://git-mastery.org/lessons/mergeConflicts/exercise-conflict-mediator.html
2 changes: 1 addition & 1 deletion fetch_and_pull/README.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
See https://git-mastery.github.io/lessons/pull/exercise-fetch-and-pull.html
See https://git-mastery.org/lessons/pull/exercise-fetch-and-pull.html
2 changes: 1 addition & 1 deletion ff_undo/README.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
See https://git-mastery.github.io/lessons/merge/exercise-ff-undo.html
See https://git-mastery.org/lessons/merge/exercise-ff-undo.html
2 changes: 1 addition & 1 deletion fork_repo/README.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
See https://git-mastery.github.io/lessons/fork/exercise-fork-repo.html
See https://git-mastery.org/lessons/fork/exercise-fork-repo.html
2 changes: 1 addition & 1 deletion glossary_branch_pull/README.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
See https://git-mastery.github.io/lessons/remoteBranchPull/exercise-glossary-branch-pull.html
See https://git-mastery.org/lessons/remoteBranchPull/exercise-glossary-branch-pull.html
2 changes: 1 addition & 1 deletion grocery_shopping/README.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
See https://git-mastery.github.io/lessons/commit/exercise-grocery-shopping.html
See https://git-mastery.org/lessons/commit/exercise-grocery-shopping.html
2 changes: 1 addition & 1 deletion ignoring_somethings/README.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
See https://git-mastery.github.io/lessons/ignore/exercise-ignoring-something.html
See https://git-mastery.org/lessons/ignore/exercise-ignoring-something.html
2 changes: 1 addition & 1 deletion link_me/README.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
See https://git-mastery.github.io/lessons/setRemote/exercise-link-me.html
See https://git-mastery.org/lessons/setRemote/exercise-link-me.html
2 changes: 1 addition & 1 deletion log_and_order/README.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
See https://git-mastery.github.io/lessons/log/exercise-log-and-order.html
See https://git-mastery.org/lessons/log/exercise-log-and-order.html
2 changes: 1 addition & 1 deletion merge_squash/README.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
See https://git-mastery.github.io/lessons/merge/exercise-merge-squash.html
See https://git-mastery.org/lessons/merge/exercise-merge-squash.html
2 changes: 1 addition & 1 deletion merge_undo/README.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
See https://git-mastery.github.io/lessons/merge/exercise-merge-undo.html
See https://git-mastery.org/lessons/merge/exercise-merge-undo.html
2 changes: 1 addition & 1 deletion mix_messy_docs/README.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
See https://git-mastery.github.io/lessons/branchDelete/exercise-mix-messy-docs.html
See https://git-mastery.org/lessons/branchDelete/exercise-mix-messy-docs.html
2 changes: 1 addition & 1 deletion mix_messy_graph/README.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
See https://git-mastery.github.io/lessons/branchDelete/exercise-mix-messy-graph.html
See https://git-mastery.orgns/branchDelete/exercise-mix-messy-graph.html
2 changes: 1 addition & 1 deletion push_over/README.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
See https://git-mastery.github.io/lessons/push/exercise-push-over.html
See https://git-mastery.org/lessons/push/exercise-push-over.html
2 changes: 1 addition & 1 deletion remote_branch_rename/README.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
See https://git-mastery.github.io/lessons/remoteBranchRename/exercise-remote-branch-rename.html
See https://git-mastery.org/lessons/remoteBranchRename/exercise-remote-branch-rename.html
2 changes: 1 addition & 1 deletion remote_control/README.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
See https://git-mastery.github.io/lessons/createRemoteRepo/exercise-remote-control.html
See https://git-mastery.org/lessons/createRemoteRepo/exercise-remote-control.html
2 changes: 1 addition & 1 deletion scripts/create-exercise-directory.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def generate_markdown(tag_map):
lines.append("|----------|------------------|")
for name, command in tag_map[tag]:
lines.append(
f"| [{name}](https://git-mastery.github.io/exercises/{name.replace('-', '_')}) | `{command}` |"
f"| [{name}](https://git-mastery.org/exercises/{name.replace('-', '_')}) | `{command}` |"
)
lines.append("") # blank line between sections
return "\n".join(lines)
Expand Down
2 changes: 1 addition & 1 deletion scripts/new-exercise.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ def create_exercise_config_file(config: ExerciseConfig) -> None:
def create_readme_file(config: ExerciseConfig) -> None:
with open("README.md", "w") as readme_file:
readme = f"""
See https://git-mastery.github.io/lessons/{{LESSON_ID}}/exercise-{config.exercise_name}.html
See https://git-mastery.org/lessons/{{LESSON_ID}}/exercise-{config.exercise_name}.html
"""
readme_file.write(textwrap.dedent(readme).lstrip())

Expand Down
2 changes: 1 addition & 1 deletion scripts/post-contribution-message.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@

### Prerequisites

Ensure that you have the `gitmastery` app installed locally ([instructions](https://git-mastery.github.io/companion-app/index.html))
Ensure that you have the `gitmastery` app installed locally ([instructions](https://git-mastery.org/companion-app/index.html))

### Testing steps

Expand Down
2 changes: 1 addition & 1 deletion sensors_checkout/README.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
See https://git-mastery.github.io/lessons/checkout/exercise-sensors-checkout.html
See https://git-mastery.org/lessons/checkout/exercise-sensors-checkout.html
2 changes: 1 addition & 1 deletion sensors_diff/README.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
See https://git-mastery.github.io/lessons/diff/exercise-sensors-diff.html
See https://git-mastery.org/lessons/diff/exercise-sensors-diff.html
2 changes: 1 addition & 1 deletion sensors_reset/README.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
See https://git-mastery.github.io/lessons/reset/exercise-sensors-reset.html
See https://git-mastery.org/lessons/reset/exercise-sensors-reset.html
2 changes: 1 addition & 1 deletion sensors_revert/README.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
See https://git-mastery.github.io/lessons/revert/exercise-sensors-revert.html
See https://git-mastery.org/lessons/revert/exercise-sensors-revert.html
2 changes: 1 addition & 1 deletion side_track/README.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
See https://git-mastery.github.io/lessons/branch/exercise-side-track.html
See https://git-mastery.org/lessons/branch/exercise-side-track.html
2 changes: 1 addition & 1 deletion stage_fright/README.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
See https://git-mastery.github.io/lessons/stage/exercise-stage-fright.html
See https://git-mastery.org/lessons/stage/exercise-stage-fright.html
2 changes: 1 addition & 1 deletion staging_intervention/README.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
See https://git-mastery.github.io/lessons/stage/exercise-staging-intervention.html
See https://git-mastery.org/lessons/stage/exercise-staging-intervention.html
2 changes: 1 addition & 1 deletion tags_add/README.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
See https://git-mastery.github.io/lessons/tag/exercise-tags-add.html
See https://git-mastery.org/lessons/tag/exercise-tags-add.html
2 changes: 1 addition & 1 deletion tags_push/README.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
See https://git-mastery.github.io/lessons/tag/exercise-tags-push.html
See https://git-mastery.org/lessons/tag/exercise-tags-push.html
2 changes: 1 addition & 1 deletion tags_update/README.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
See https://git-mastery.github.io/lessons/tag/exercise-tags-update.html
See https://git-mastery.org/lessons/tag/exercise-tags-update.html
2 changes: 1 addition & 1 deletion under_control/README.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
See https://git-mastery.github.io/lessons/init/exercise-under-control.html
See https://git-mastery.org/lessons/init/exercise-under-control.html
2 changes: 1 addition & 1 deletion undo_init/README.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
See https://git-mastery.github.io/lessons/init/exercise-undo-init.html
See https://git-mastery.org/lessons/init/exercise-undo-init.html
2 changes: 1 addition & 1 deletion view_commits/README.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
See https://git-mastery.github.io/lessons/show/exercise-view-commits.html
See https://git-mastery.org/lessons/show/exercise-view-commits.html
Loading