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.