From: Anton Khorev Date: Wed, 18 Dec 2024 13:35:01 +0000 (+0300) Subject: Merge branch 'pull/4985' X-Git-Tag: live~12 X-Git-Url: https://git.openstreetmap.org./rails.git/commitdiff_plain/7e7ede890e8e948236d3dbc48e24aca00cd01f62?hp=95e1aff23493b3725d5259bcca7bcc79d7d3bc26 Merge branch 'pull/4985' --- diff --git a/.erb-lint.yml b/.erb_lint.yml similarity index 93% rename from .erb-lint.yml rename to .erb_lint.yml index 0c729d38f..dc9b39c5c 100644 --- a/.erb-lint.yml +++ b/.erb_lint.yml @@ -20,8 +20,6 @@ linters: Enabled: false Naming/FileName: Enabled: false - Rails/OutputSafety: - Enabled: false Style/FrozenStringLiteralComment: Enabled: false SelfClosingTag: diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 000000000..b5f38b76b --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,13 @@ + + +### Description + + +### How has this been tested? + diff --git a/.github/workflows/danger.yml b/.github/workflows/danger.yml new file mode 100644 index 000000000..6da5e7164 --- /dev/null +++ b/.github/workflows/danger.yml @@ -0,0 +1,35 @@ +name: Danger + +on: + pull_request_target: + types: [opened, synchronize] + +permissions: + pull-requests: write + statuses: write + +jobs: + danger: + runs-on: ubuntu-22.04 + steps: + - name: Check out code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Setup ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: 3.1 + rubygems: 3.4.10 + bundler-cache: true + - name: Create base branch + run: | + git fetch ${{ github.event.pull_request.base.repo.clone_url }} ${{ github.event.pull_request.base.sha }}:danger_base + - name: Create head branch + run: | + git fetch ${{ github.event.pull_request.head.repo.clone_url }} ${{ github.event.pull_request.head.sha }}:danger_head + - name: Danger + env: + DANGER_GITHUB_BEARER_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + bundle exec danger --verbose diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 9fc132014..06f6ff841 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -7,7 +7,7 @@ concurrency: cancel-in-progress: true env: os: ubuntu-22.04 - ruby: '3.0' + ruby: '3.1' jobs: rubocop: name: RuboCop @@ -36,7 +36,7 @@ jobs: rubygems: 3.4.10 bundler-cache: true - name: Run erblint - run: bundle exec erblint . + run: bundle exec erb_lint . eslint: name: ESLint runs-on: ubuntu-22.04 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 46ab75482..25722c1f4 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -10,8 +10,8 @@ jobs: name: Ubuntu ${{ matrix.ubuntu }}, Ruby ${{ matrix.ruby }} strategy: matrix: - ubuntu: [20.04, 22.04] - ruby: ['3.0', '3.1', '3.2', '3.3'] + ubuntu: [22.04, 24.04] + ruby: ['3.1', '3.2', '3.3'] runs-on: ubuntu-${{ matrix.ubuntu }} env: RAILS_ENV: test @@ -58,10 +58,14 @@ jobs: run: bundle exec bin/yarn install - name: Compile assets run: bundle exec rails assets:precompile + - name: Create tmp/pids directory + run: mkdir -p tmp/pids - name: Run tests run: bundle exec rails test:all + - name: Run javascript tests + run: bundle exec teaspoon - name: Report completion to Coveralls - uses: coverallsapp/github-action@v2.3.0 + uses: coverallsapp/github-action@v2.3.4 with: github-token: ${{ secrets.github_token }} flag-name: ubuntu-${{ matrix.ubuntu }}-ruby-${{ matrix.ruby }} @@ -73,7 +77,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Report completion to Coveralls - uses: coverallsapp/github-action@v2.3.0 + uses: coverallsapp/github-action@v2.3.4 with: github-token: ${{ secrets.github_token }} parallel-finished: true diff --git a/.rubocop.yml b/.rubocop.yml index c0f0c1fa0..8b6ed0180 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -9,7 +9,7 @@ require: - rubocop-rake AllCops: - TargetRubyVersion: 3.0 + TargetRubyVersion: 3.1 NewCops: enable Exclude: - 'vendor/**/*' diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 7384a8d95..0dd79ea2a 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -169,6 +169,7 @@ Rails/NotNullColumn: Rails/OutputSafety: Exclude: - 'app/helpers/application_helper.rb' + - 'app/helpers/user_mailer_helper.rb' - 'lib/rich_text.rb' - 'test/helpers/application_helper_test.rb' diff --git a/CONFIGURE.md b/CONFIGURE.md index dcc8ae2ac..29d1daad8 100644 --- a/CONFIGURE.md +++ b/CONFIGURE.md @@ -76,7 +76,7 @@ For iD, do the following: An example excerpt from settings.local.yml: -``` +```yaml # Default editor default_editor: "id" # OAuth 2 Client ID for iD @@ -99,7 +99,7 @@ To allow [Notes](https://wiki.openstreetmap.org/wiki/Notes) and changeset discus An example excerpt from settings.local.yml: -``` +```yaml # OAuth 2 Client ID for the web site oauth_application: "SGm8QJ6tmoPXEaUPIZzLUmm1iujltYZVWCp9hvGsqXg" # OAuth 2 Client Secret for the web site diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 383e793b3..e298c944f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,15 @@ +# Contributing + * https://www.ruby-lang.org/ - The homepage of Ruby which has more links and some great tutorials. * https://rubyonrails.org/ - The homepage of Rails, also has links and tutorials. +## Assigning Issues + +We don't assign issues to individual contributors. You are welcome to work on any +issue, and there's no need to ask first. + +For more details see [our FAQ](FAQ.md)] + ## Coding style We use [Rubocop](https://github.com/rubocop-hq/rubocop) (for ruby files) @@ -43,6 +52,12 @@ You can run the existing test suite with: bundle exec rails test:all ``` +You can run javascript tests with: + +``` +bundle exec teaspoon +``` + You can view test coverage statistics by browsing the `coverage` directory. The tests are automatically run on Pull Requests and other commits via github @@ -77,15 +92,6 @@ only submit changes to the `en.yml` file. The other files are updated via [Translatewiki](https://translatewiki.net/wiki/Translating:OpenStreetMap) and should not be included in your pull request. -### Nominatim prefixes - -I18n keys under the `geocoder.search_osm_nominatim` keyspace are managed by the -Nominatim maintainers. From time to time they run stats over the Nominatim -database, and update the list of available keys manually. - -Adding or removing keys to this list is therefore discouraged, but contributions -to the descriptive texts are welcome. - ### Copyright attribution The list of attributions on the /copyright page is managed by the [OSMF Licensing diff --git a/DOCKER.md b/DOCKER.md index 4804d09b3..b93bf6d50 100644 --- a/DOCKER.md +++ b/DOCKER.md @@ -24,27 +24,37 @@ Use [Docker Engine](https://docs.docker.com/engine/install/ubuntu/) with the [do The first step is to fork/clone the repo to your local machine: - git clone https://github.com/openstreetmap/openstreetmap-website.git +``` +git clone https://github.com/openstreetmap/openstreetmap-website.git +``` Now change working directory to the `openstreetmap-website`: - cd openstreetmap-website +``` +cd openstreetmap-website +``` ## Initial Setup ### Storage - cp config/example.storage.yml config/storage.yml +``` +cp config/example.storage.yml config/storage.yml +``` ### Database - cp config/docker.database.yml config/database.yml +``` +cp config/docker.database.yml config/database.yml +``` ## Prepare local settings file This is a workaround. [See issues/2185 for details](https://github.com/openstreetmap/openstreetmap-website/issues/2185#issuecomment-508676026). - touch config/settings.local.yml +``` +touch config/settings.local.yml +``` **Windows users:** `touch` is not an availible command in Windows so just create a `settings.local.yml` file in the `config` directory, or if you have WSL you can run `wsl touch config/settings.local.yml`. @@ -52,13 +62,17 @@ This is a workaround. [See issues/2185 for details](https://github.com/openstree To build local Docker images run from the root directory of the repository: - docker compose build +``` +docker compose build +``` If this is your first time running or you have removed cache this will take some time to complete. Once the Docker images have finished building you can launch the images as containers. To launch the app run: - docker compose up -d +``` +docker compose up -d +``` This will launch one Docker container for each 'service' specified in `docker-compose.yml` and run them in the background. There are two options for inspecting the logs of these running containers: @@ -69,21 +83,29 @@ This will launch one Docker container for each 'service' specified in `docker-co Run the Rails database migrations: - docker compose run --rm web bundle exec rails db:migrate +``` +docker compose run --rm web bundle exec rails db:migrate +``` ### Tests Prepare the test database: - docker compose run --rm web bundle exec rails db:test:prepare +``` +docker compose run --rm web bundle exec rails db:test:prepare +``` Run the test suite: - docker compose run --rm web bundle exec rails test:all +``` +docker compose run --rm web bundle exec rails test:all +``` If you encounter errors about missing assets, precompile the assets: - docker compose run --rm web bundle exec rake assets:precompile +``` +docker compose run --rm web bundle exec rake assets:precompile +``` ### Loading an OSM extract @@ -91,31 +113,37 @@ This installation comes with no geographic data loaded. You can either create ne For example, let's download the District of Columbia from Geofabrik or [any other region](https://download.geofabrik.de): - wget https://download.geofabrik.de/north-america/us/district-of-columbia-latest.osm.pbf +``` +wget https://download.geofabrik.de/north-america/us/district-of-columbia-latest.osm.pbf +``` You can now use Docker to load this extract into your local Docker-based OSM instance: - docker compose run --rm web osmosis \ - -verbose \ - --read-pbf district-of-columbia-latest.osm.pbf \ - --log-progress \ - --write-apidb \ - host="db" \ - database="openstreetmap" \ - user="openstreetmap" \ - validateSchemaVersion="no" +``` +docker compose run --rm web osmosis \ + -verbose \ + --read-pbf district-of-columbia-latest.osm.pbf \ + --log-progress \ + --write-apidb \ + host="db" \ + database="openstreetmap" \ + user="openstreetmap" \ + validateSchemaVersion="no" +``` **Windows users:** Powershell uses `` ` `` and CMD uses `^` at the end of each line, e.g.: - docker compose run --rm web osmosis ` - -verbose ` - --read-pbf district-of-columbia-latest.osm.pbf ` - --log-progress ` - --write-apidb ` - host="db" ` - database="openstreetmap" ` - user="openstreetmap" ` - validateSchemaVersion="no" +``` +docker compose run --rm web osmosis ` + -verbose ` + --read-pbf district-of-columbia-latest.osm.pbf ` + --log-progress ` + --write-apidb ` + host="db" ` + database="openstreetmap" ` + user="openstreetmap" ` + validateSchemaVersion="no" +``` Once you have data loaded for Washington, DC you should be able to navigate to [`http://localhost:3000/#map=12/38.8938/-77.0146`](http://localhost:3000/#map=12/38.8938/-77.0146) to begin working with your local instance. @@ -127,12 +155,18 @@ See [`CONFIGURE.md`](CONFIGURE.md) for information on how to manage users and en If you want to get into a web container and run specific commands you can fire up a throwaway container to run bash in via: - docker compose run --rm web bash +``` +docker compose run --rm web bash +``` Alternatively, if you want to use the already-running `web` container then you can `exec` into it via: - docker compose exec web bash +``` +docker compose exec web bash +``` Similarly, if you want to `exec` in the db container use: - docker compose exec db bash +``` +docker compose exec db bash +``` diff --git a/Dangerfile b/Dangerfile new file mode 100644 index 000000000..6e2aeced8 --- /dev/null +++ b/Dangerfile @@ -0,0 +1,42 @@ +# Get PR number +pr_number = github.pr_json["number"] + +# Report if number of changed lines is > 500 +if git.lines_of_code > 500 + warn("Number of updated lines of code is too large to be in one PR. Perhaps it should be separated into two or more?") + auto_label.set(pr_number, "big-pr", "FBCA04") +else + auto_label.remove("big-pr") +end + +# Get list of translation files (except en.yml) which are modified +modified_yml_files = git.modified_files.select do |file| + file.start_with?("config/locales") && File.extname(file) == ".yml" && File.basename(file) != "en.yml" +end + +# Report if some translation file (except en.yml) is modified +if modified_yml_files.empty? + auto_label.remove("inappropriate-translations") +else + modified_files_str = modified_yml_files.map { |file| "`#{file}`" }.join(", ") + warn("The following YAML files other than `en.yml` have been modified: #{modified_files_str}. Only `en.yml` is allowed to be changed. Translations are updated via Translatewiki, see CONTRIBUTING.md.") + auto_label.set(pr_number, "inappropriate-translations", "B60205") +end + +# Report if there are merge-commits in PR +if git.commits.any? { |c| c.parents.count > 1 } + warn("Merge commits are found in PR. Please rebase to get rid of the merge commits in this PR, see CONTRIBUTING.md.") + auto_label.set(pr_number, "merge-commits", "D93F0B") +else + auto_label.remove("merge-commits") +end + +# Check if Gemfile is modified but Gemfile.lock is not +gemfile_modified = git.modified_files.include?("Gemfile") +gemfile_lock_modified = git.modified_files.include?("Gemfile.lock") +if gemfile_modified && !gemfile_lock_modified + warn("Gemfile was updated, but Gemfile.lock wasn't updated. Usually, when Gemfile is updated, you should run `bundle install` to update Gemfile.lock.") + auto_label.set(pr_number, "gemfile-lock-outdated", "F9D0C4") +else + auto_label.remove("gemfile-lock-outdated") +end diff --git a/FAQ.md b/FAQ.md index d4ac1fc9f..e53c8dddb 100644 --- a/FAQ.md +++ b/FAQ.md @@ -1,3 +1,5 @@ +# Frequently Asked Questions + ## How do I create a banner to promote my OpenStreetMap event? We occasionally display banner images on the main page of [openstreetmap.org](https://www.openstreetmap.org/) to @@ -23,3 +25,13 @@ drive. This is a great way to reach a lot of people! See [PR #1296](https://github.com/openstreetmap/openstreetmap-website/pull/1296) as an example. + +## Why don't you assign issues? + +We don't assign issues to volunteers for several reasons. The main reasons are that it discourages other volunteers from working on the issue, and the process turns into an unproductive administrative overhead for our team. + +There's no need to ask for an issue to be assigned before anyone starts working on it. Everyone is welcome to work on any issue at any time. + +In our experience, most people who ask for an issue to be assigned to them never create a pull request. So we would need to keep track of the assigned issues, and remember to unassign them a week or two into the future, when it is likely that they will not be making a PR. Assigned developers might feel bad if they perceive that we're unhappy with their progress, further discouraging them from contributing. Or we will get drawn into discussions about needing more time, or re-assigning them again, or so on. So it is best not to assign in the first place. + +The risk that two people are both genuinely working on the same task in the same hour or two is vanishingly remote, and doesn't outweigh the downsides described above. A better approach is to encourage people to simply work on the task and create a pull request, at which point everyone knows that they are actually working on the issue and not just planning/hoping/wishing to do so. diff --git a/Gemfile b/Gemfile index 27f295eb6..277346b83 100644 --- a/Gemfile +++ b/Gemfile @@ -1,7 +1,7 @@ source "https://rubygems.org" # Require rails -gem "rails", "~> 7.1.0" +gem "rails", "~> 7.2.0" gem "turbo-rails" # Require json for multi_json @@ -130,7 +130,7 @@ gem "gd2-ffij", ">= 0.4.0" gem "marcel" # Used for browser detection -gem "browser", "< 6" # for ruby 3.0 support +gem "browser", "< 6" # for ruby 3.1 support # Used for S3 object storage gem "aws-sdk-s3" @@ -141,13 +141,15 @@ gem "image_processing" # Used to validate widths gem "unicode-display_width" -# Keep ruby 3.0 compatibility -gem "multi_xml", "~> 0.6.0" +# Lock some modules to old versions for ruby 3.1 support +gem "zeitwerk", "< 2.7" # Gems useful for development group :development do gem "better_errors" gem "binding_of_caller" + gem "danger" + gem "danger-auto_label" gem "debug_inspector" gem "i18n-tasks" gem "listen" @@ -181,6 +183,8 @@ end group :development, :test do gem "annotate" + gem "teaspoon" + gem "teaspoon-mocha", "~> 2.3.3" # See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem gem "debug", :require => "debug/prelude" diff --git a/Gemfile.lock b/Gemfile.lock index f496e5a98..0200f153e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -3,86 +3,83 @@ GEM specs: aasm (5.5.0) concurrent-ruby (~> 1.0) - actioncable (7.1.4) - actionpack (= 7.1.4) - activesupport (= 7.1.4) + actioncable (7.2.2.1) + actionpack (= 7.2.2.1) + activesupport (= 7.2.2.1) nio4r (~> 2.0) websocket-driver (>= 0.6.1) zeitwerk (~> 2.6) - actionmailbox (7.1.4) - actionpack (= 7.1.4) - activejob (= 7.1.4) - activerecord (= 7.1.4) - activestorage (= 7.1.4) - activesupport (= 7.1.4) - mail (>= 2.7.1) - net-imap - net-pop - net-smtp - actionmailer (7.1.4) - actionpack (= 7.1.4) - actionview (= 7.1.4) - activejob (= 7.1.4) - activesupport (= 7.1.4) - mail (~> 2.5, >= 2.5.4) - net-imap - net-pop - net-smtp + actionmailbox (7.2.2.1) + actionpack (= 7.2.2.1) + activejob (= 7.2.2.1) + activerecord (= 7.2.2.1) + activestorage (= 7.2.2.1) + activesupport (= 7.2.2.1) + mail (>= 2.8.0) + actionmailer (7.2.2.1) + actionpack (= 7.2.2.1) + actionview (= 7.2.2.1) + activejob (= 7.2.2.1) + activesupport (= 7.2.2.1) + mail (>= 2.8.0) rails-dom-testing (~> 2.2) - actionpack (7.1.4) - actionview (= 7.1.4) - activesupport (= 7.1.4) + actionpack (7.2.2.1) + actionview (= 7.2.2.1) + activesupport (= 7.2.2.1) nokogiri (>= 1.8.5) racc - rack (>= 2.2.4) + rack (>= 2.2.4, < 3.2) rack-session (>= 1.0.1) rack-test (>= 0.6.3) rails-dom-testing (~> 2.2) rails-html-sanitizer (~> 1.6) + useragent (~> 0.16) actionpack-page_caching (1.2.4) actionpack (>= 4.0.0) - actiontext (7.1.4) - actionpack (= 7.1.4) - activerecord (= 7.1.4) - activestorage (= 7.1.4) - activesupport (= 7.1.4) + actiontext (7.2.2.1) + actionpack (= 7.2.2.1) + activerecord (= 7.2.2.1) + activestorage (= 7.2.2.1) + activesupport (= 7.2.2.1) globalid (>= 0.6.0) nokogiri (>= 1.8.5) - actionview (7.1.4) - activesupport (= 7.1.4) + actionview (7.2.2.1) + activesupport (= 7.2.2.1) builder (~> 3.1) erubi (~> 1.11) rails-dom-testing (~> 2.2) rails-html-sanitizer (~> 1.6) active_record_union (1.3.0) activerecord (>= 4.0) - activejob (7.1.4) - activesupport (= 7.1.4) + activejob (7.2.2.1) + activesupport (= 7.2.2.1) globalid (>= 0.3.6) - activemodel (7.1.4) - activesupport (= 7.1.4) - activerecord (7.1.4) - activemodel (= 7.1.4) - activesupport (= 7.1.4) + activemodel (7.2.2.1) + activesupport (= 7.2.2.1) + activerecord (7.2.2.1) + activemodel (= 7.2.2.1) + activesupport (= 7.2.2.1) timeout (>= 0.4.0) - activerecord-import (1.8.1) + activerecord-import (2.0.0) activerecord (>= 4.2) - activestorage (7.1.4) - actionpack (= 7.1.4) - activejob (= 7.1.4) - activerecord (= 7.1.4) - activesupport (= 7.1.4) + activestorage (7.2.2.1) + actionpack (= 7.2.2.1) + activejob (= 7.2.2.1) + activerecord (= 7.2.2.1) + activesupport (= 7.2.2.1) marcel (~> 1.0) - activesupport (7.1.4) + activesupport (7.2.2.1) base64 + benchmark (>= 0.3) bigdecimal - concurrent-ruby (~> 1.0, >= 1.0.2) + concurrent-ruby (~> 1.0, >= 1.3.1) connection_pool (>= 2.2.5) drb i18n (>= 1.6, < 2) + logger (>= 1.4.2) minitest (>= 5.1) - mutex_m - tzinfo (~> 2.0) + securerandom (>= 0.3) + tzinfo (~> 2.0, >= 2.0.5) addressable (2.8.7) public_suffix (>= 2.0.2, < 7.0) annotate (3.2.0) @@ -95,22 +92,23 @@ GEM autoprefixer-rails (10.4.19.0) execjs (~> 2) aws-eventstream (1.3.0) - aws-partitions (1.972.0) - aws-sdk-core (3.203.0) + aws-partitions (1.1023.0) + aws-sdk-core (3.214.0) aws-eventstream (~> 1, >= 1.3.0) - aws-partitions (~> 1, >= 1.651.0) + aws-partitions (~> 1, >= 1.992.0) aws-sigv4 (~> 1.9) jmespath (~> 1, >= 1.6.1) - aws-sdk-kms (1.89.0) - aws-sdk-core (~> 3, >= 3.203.0) + aws-sdk-kms (1.96.0) + aws-sdk-core (~> 3, >= 3.210.0) aws-sigv4 (~> 1.5) - aws-sdk-s3 (1.160.0) - aws-sdk-core (~> 3, >= 3.203.0) + aws-sdk-s3 (1.176.1) + aws-sdk-core (~> 3, >= 3.210.0) aws-sdk-kms (~> 1) aws-sigv4 (~> 1.5) - aws-sigv4 (1.9.1) + aws-sigv4 (1.10.1) aws-eventstream (~> 1, >= 1.0.2) base64 (0.2.0) + benchmark (0.4.0) better_errors (2.10.1) erubi (>= 1.0.0) rack (>= 0.9.0) @@ -133,7 +131,7 @@ GEM bootstrap_form (5.4.0) actionpack (>= 6.1) activemodel (>= 6.1) - brakeman (6.2.1) + brakeman (6.2.2) racc brotli (0.6.0) browser (5.3.1) @@ -141,8 +139,8 @@ GEM bzip2-ffi (1.1.1) ffi (~> 1.0) cancancan (3.6.1) - canonical-rails (0.2.15) - actionview (>= 4.1, <= 7.2) + canonical-rails (0.2.16) + actionview (>= 4.1, < 7.3) capybara (3.40.0) addressable matrix @@ -154,15 +152,42 @@ GEM xpath (~> 3.2) childprocess (5.1.0) logger (~> 1.5) + claide (1.1.0) + claide-plugins (0.9.2) + cork + nap + open4 (~> 1.3) + colored2 (3.1.2) concurrent-ruby (1.3.4) - config (5.5.1) + config (5.5.2) deep_merge (~> 1.2, >= 1.2.1) + ostruct connection_pool (2.4.1) + cork (0.3.0) + colored2 (~> 3.1) crack (1.0.0) bigdecimal rexml crass (1.0.6) dalli (3.2.8) + danger (9.5.1) + base64 (~> 0.2) + claide (~> 1.0) + claide-plugins (>= 0.9.2) + colored2 (~> 3.1) + cork (~> 0.1) + faraday (>= 0.9.0, < 3.0) + faraday-http-cache (~> 2.0) + git (~> 1.13) + kramdown (~> 2.3) + kramdown-parser-gfm (~> 1.0) + octokit (>= 4.0) + pstore (~> 0.1) + terminal-table (>= 1, < 4) + danger-auto_label (1.3.1) + danger-plugin-api (~> 1.0) + danger-plugin-api (1.0.0) + danger (> 2.0) dartsass-ruby (3.0.2) sass-embedded (~> 1.54, < 1.67) dartsass-sprockets (3.0.0) @@ -171,31 +196,32 @@ GEM sprockets (> 3.0) sprockets-rails tilt - date (3.3.4) + date (3.4.1) debug (1.9.2) irb (~> 1.10) reline (>= 0.3.8) debug_inspector (1.2.0) deep_merge (1.2.2) - delayed_job (4.1.12) - activesupport (>= 3.0, < 8.0) - delayed_job_active_record (4.1.10) - activerecord (>= 3.0, < 8.0) + delayed_job (4.1.13) + activesupport (>= 3.0, < 9.0) + delayed_job_active_record (4.1.11) + activerecord (>= 3.0, < 9.0) delayed_job (>= 3.0, < 5) docile (1.4.1) - doorkeeper (5.7.1) + doorkeeper (5.8.1) railties (>= 5) doorkeeper-i18n (5.2.7) doorkeeper (>= 5.2) - doorkeeper-openid_connect (1.8.9) - doorkeeper (>= 5.5, < 5.8) + doorkeeper-openid_connect (1.8.10) + doorkeeper (>= 5.5, < 5.9) jwt (>= 2.5) drb (2.2.1) dry-configurable (1.2.0) dry-core (~> 1.0, < 2) zeitwerk (~> 2.6) - dry-core (1.0.1) + dry-core (1.0.2) concurrent-ruby (~> 1.0) + logger zeitwerk (~> 2.6) dry-inflector (1.1.0) dry-initializer (3.1.1) @@ -224,7 +250,7 @@ GEM dry-initializer (~> 3.0) dry-schema (>= 1.12, < 2) zeitwerk (~> 2.6) - erb_lint (0.6.0) + erb_lint (0.7.0) activesupport better_html (>= 2.0.1) parser (>= 2.7.1.4) @@ -232,18 +258,21 @@ GEM rubocop (>= 1) smart_properties erubi (1.13.0) - execjs (2.9.1) + execjs (2.10.0) exifr (1.4.0) factory_bot (6.5.0) activesupport (>= 5.0.0) - factory_bot_rails (6.4.3) - factory_bot (~> 6.4) + factory_bot_rails (6.4.4) + factory_bot (~> 6.5) railties (>= 5.0.0) - faraday (2.11.0) - faraday-net_http (>= 2.0, < 3.4) + faraday (2.12.2) + faraday-net_http (>= 2.0, < 3.5) + json logger - faraday-net_http (3.3.0) - net-http + faraday-http-cache (2.5.1) + faraday (>= 0.8) + faraday-net_http (3.4.0) + net-http (>= 0.5.0) ffi (1.17.0) ffi-compiler (1.3.2) ffi (>= 1.15.5) @@ -256,16 +285,19 @@ GEM fspath (3.1.2) gd2-ffij (0.4.0) ffi (>= 1.0.0) + git (1.19.1) + addressable (~> 2.8) + rchardet (~> 1.8) globalid (1.2.1) activesupport (>= 6.1) - google-protobuf (3.25.4) - hashdiff (1.1.1) + google-protobuf (3.25.5) + hashdiff (1.1.2) hashie (5.0.0) highline (3.1.1) reline htmlentities (4.3.4) http_accept_language (2.1.1) - i18n (1.14.5) + i18n (1.14.6) concurrent-ruby (~> 1.0) i18n-js (3.9.2) i18n (>= 0.6.6) @@ -279,7 +311,7 @@ GEM rails-i18n rainbow (>= 2.2.2, < 4.0) terminal-table (>= 1.5.1) - image_optim (0.31.3) + image_optim (0.31.4) exifr (~> 1.2, >= 1.2.2) fspath (~> 3.0) image_size (>= 1.5, < 4) @@ -295,11 +327,11 @@ GEM image_size (3.4.0) in_threads (1.6.0) iniparse (1.5.0) - io-console (0.7.2) - irb (1.14.0) + io-console (0.8.0) + irb (1.14.2) rdoc (>= 4.0.0) reline (>= 0.4.2) - jbuilder (2.12.0) + jbuilder (2.13.0) actionview (>= 5.0.0) activesupport (>= 5.0.0) jmespath (1.6.2) @@ -307,23 +339,25 @@ GEM rails-dom-testing (>= 1, < 3) railties (>= 4.2.0) thor (>= 0.14, < 2.0) - json (2.7.2) - jwt (2.8.2) + json (2.9.0) + jwt (2.9.3) base64 kgio (2.11.4) - kramdown (2.4.0) - rexml + kramdown (2.5.1) + rexml (>= 3.3.9) + kramdown-parser-gfm (1.1.0) + kramdown (~> 2.0) language_server-protocol (3.17.0.3) libv8-node (18.19.0.0) libxml-ruby (5.0.3) listen (3.9.0) rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) - logger (1.6.1) + logger (1.6.3) logstasher (2.1.5) activesupport (>= 5.2) request_store - loofah (2.22.0) + loofah (2.23.1) crass (~> 1.0.2) nokogiri (>= 1.12.0) mail (2.8.1) @@ -336,19 +370,20 @@ GEM maxminddb (0.1.22) mini_magick (4.13.2) mini_mime (1.1.5) - mini_portile2 (2.8.7) + mini_portile2 (2.8.8) mini_racer (0.9.0) libv8-node (~> 18.19.0.0) - minitest (5.25.1) + minitest (5.25.4) minitest-focus (1.4.0) minitest (>= 4, < 6) - msgpack (1.7.2) + msgpack (1.7.5) multi_json (1.15.0) - multi_xml (0.6.0) - mutex_m (0.2.0) - net-http (0.4.1) + multi_xml (0.7.1) + bigdecimal (~> 3.1) + nap (1.1.0) + net-http (0.6.0) uri - net-imap (0.4.16) + net-imap (0.5.2) date net-protocol net-pop (0.1.2) @@ -357,8 +392,8 @@ GEM timeout net-smtp (0.5.0) net-protocol - nio4r (2.7.3) - nokogiri (1.16.7) + nio4r (2.7.4) + nokogiri (1.17.2) mini_portile2 (~> 2.8.2) racc (~> 1.4) oauth (1.1.0) @@ -374,6 +409,9 @@ GEM rack (>= 1.2, < 4) snaky_hash (~> 2.0) version_gem (~> 1.1) + octokit (9.2.0) + faraday (>= 1, < 3) + sawyer (~> 0.9) omniauth (2.0.4) hashie (>= 3.4.6) rack (>= 1.6.2, < 3) @@ -384,8 +422,8 @@ GEM omniauth-github (2.0.1) omniauth (~> 2.0) omniauth-oauth2 (~> 1.8) - omniauth-google-oauth2 (1.1.3) - jwt (>= 2.0) + omniauth-google-oauth2 (1.2.0) + jwt (>= 2.9) oauth2 (~> 2.0) omniauth (~> 2.0) omniauth-oauth2 (~> 1.8) @@ -409,26 +447,30 @@ GEM omniauth-rails_csrf_protection (1.0.2) actionpack (>= 4.2) omniauth (~> 2.0) + open4 (1.3.4) openstreetmap-deadlock_retry (1.3.1) - overcommit (0.64.0) + ostruct (0.6.1) + overcommit (0.64.1) childprocess (>= 0.6.3, < 6) iniparse (~> 1.4) - rexml (~> 3.2) + rexml (>= 3.3.9) parallel (1.26.3) - parser (3.3.5.0) + parser (3.3.6.0) ast (~> 2.4.1) racc - pg (1.5.8) + pg (1.5.9) popper_js (2.11.8) progress (3.6.0) - psych (5.1.2) + pstore (0.1.4) + psych (5.2.1) + date stringio public_suffix (6.0.1) - puma (5.6.8) + puma (5.6.9) nio4r (~> 2.0) quad_tile (1.0.1) racc (1.8.1) - rack (2.2.9) + rack (2.2.10) rack-cors (2.0.2) rack (>= 2.0.0) rack-openid (1.4.2) @@ -442,23 +484,23 @@ GEM rack-test (2.1.0) rack (>= 1.3) rack-uri_sanitizer (0.0.2) - rackup (1.0.0) + rackup (1.0.1) rack (< 3) webrick - rails (7.1.4) - actioncable (= 7.1.4) - actionmailbox (= 7.1.4) - actionmailer (= 7.1.4) - actionpack (= 7.1.4) - actiontext (= 7.1.4) - actionview (= 7.1.4) - activejob (= 7.1.4) - activemodel (= 7.1.4) - activerecord (= 7.1.4) - activestorage (= 7.1.4) - activesupport (= 7.1.4) + rails (7.2.2.1) + actioncable (= 7.2.2.1) + actionmailbox (= 7.2.2.1) + actionmailer (= 7.2.2.1) + actionpack (= 7.2.2.1) + actiontext (= 7.2.2.1) + actionview (= 7.2.2.1) + activejob (= 7.2.2.1) + activemodel (= 7.2.2.1) + activerecord (= 7.2.2.1) + activestorage (= 7.2.2.1) + activesupport (= 7.2.2.1) bundler (>= 1.15.0) - railties (= 7.1.4) + railties (= 7.2.2.1) rails-controller-testing (1.0.5) actionpack (>= 5.0.1.rc1) actionview (>= 5.0.1.rc1) @@ -467,19 +509,19 @@ GEM activesupport (>= 5.0.0) minitest nokogiri (>= 1.6) - rails-html-sanitizer (1.6.0) + rails-html-sanitizer (1.6.2) loofah (~> 2.21) - nokogiri (~> 1.14) - rails-i18n (7.0.9) + nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0) + rails-i18n (7.0.10) i18n (>= 0.7, < 2) railties (>= 6.0.0, < 8) rails_param (1.3.1) actionpack (>= 3.2.0) activesupport (>= 3.2.0) - railties (7.1.4) - actionpack (= 7.1.4) - activesupport (= 7.1.4) - irb + railties (7.2.2.1) + actionpack (= 7.2.2.1) + activesupport (= 7.2.2.1) + irb (~> 1.13) rackup (>= 1.0.0) rake (>= 12.2) thor (~> 1.0, >= 1.2.2) @@ -489,30 +531,31 @@ GEM rb-fsevent (0.11.2) rb-inotify (0.11.1) ffi (~> 1.0) - rdoc (6.7.0) + rchardet (1.8.0) + rdoc (6.9.1) psych (>= 4.0.0) - regexp_parser (2.9.2) - reline (0.5.10) + regexp_parser (2.9.3) + reline (0.6.0) io-console (~> 0.5) request_store (1.7.0) rack (>= 1.4) - rexml (3.3.7) + rexml (3.4.0) rinku (2.0.6) rotp (6.3.0) - rouge (4.3.0) + rouge (4.5.1) rtlcss (0.2.1) mini_racer (>= 0.6.3) - rubocop (1.66.1) + rubocop (1.69.2) json (~> 2.3) language_server-protocol (>= 3.17.0) parallel (~> 1.10) parser (>= 3.3.0.2) rainbow (>= 2.2.2, < 4.0) - regexp_parser (>= 2.4, < 3.0) - rubocop-ast (>= 1.32.2, < 2.0) + regexp_parser (>= 2.9.3, < 3.0) + rubocop-ast (>= 1.36.2, < 2.0) ruby-progressbar (~> 1.7) - unicode-display_width (>= 2.4.0, < 3.0) - rubocop-ast (1.32.3) + unicode-display_width (>= 2.4.0, < 4.0) + rubocop-ast (1.37.0) parser (>= 3.3.1.0) rubocop-capybara (2.21.0) rubocop (~> 1.41) @@ -521,10 +564,10 @@ GEM rubocop-minitest (0.36.0) rubocop (>= 1.61, < 2.0) rubocop-ast (>= 1.31.1, < 2.0) - rubocop-performance (1.21.1) + rubocop-performance (1.23.0) rubocop (>= 1.48.1, < 2.0) rubocop-ast (>= 1.31.1, < 2.0) - rubocop-rails (2.26.1) + rubocop-rails (2.27.0) activesupport (>= 4.2.0) rack (>= 1.1) rubocop (>= 1.52.0, < 2.0) @@ -543,6 +586,10 @@ GEM sass-embedded (1.64.2) google-protobuf (~> 3.23) rake (>= 13.0.0) + sawyer (0.9.2) + addressable (>= 2.3.5) + faraday (>= 0.17.3, < 3) + securerandom (0.4.1) selenium-webdriver (4.23.0) base64 (~> 0.2) logger (~> 1.4) @@ -574,31 +621,35 @@ GEM stringio (3.1.1) strong_migrations (1.8.0) activerecord (>= 5.2) + teaspoon (1.4.0) + railties (>= 5.0) + teaspoon-mocha (2.3.3) + teaspoon (>= 1.0.0) terminal-table (3.0.2) unicode-display_width (>= 1.1.1, < 3) - terser (1.2.3) + terser (1.2.4) execjs (>= 0.3.0, < 3) thor (1.3.2) tilt (2.4.0) - timeout (0.4.1) - turbo-rails (2.0.6) + timeout (0.4.3) + turbo-rails (2.0.11) actionpack (>= 6.0.0) - activejob (>= 6.0.0) railties (>= 6.0.0) tzinfo (2.0.6) concurrent-ruby (~> 1.0) - unicode-display_width (2.5.0) + unicode-display_width (2.6.0) uri (0.13.1) + useragent (0.16.11) validates_email_format_of (1.8.2) i18n (>= 0.8.0) simpleidn vendorer (0.2.0) version_gem (1.1.4) - webmock (3.23.1) + webmock (3.24.0) addressable (>= 2.8.0) crack (>= 0.3.2) hashdiff (>= 0.4.0, < 2.0.0) - webrick (1.8.1) + webrick (1.9.1) websocket (1.2.11) websocket-driver (0.7.6) websocket-extensions (>= 0.1.0) @@ -634,6 +685,8 @@ DEPENDENCIES config connection_pool dalli + danger + danger-auto_label dartsass-sprockets debug debug_inspector @@ -670,7 +723,6 @@ DEPENDENCIES minitest (~> 5.1) minitest-focus multi_json - multi_xml (~> 0.6.0) omniauth (~> 2.0.2) omniauth-facebook omniauth-github @@ -686,7 +738,7 @@ DEPENDENCIES quad_tile (~> 1.0.1) rack-cors rack-uri_sanitizer - rails (~> 7.1.0) + rails (~> 7.2.0) rails-controller-testing rails-i18n (~> 7.0.0) rails_param @@ -707,12 +759,15 @@ DEPENDENCIES simplecov-lcov sprockets-exporters_pack strong_migrations (< 2.0.0) + teaspoon + teaspoon-mocha (~> 2.3.3) terser turbo-rails unicode-display_width validates_email_format_of (>= 1.5.1) vendorer webmock + zeitwerk (< 2.7) BUNDLED WITH - 2.4.19 + 2.5.22 diff --git a/INSTALL.md b/INSTALL.md index c8e28a62f..8667fb512 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -9,7 +9,7 @@ are two alternatives which make it easier to get a consistent development enviro * **Vagrant** This installs the software into a virtual machine. For Vagrant instructions see [VAGRANT.md](VAGRANT.md). * **Docker** This installs the software using containerization. For Docker instructions see [DOCKER.md](DOCKER.md). -These instructions are based on Ubuntu 22.04 LTS, which is the platform used by the OSMF servers. +These instructions are based on Ubuntu 24.04 LTS, which is the platform used by the OSMF servers. The instructions also work, with only minor amendments, for all other current Ubuntu releases, Fedora and MacOSX We don't recommend attempting to develop or deploy this software on Windows. Some Ruby gems may not be supported. If you need to use Windows the easiest solutions in order are [Docker](DOCKER.md), [Vagrant](VAGRANT.md), and Ubuntu in a virtual machine. @@ -22,12 +22,12 @@ of packages required before you can get the various gems installed. ## Minimum requirements -* Ruby 3.0+ +* Ruby 3.1+ * PostgreSQL 13+ * Bundler (see note below about [developer Ruby setup](#rbenv)) * Javascript Runtime -These can be installed on Ubuntu 22.04 or later with: +These can be installed on Ubuntu 24.04 or later with: ``` sudo apt-get update diff --git a/Vagrantfile b/Vagrantfile index 7895d3b86..617bd7b4d 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -2,9 +2,11 @@ # vi: set ft=ruby : Vagrant.configure("2") do |config| - # use official ubuntu image for virtualbox + # use official debian image + config.vm.box = "debian/bookworm64" + + # configure virtualbox provider config.vm.provider "virtualbox" do |vb, override| - override.vm.box = "ubuntu/jammy64" override.vm.synced_folder ".", "/srv/openstreetmap-website" vb.customize ["modifyvm", :id, "--memory", "4096"] vb.customize ["modifyvm", :id, "--cpus", "2"] @@ -14,16 +16,16 @@ Vagrant.configure("2") do |config| # Use sshfs sharing if available, otherwise NFS sharing sharing_type = Vagrant.has_plugin?("vagrant-sshfs") ? "sshfs" : "nfs" - # use third party image and sshfs or NFS sharing for lxc + # configure lxc provider config.vm.provider "lxc" do |_, override| - override.vm.box = "generic/ubuntu2204" override.vm.synced_folder ".", "/srv/openstreetmap-website", :type => sharing_type end - # use third party image and sshfs or NFS sharing for libvirt - config.vm.provider "libvirt" do |_, override| - override.vm.box = "generic/ubuntu2204" + # configure libvirt provider + config.vm.provider "libvirt" do |libvirt, override| override.vm.synced_folder ".", "/srv/openstreetmap-website", :type => sharing_type + libvirt.memory = 4096 + libvirt.cpus = 2 end # configure shared package cache if possible diff --git a/app/abilities/ability.rb b/app/abilities/ability.rb index 9a8f193a1..725ceccb2 100644 --- a/app/abilities/ability.rb +++ b/app/abilities/ability.rb @@ -68,7 +68,7 @@ class Ability can [:index, :show, :resolve, :ignore, :reopen], Issue can :create, IssueComment can [:set_status, :destroy, :index], User - can [:grant, :revoke], UserRole + can [:create, :destroy], UserRole end end end diff --git a/app/abilities/api_ability.rb b/app/abilities/api_ability.rb index 96ed9b080..c790da66a 100644 --- a/app/abilities/api_ability.rb +++ b/app/abilities/api_ability.rb @@ -22,7 +22,7 @@ class ApiAbility if user&.active? can [:comment, :close, :reopen], Note - can [:create, :show, :update, :destroy, :data], Trace + can [:create, :show, :update, :destroy], Trace can [:details, :gpx_files], User can [:index, :show, :update, :update_all, :destroy], UserPreference diff --git a/app/abilities/api_capability.rb b/app/abilities/api_capability.rb index d8be13643..0e953d50b 100644 --- a/app/abilities/api_capability.rb +++ b/app/abilities/api_capability.rb @@ -9,6 +9,7 @@ class ApiCapability if user&.active? can [:create, :comment, :close, :reopen], Note if scope?(token, :write_notes) + can [:create, :destroy], NoteSubscription if scope?(token, :write_notes) can [:show, :data], Trace if scope?(token, :read_gpx) can [:create, :update, :destroy], Trace if scope?(token, :write_gpx) can [:details], User if scope?(token, :read_prefs) diff --git a/app/assets/images/browse/node.svg b/app/assets/images/browse/node.svg new file mode 100644 index 000000000..35e592763 --- /dev/null +++ b/app/assets/images/browse/node.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/app/assets/images/browse/relation.svg b/app/assets/images/browse/relation.svg new file mode 100644 index 000000000..9cb52fc67 --- /dev/null +++ b/app/assets/images/browse/relation.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/app/assets/images/browse/way.svg b/app/assets/images/browse/way.svg new file mode 100644 index 000000000..98eae574f --- /dev/null +++ b/app/assets/images/browse/way.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 054742126..ead01a8ff 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -1,6 +1,5 @@ //= require jquery3 //= require jquery_ujs -//= require jquery.timers //= require jquery.throttle-debounce //= require js-cookie/dist/js.cookie //= require popper diff --git a/app/assets/javascripts/id.js b/app/assets/javascripts/id.js index 706097bba..15f77b1c1 100644 --- a/app/assets/javascripts/id.js +++ b/app/assets/javascripts/id.js @@ -28,6 +28,12 @@ document.addEventListener("DOMContentLoaded", function () { .containerNode(container) .init(); + if (parent === window) { + // iD not opened in an iframe -> skip setting of parent handlers + return; + } + + var hashChangedAutomatically = false; id.map().on("move.embed", parent.$.throttle(250, function () { if (id.inIntro()) return; var zoom = ~~id.map().zoom(), @@ -40,14 +46,12 @@ document.addEventListener("DOMContentLoaded", function () { // https://gist.github.com/jfirebaugh/5439412 var hash = parent.OSM.formatHash(llz); if (hash !== parent.location.hash) { + hashChangedAutomatically = true; parent.location.replace(parent.location.href.replace(/(#.*|$)/, hash)); } })); - parent.$("body").on("click", "a.set_position", function (e) { - e.preventDefault(); - var data = parent.$(this).data(); - + function goToLocation(data) { // 0ms timeout to avoid iframe JS context weirdness. // https://gist.github.com/jfirebaugh/5439412 setTimeout(function () { @@ -55,6 +59,22 @@ document.addEventListener("DOMContentLoaded", function () { [data.lon, data.lat], Math.max(data.zoom || 15, 13)); }, 0); + } + + parent.$("body").on("click", "a.set_position", function (e) { + e.preventDefault(); + var data = parent.$(this).data(); + goToLocation(data); + }); + + parent.addEventListener("hashchange", function (e) { + if (hashChangedAutomatically) { + hashChangedAutomatically = false; + return; + } + e.preventDefault(); + var data = parent.OSM.mapParams(); + goToLocation(data); }); } }); diff --git a/app/assets/javascripts/index.js b/app/assets/javascripts/index.js index 4f3c414f5..56495b31a 100644 --- a/app/assets/javascripts/index.js +++ b/app/assets/javascripts/index.js @@ -1,7 +1,7 @@ //= require_self //= require leaflet.sidebar //= require leaflet.sidebar-pane -//= require leaflet.locatecontrol/src/L.Control.Locate +//= require leaflet.locatecontrol/dist/L.Control.Locate.umd //= require leaflet.locate //= require leaflet.layers //= require leaflet.key @@ -25,8 +25,6 @@ //= require qs/dist/qs $(document).ready(function () { - var loaderTimeout; - var map = new L.OSM.Map("map", { zoomControl: false, layerControl: false, @@ -39,11 +37,7 @@ $(document).ready(function () { map.setSidebarOverlaid(false); - clearTimeout(loaderTimeout); - - loaderTimeout = setTimeout(function () { - $("#sidebar_loader").show(); - }, 200); + $("#sidebar_loader").show().addClass("delayed-fade-in"); // IE<10 doesn't respect Vary: X-Requested-With header, so // prevent caching the XHR response as a full-page URL. @@ -60,9 +54,8 @@ $(document).ready(function () { url: content_path, dataType: "html", complete: function (xhr) { - clearTimeout(loaderTimeout); $("#flash").empty(); - $("#sidebar_loader").hide(); + $("#sidebar_loader").removeClass("delayed-fade-in").hide(); var content = $(xhr.responseText); @@ -214,7 +207,7 @@ $(document).ready(function () { if (OSM.MATOMO) { map.on("layeradd", function (e) { if (e.layer.options) { - var goal = OSM.MATOMO.goals[e.layer.options.keyid]; + var goal = OSM.MATOMO.goals[e.layer.options.layerId]; if (goal) { $("body").trigger("matomogoal", goal); @@ -262,20 +255,10 @@ $(document).ready(function () { }); function sendRemoteEditCommand(url, callback) { - var iframe = $("