# Contributing to podman-compose

## Who can contribute?

- Users that found a bug,
- Users that want to propose new functionalities or enhancements,
- Users that want to help other users to troubleshoot their environments,
- Developers that want to fix bugs,
- Developers that want to implement new functionalities or enhancements.

## Development environment setup

Note: Some steps are OPTIONAL but all are RECOMMENDED.

1. Fork the project repository and clone it:

   ```shell
   $ git clone https://github.com/USERNAME/podman-compose.git
   $ cd podman-compose
   ```

2. (OPTIONAL) Create a Python virtual environment. Example using
   [virtualenv wrapper](https://virtualenvwrapper.readthedocs.io/en/latest/):

    ```shell
    $ mkvirtualenv podman-compose
    ```

3. Install the project runtime and development requirements:

   ```shell
   $ pip install '.[devel]'
   ```

4. (OPTIONAL) Install `pre-commit` git hook scripts
   (https://pre-commit.com/#3-install-the-git-hook-scripts):

   ```shell
   $ pre-commit install
   ```

5. Create a new branch, develop and add tests when possible.
6. Run linting and testing before committing code. Ensure all the hooks are passing.

   ```shell
   $ pre-commit run --all-files
   ```

7. Run code coverage:

    ```shell
    $ coverage run --source podman_compose -m unittest discover tests/unit
    $ python3 -m unittest discover tests/integration
    $ coverage combine
    $ coverage report
    $ coverage html
    ```

8. Commit your code to your fork's branch.
   - Make sure you include a `Signed-off-by` message in your commits.
     Read [this guide](https://github.com/containers/common/blob/main/CONTRIBUTING.md#sign-your-prs)
     to learn how to sign your commits.
   - In the commit message, reference the Issue ID that your code fixes and a brief description of
     the changes.
     Example: `Fixes #516: Allow empty network`
9. Open a pull request to `containers/podman-compose` and wait for a maintainer to review your work.

## Adding new commands

To add a command, you need to add a function that is decorated with `@cmd_run`.

The decorated function must be declared `async` and should accept two arguments: The compose
instance and the command-specific arguments (resulted from the Python's `argparse` package).

In this function, you can run Podman (e.g. `await compose.podman.run(['inspect', 'something'])`),
access `compose.pods`, `compose.containers` etc.

Here is an example:

```python
@cmd_run(podman_compose, 'build', 'build images defined in the stack')
async def compose_build(compose, args):
    await compose.podman.run(['build', 'something'])
```

## Command arguments parsing

To add arguments to be parsed by a command, you need to add a function that is decorated with
`@cmd_parse` which accepts the compose instance and the command's name (as a string list or as a
single string).

The decorated function should accept a single argument: An instance of `argparse`.

In this function, you can call `parser.add_argument()` to add a new argument to the command.

Note you can add such a function multiple times.

Here is an example:

```python
@cmd_parse(podman_compose, 'build')
def compose_build_parse(parser):
    parser.add_argument("--pull",
        help="attempt to pull a newer version of the image", action='store_true')
    parser.add_argument("--pull-always",
        help="Attempt to pull a newer version of the image, "
             "raise an error even if the image is present locally.",
        action='store_true')
```

NOTE: `@cmd_parse` should be after `@cmd_run`.

## Calling a command from another one

If you need to call `podman-compose down` from `podman-compose up`, do something like:

```python
@cmd_run(podman_compose, 'up', 'up desc')
async def compose_up(compose, args):
    await compose.commands['down'](compose, args)
    # or
    await compose.commands['down'](argparse.Namespace(foo=123))
```

## Missing Commands (help needed)

```
  bundle             Generate a Docker bundle from the Compose file
  create             Create services
  events             Receive real time events from containers
  images             List images
  rm                 Remove stopped containers
  scale              Set number of containers for a service
  top                Display the running processes
```
