Setting up a development environment

Some steps described here overlap the ones described in the installation instructions.

Using Docker

Inside the docker folder you can find all the Dockerfile and docker-compose files for several enviroments. To run the development setup, copy the .env.example to .env and update it to the values of your environment.

In the root .env, use these values

DB_HOST=db
...
API_BASE_URL="http://phpreport-api:8555"

In the frontend/.env, use the following:

VITE_OIDC_REDIRECT_URL='http://0.0.0.0:5173/web/v2/'
VITE_API_BASE='http://0.0.0.0:8555'

You need docker and docker-compose running and you can run it from the root folder of the project with:

docker-compose -f docker/docker-compose.dev.yml up

During the first time running the app, the API will fail because it needs to access the database tables that still don't exist, so run the migrations to create the tables with:

docker exec -ti phpreport-api alembic upgrade head

Kill the containers and run them again, so the API can connect to the database correctly.

[Optional] When running the project for the first time, you can add some basic data for the development environment:

docker exec -dti phpreport-db psql phpreport -U phpreport < sql/initialData.sql

If you make changes to the models and want to create migrations:

docker exec -ti phpreport-api alembic revision --autogenerate -m "Migrations description"

All the services are setup to reload when the files are updated without the need of rebuild the containers.

If you are using an external OAuth provider, you will also need to add a user to the database with the same username as your OAuth user because PhpReport will match on the username. To do this, you will want to run the following commands once your db container is up and running:

docker exec -ti phpreport-db bash
psql -U phpreport
INSERT INTO usr (id, password, login) VALUES (DEFAULT, md5('myusername'), 'myusername') RETURNING id;

This will echo the id of the user you just created. Keep this terminal open. Now you will need to also add some permissions to your user. To do this you'll need to insert the user id into the belongs table along with the proper group id. The default group ids added are as follows:

idname
1staff
2admin
3manager

If you want your user to have the highest permission level, then run the following and replace {your user id} with the value returned when you inserted your user: INSERT into belongs VALUES(1, {your user id}), (2, {your user id}), (3, {your user id});

If you want your user to have lower permissions, then remove whichever groups from your INSERT statement you don't want your user in.

If you've given your user the highest permissions, then you'll be able to use the interface to create clients and projects to use for creating tasks.

Dependencies

Follow the corresponding section from the installation instructions. Make sure to also install composer as specified there.

Additionally, a development environment may need the following dependencies to generate minified versions of the JS code and the documentation pages:

  • Fedora: package uglify-js.
  • Debian/Ubuntu: package uglifyjs.

NOTICE: UglifyJS version must be 3.15 or above.

For the React frontend, you will need to run npm install inside the frontend folder. Make sure that you have Node.js version 20 or higher.

For the Python API, make sure you have Python version 3.11 or higher.

Setting up the database

From the api folder, run the migrations with

alembic upgrade head

Create a new migration with

alembic revision --autogenerate -m "Migrations description"

For more details check the alembic documentation.

History tracking in database

As part of the migrations, an archive table is added to the database along with a function to log to this table and a trigger to captures changes on the project table. A trigger using this function can be added to track the history of any table. To do so, create a migration with the following (with the customer table used as an example):

    customer_trigger = PGTrigger(
        schema="public",
        signature="trg_make_archive_of_changes_for_customers",
        on_entity="public.customer",
        definition="""
        after insert or delete or update on
            public.customer for each row execute function make_archive_of_changes('Customer')
        """
    )
    op.create_entity(customer_trigger)

Setting up the files

Clone the PhpReport repository https://github.com/Igalia/phpreport in a location available to the web server. The usual default location for the Apache web server is: /var/www/html/

Alternatively, clone it elsewhere and create a link from the web server directory.

You must also run composer dump-autoload -o inside PhpReport root directory, so it can generate the autoload files. Then, run composer install to install the project dependencies.

Creating the schema and initial data of the database

The configuration file with the default values already exists in the repository, so you don't have to touch it unless you changed any data in the first step.

Then, you can follow the step three in the installation instructions (either the manual or the wizard setup) to create the schema and initial data.

Setup autogenerated files

You can optionally minify the JS source with make minify. You should be able to debug it because there are source map files in place, but take into account you would have to re-generate them with make minify every time you modify a .js file. In a development environment, it's probably better not to minify the sources.

Create necessary .env files in your project

Using the .env.example as a template, create an .env at the root and one inside frontend and set the values to fit your environment.

Running the API

Before you try the application, you'll want to get the API server running. To do so, follow the instructions in the api documentation section

Running the frontend (React)

If you only want to want the React portion of the frontend and not the PHP portion, you can run npm run dev in the frontend folder. This will spin up a server at `http://localhost:5173/web/v2'

If you want to run everything together (exisiting PHP app, new API, and new frontend), it is easiest to run npm run build in the frontend folder. This will compile your JS to the web/v2 folder.

Try the application

Use a browser to open the correct URL of your web server (very likely, http://localhost/phpreport), then use the user name admin and the password admin to try a user with full privileges, or user with password user to try a login with restricted permissions. You will also be able to create users with any permission level once you are logged in as admin.

Running automated tests

There 2 types of tests in the project: unit and integration tests.

The unit tests will work locally without issues, but the integration tests will only work if there is a service running on the port 8000 with the data from the [sql/initialData.sql]{.title-ref} file. In that case it's easier to run it with docker, as it has everything setup.

In one terminal build and run the application and the database:

docker-compose -f docker/docker-compose.test.yml up --build --renew-anon-volumes

In a second terminal run the test container to run the tests:

docker-compose -f docker/docker-compose.test.yml run -T test

If you don't want to setup docker, it's possible to run only the unit tests. Make sure you have composer and the projects dependencies installed. To install the dependencies run composer install in the project root directory.

All the automated tests should be placed inside the tests directory. From the project root, run ./vendor/bin/phpunit --testdox tests/unit to execute the automated tests.

Documentation

The application documentation is published using mdBook. To preview the output of mdBook locally, ensure you have mdBook installed, then run mdbook serve at the root of the project.

API documentation is autogenerated using the OpenAPI standard. When running locally, you can view those docs at http://localhost:8555/docs. The FastAPI framework also provides docs at http://localhost:8555/redoc if you prefer ReDoc to Swagger.

Linting and Formatting

The API uses Flake8 for linting and Black for formatting.

The frontend uses ESLint and Prettier.