the browser-facing portion of osu!
1# Setting up your development environment 2 3There are a few different options to get started: 4 5## 1\. Manual setup for experienced developers (i.e. using an existing development environment): 6 7### Install prerequisites 8 9- MySQL 8.0+ 10- PHP 8.0+ (with curl, gd, intl, json, mbstring, mcrypt, mysql, xml and zip extensions) 11- nginx (or other webserver) 12- Node.js 16 13- elasticsearch 6+ 14- redis 15 16### Clone the git repository 17 18``` 19git clone https://github.com/ppy/osu-web.git 20``` 21 22### Configure .env file 23 24```bash 25# copy the example file and edit the settings, the important ones are APP_* and DB_* 26cp .env.example .env 27vi .env 28``` 29 30### URL rewriting 31 32```nginx 33# for nginx, with root set to the `public` folder of the repo 34location / { 35 try_files $uri $uri/ /index.php?$query_string; 36} 37``` 38 39Consult the [laravel documentation](https://laravel.com/docs/6.x/installation#web-server-configuration) for non-nginx 40 41### Initialize database 42 43```bash 44php artisan db:create 45``` 46 47### Install packages and build assets 48 49```bash 50# will also install composer and yarn 51./build.sh 52``` 53 54At this point you should be able to access the site via whatever webserver you configured. 55 56## 2\. Using Docker 57 58- First, install [Docker](https://www.docker.com/community-edition) and [Docker Compose](https://docs.docker.com/compose/install/) (on Windows, it's already part of Docker install). 59- Install [git](https://git-scm.com). 60- Obtain a [GitHub token](https://github.com/settings/tokens/new?scopes=public_repo&description=osu-web) as it's required for several parts of the website. 61- If using Windows, make sure it's running at least build 2004 and install Ubuntu (or another Linux distro of choice) from Windows Store. Additionally: 62 - Make sure it's running WSL2 (convert it if it's still using WSL1). 63 - Open Docker settings, go to Resources → WSL Integration → Enable integration with additional distros (enable for the installed distro). 64- Open terminal (or Linux console on Windows). 65- Clone this repository. 66- Set `GITHUB_TOKEN` environment variable (usually by `export GITHUB_TOKEN=ghs_...`). 67 - It'll be recorded to composer and app config so it doesn't need to be set again next time. 68- Run `bin/docker_dev.sh`. Make sure the repository folder is owned by the user executing this command (must be non-root). The site will be hosted at http://localhost:8080/. 69- Due to the nature of Docker (a container is killed when the command running in it finishes), the Yarn container will be run in watch mode. 70- Do note that the supplied Elasticsearch container uses a high (1+ GB) amount of RAM. Ensure that your system (or virtual machine, if running on Windows/macOS) has a necessary amount of memory allocated (at least 2 GB). If you can't (or don't want to), you can comment out the relevant elasticsearch lines in `docker-compose.yml`. 71- To run any of the below commands, make sure you are using the docker container: `docker compose run --rm php`. 72 - To run artisan commands, run using `docker compose run --rm php artisan`. 73 74--- 75**Notes** 76 77The `elasticsearch` and `db` containers store their data to volumes, the containers will use data on these volumes if they already exist. 78 79### Elasticsearch 80 81Existing Elasticsearch indices will be upgraded to new versions on start. Indices from a newer version cannot be used by older versions and downgrades are not supported. 82 83If you need to use a previous version of elasticsearch, e.g. to run `osu-elastic-indexer`, you can specify a previous version in a `docker-compose.override.yml` file (`volumes` and `environment` must be specified, as well, not just `image`): 84 85 services: 86 elasticsearch: 87 image: docker.elastic.co/elasticsearch/elasticsearch-oss:6.8.23 88 volumes: 89 - elasticsearch:/usr/share/elasticsearch/data 90 environment: 91 action.auto_create_index: "false" 92 discovery.type: single-node 93 ES_JAVA_OPTS: "-Xms512m -Xmx512m" 94 95Note that older versions of Elasticsearch do not work on ARM-based CPUs. 96 97`osu-elastic-indexer` currently cannot update indices using Elasticsearch 7; existing records can still be queried normally. 98 99### MySQL 100 101The MySQL images provided by Docker and MySQL have different uids for the `mysql` user, if you are getting permission errors when starting the `db` container like 102 103 mysqld: File './binlog.index' not found (OS errno 13 - Permission denied) 104 105update the ownership of the mysql data files: 106 107 docker compose run --rm db sh -c 'chown -R mysql:mysql /var/lib/mysql' 108 109 110### Windows 111 112On Windows, the files inside Linux system can be found in Explorer from `\\wsl$` location. 113 114Default user home directory can be found inside `home``<username>`. 115 116Due to difference in file permission and line endings, adjustments on git may be needed. Run these in the repository directory: 117 118``` 119git config core.eol lf 120git config core.filemode false 121``` 122 123### Docker hints 124 125#### Services 126 127There are multiple services involved: 128 129- php: main service for php server. Also serves as entry point for doing other stuff like testing etc 130- assets: builds assets. It sometimes behaves weirdly in which case try restarting it 131- job: runs queued job 132- schedule: runs scheduled job every 5 minutes 133- migrator: prepare database and elasticsearch (service should exit with status 0 after finishing its task) 134- beatmap-difficulty-lookup-cache: for computing beatmap difficulty attributes 135- notification-server: main service for notification websocket server 136- notification-server-dusk: notification server to be used by browser test 137- db: database server. Can be skipped by commenting it out and setting a different database instance 138- redis: cache and session server. Can be skipped just like db service 139- elasticsearch: search database. Can be skipped just like db service 140- nginx: proxies php and notification-server(-dusk) so they can be accessed under same host 141- score-indexer: `Solo\Score` indexer. 142- score-indexer-test: `Solo\Score` indexer used by tests. 143 144#### Modifying environment (`.env`, `.env.dusk.local`) files 145 146Sometimes a restart of notification-server and notification-server-dusk will be needed when changing those files. 147 148#### Example commands 149 150See if anything has stopped: 151 152``` 153docker compose ps 154``` 155 156Start docker in background: 157 158``` 159bin/docker_dev.sh -d 160``` 161 162Start single docker service: 163 164``` 165docker compose start <servicename> 166``` 167 168Restart single docker service: 169 170``` 171docker compose restart <servicename> 172``` 173 174#### Direct database access 175 176Using own mysql client, connect to port 3306 or `MYSQL_EXTERNAL_PORT` if set when starting up docker. 177 178Alternatively, there's mysql client installed in php service: 179 180``` 181docker compose run --rm php mysql 182``` 183 184#### Updating image 185 186Docker images need to be occasionally updated to make sure they're running latest version of the packages. 187 188``` 189docker compose pull 190docker compose build --no-cache 191``` 192 193#### Faster php commands 194 195When frequently running commands, doing `docker compose run` may feel a little bit slow. An alternative is by running the command in existing instance instead. For example to run `artisan tinker`: 196 197``` 198docker compose exec php /app/docker/development/entrypoint.sh artisan tinker 199``` 200 201Add an alias for the docker compose command so it doesn't need to be specified every time: 202 203``` 204alias p='docker compose exec php /app/docker/development/entrypoint.sh' 205p artisan tinker 206``` 207 208(add the `alias` line to shell startup file; usually `~/.profile`, `~/.zshrc`, etc) 209 210# Development 211 212## Reset the database + seeding sample data 213 214``` 215php artisan migrate:fresh --seed 216``` 217 218Run the above command to rebuild the database and populate it with sample data. In order for the seeder to seed beatmaps, you must enter a valid osu! API key as the value of the `OSU_API_KEY` property in the `.env` configuration file, as the seeder obtains beatmap data from the osu! API. The key can be obtained from [the "Legacy API" section of your account settings page](https://osu.ppy.sh/home/account/edit#legacy-api). 219 220## Creating your initial user 221 222In the repository directory: 223 224```php 225php artisan tinker 226>>> (new App\Libraries\UserRegistration(["username" => "yourusername", "user_email" => "your@email.com", "password" => "yourpassword"]))->save(); 227``` 228 229Note that seeding sample data (the step above this) is required for user registration to work, otherwise the command above will fail due to missing user groups or otherwise. 230 231## Generating assets 232 233```bash 234# build assets (should be done automatically if using docker) 235yarn run development 236``` 237 238Note that if you use the bundled docker compose setup, yarn/webpack will be already run in watch mode. 239 240## Continuous asset generation while developing 241 242To continuously generate assets as you make changes to files (less, coffeescript) you can run `webpack` in `watch` mode. 243 244``` 245yarn run watch 246``` 247 248## Email 249 250You can watch emails being sent from `osu-web` by watching the `storage/logs/laravel.log` file. Make sure the `MAIL_DRIVER` is set to `log`. 251 252## Use the API from osu! 253 254To connect from osu!(lazer) via the API offered by osu-web, you need to create a special OAuth password client with: 255``` 256php artisan passport:client --password 257``` 258You can then change the constants in the osu! repository (`./osu.Game/Online/API/APIAccess.cs`). 259 260# Testing 261 262To run test, first copy `.env.testing.example` to `.env.testing` and `.env.dusk.local.example` to `.env.dusk.local`. 263Make sure to set `ES_INDEX_PREFIX` and all the databases to something other than production. 264 265Once the env files are set, database for testing will need to be setup: 266 267## Initializing the test database 268 269Tests should be run against an empty database, to initialize an empty database: 270 271``` 272APP_ENV=testing php artisan migrate:fresh --no-interaction 273``` 274 275or if using docker: 276 277``` 278docker compose run --rm -e APP_ENV=testing php artisan migrate:fresh --no-interaction 279``` 280 281--- 282**IMPORTANT** 283 284If there are existing matching databases, they will be dropped! 285 286--- 287 288## PHP tests 289 290PHP tests use PHPUnit, to run: 291 292``` 293bin/phpunit.sh 294``` 295 296or if using Docker: 297 298``` 299docker compose run --rm php test phpunit 300``` 301 302Regular PHPUnit arguments are accepted, e.g.: 303 304``` 305bin/phpunit.sh --filter=Route --stop-on-failure 306``` 307 308## Test groups 309 310Some tests are marked with a `@group` they require a specific service to be available. 311These groups can be used to exclude tests: 312 313 bin/phpunit.sh --exclude=RequiresScoreIndexer,RequiresBeatmapDifficultyLookupCache 314 315or run only those tests: 316 317 bin/phpunit.sh --group=RequiresScoreIndexer 318 319- `RequiresBeatmapDifficultyLookupCache`: Requires `beatmap-difficulty-lookup-cache` to be running 320- `RequiresScoreIndexer`: Requires a score indexing schema to be set and `score-indexer-test` service to be running 321 322Most tests require `elasticsearch` and `redis` to be available, so these are not optional. 323 324## Browser tests 325 326Browser tests are run using Laravel Dusk: 327 328``` 329bin/run_dusk.sh 330``` 331 332or if using Docker: 333 334``` 335docker compose run --rm php test browser 336``` 337 338--- 339**Known Issues** 340 341The Dusk tests currently do not clean up completely, leaving behind test data in the database; the database should be reintialized after running a Dusk test. 342 343--- 344 345## Javascript tests 346 347Javascript tests are run with Karma. 348 349Karma is currently configured to use Headless Chrome by default; this will require Chrome or a standalone Headless Chrome to be already installed. If you are using Docker, Headless Chrome will already be installed in the container. 350 351``` 352yarn karma start --single-run 353``` 354 355or if using Docker: 356 357``` 358docker compose run --rm testjs 359``` 360 361# Documentation 362 363```bash 364php artisan scribe:generate 365``` 366 367Documentation will be generated in the `docs` folder in both html and markdown formats.