diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 776127446ef..8270218e95f 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,16 +1,37 @@ { "name": "Discourse", - "image": "discourse/discourse_dev:release", - "workspaceMount": "source=${localWorkspaceFolder}/../..,target=/var/www/discourse,type=bind", - "workspaceFolder": "/var/www/discourse", - "settings": { - "search.followSymlinks": false - }, - "postStartCommand": "sudo /sbin/boot", - "extensions": ["rebornix.Ruby"], - "forwardPorts": [9292], + "image": "docker.io/discourse/discourse_dev:20241111-0710", + "workspaceMount": "source=${localWorkspaceFolder},target=/workspace/discourse,type=bind", + "workspaceFolder": "/workspace/discourse", + "postStartCommand": "./.devcontainer/scripts/start.rb", + "forwardPorts": [ + 9292, // bin/unicorn + 3000, // bin/rails s + 4200, // ember-cli + 8025, // mailhog + 9229 // chrome remote debug + ], "remoteUser": "discourse", "remoteEnv": { - "DISCOURSE_DEV_HOSTS": ".githubpreview.dev" + "RAILS_DEVELOPMENT_HOSTS": ".app.github.dev", + "PGUSER": "discourse", + "SELENIUM_FORWARD_DEVTOOLS_TO_PORT": "9229", + }, + "mounts": [ + "source=${localWorkspaceFolderBasename}-node_modules,target=${containerWorkspaceFolder}/node_modules,type=volume", + "source=${localWorkspaceFolderBasename}-pg,target=/shared/postgres_data,type=volume", + "source=${localWorkspaceFolderBasename}-redis,target=/shared/redis,type=volume" + ], + "customizations": { + "vscode": { + "extensions": [ + "Shopify.ruby-lsp", + "esbenp.prettier-vscode", + "dbaeumer.vscode-eslint", + "ruby-syntax-tree.vscode-syntax-tree", + "lifeart.vscode-glimmer-syntax", + "typed-ember.glint-vscode" + ] + } } } diff --git a/.devcontainer/scripts/start.rb b/.devcontainer/scripts/start.rb new file mode 100755 index 00000000000..f00972c335b --- /dev/null +++ b/.devcontainer/scripts/start.rb @@ -0,0 +1,27 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +puts "👋 Welcome to the Discourse devcontainer! Let's get everything ready..." + +puts "Setting permissions on volume mounts..." +system "sudo chown discourse .", exception: true +system "sudo chown discourse node_modules", exception: true +system "sudo chown -R postgres /shared/postgres_data", exception: true + +puts "Starting services..." +fork do + Process.daemon + exec "sudo nohup /sbin/boot" +end + +system "cp -n .vscode/settings.json.sample .vscode/settings.json", exception: true +system "cp -n .vscode/tasks.json.sample .vscode/tasks.json", exception: true + +puts <<~TXT + 🎉 All done! + + Next steps: + 1. Cmd/Ctrl + Shift + B to run the shortcuts/boot-dev task + 2. Wait for the server to start + 3. Open your browser to http://localhost:4200 +TXT diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 3ea3050050f..1cb711620bd 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -5,6 +5,7 @@ "esbenp.prettier-vscode", "dbaeumer.vscode-eslint", "ruby-syntax-tree.vscode-syntax-tree", - "lifeart.vscode-glimmer-syntax" + "lifeart.vscode-glimmer-syntax", + "typed-ember.glint-vscode" ] } diff --git a/.vscode/tasks.json.sample b/.vscode/tasks.json.sample index ea802ffa622..c7640bb5e32 100644 --- a/.vscode/tasks.json.sample +++ b/.vscode/tasks.json.sample @@ -4,9 +4,9 @@ "version": "2.0.0", "tasks": [ { - "label": "deps/yarn", + "label": "deps/pnpm", "type": "shell", - "command": "yarn install", + "command": "pnpm install", "presentation": { "reveal": "always", "group": "deps", @@ -28,7 +28,7 @@ { "label": "deps/all", "dependsOn": [ - "deps/yarn", + "deps/pnpm", "deps/bundle" ], "problemMatcher": [] diff --git a/app/assets/javascripts/custom-proxy/index.js b/app/assets/javascripts/custom-proxy/index.js index 6a62acf8aa7..39813fb4a4a 100644 --- a/app/assets/javascripts/custom-proxy/index.js +++ b/app/assets/javascripts/custom-proxy/index.js @@ -95,10 +95,11 @@ function updateScriptReferences({ ); } - // We use _lr/livereload.js directly instead of ember-cli-live-reload so that the protocol/port is configured automatically + // ember-cli-live-reload doesn't select ports correctly, so we use _lr/livereload directly // (important for cloud development environments like GitHub CodeSpaces) newElements.unshift( - `` + ``, + `` ); } diff --git a/bin/ember-cli b/bin/ember-cli index cf3cf33c088..cdac84622cf 100755 --- a/bin/ember-cli +++ b/bin/ember-cli @@ -67,6 +67,17 @@ pnpm_env["FORWARD_HOST"] = "true" if ARGV.include?("--forward-host") if ARGV.include?("-u") || ARGV.include?("--unicorn") unicorn_env = { "DISCOURSE_PORT" => ENV["DISCOURSE_PORT"] || "4200" } + + if command == "server" && ENV["CODESPACE_NAME"] + unicorn_env.merge!( + { + "DISCOURSE_PORT" => "443", + "DISCOURSE_FORCE_HTTPS" => "1", + "DISCOURSE_FORCE_HOSTNAME" => "#{ENV["CODESPACE_NAME"]}-4200.#{ENV["GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN"]}" + } + ) + end + unicorn_pid = spawn(unicorn_env, __dir__ + "/unicorn") ember_cli_pid = nil diff --git a/spec/support/system_helpers.rb b/spec/support/system_helpers.rb index 55cc4128625..7ba73ee189d 100644 --- a/spec/support/system_helpers.rb +++ b/spec/support/system_helpers.rb @@ -8,6 +8,20 @@ module SystemHelpers msg = "Test paused. Press enter to resume, or `d` + enter to start debugger.\n\n" msg += "Browser inspection URLs:\n" + base_url = page.driver.browser.send(:devtools_address) + uri = URI(base_url) + response = Net::HTTP.get(uri.hostname, "/json/list", uri.port) + + socat_pid = nil + + if exposed_port = ENV["SELENIUM_FORWARD_DEVTOOLS_TO_PORT"] + socat_pid = + fork do + chrome_port = uri.port + exec "socat tcp-listen:#{exposed_port},reuseaddr,fork tcp:localhost:#{chrome_port}" + end + end + # Fetch devtools urls base_url = page.driver.browser.send(:devtools_address) uri = URI(base_url) @@ -15,13 +29,28 @@ module SystemHelpers JSON .parse(response) .each do |result| - msg += - " - (#{result["type"]}) #{base_url}#{result["devtoolsFrontendUrl"]} (#{URI(result["url"]).path})\n" + devtools_url = "#{base_url}#{result["devtoolsFrontendUrl"]}" + + devtools_url = devtools_url.gsub(":#{uri.port}", ":#{exposed_port}") if exposed_port + + if ENV["CODESPACE_NAME"] + devtools_url = + devtools_url + .gsub( + "localhost:#{exposed_port}", + "#{ENV["CODESPACE_NAME"]}-#{exposed_port}.#{ENV["GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN"]}", + ) + .gsub("http://", "https://") + .gsub("ws=", "wss=") + end + + msg += " - (#{result["type"]}) #{devtools_url} (#{URI(result["url"]).path})\n" end result = ask("\n\e[33m#{msg}\e[0m") binding.pry if result == "d" # rubocop:disable Lint/Debugger puts "\e[33mResuming...\e[0m" + Process.kill("TERM", socat_pid) if socat_pid self end