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