Skip to content

Commit 333690a

Browse files
committed
Add support for GitHub Codespaces and port forwarding
GitHub Codespaces is a commercial offering for devcontainers. While our setup mostly works out-of-the-box, the host and port forwarding required further adjustments to work as expected.
1 parent e959d37 commit 333690a

6 files changed

Lines changed: 90 additions & 6 deletions

File tree

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# CodeHarbor
22

3+
[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/openHPI/codeharbor)
4+
35
[![Build Status](https://github.com/openHPI/codeharbor/workflows/CI/badge.svg)](https://github.com/openHPI/codeharbor/actions?query=workflow%3ACI)
46
[![codecov](https://codecov.io/gh/openHPI/codeharbor/branch/master/graph/badge.svg?token=lUL0Fq7Uc9)](https://codecov.io/gh/openHPI/codeharbor)
57

bin/shakapacker-dev-server

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,13 @@ ENV['SHAKAPACKER_USE_PACKAGE_JSON_GEM'] ||= 'true'
1010
require 'bundler/setup'
1111
require 'shakapacker'
1212
require 'shakapacker/dev_server_runner'
13+
require_relative '../config/initializers/github_codespaces'
1314

1415
APP_ROOT = File.expand_path('..', __dir__)
1516
Dir.chdir(APP_ROOT) do
17+
if GithubCodespaces.active?
18+
ARGV.push('--client-web-socket-url', GithubCodespaces.client_web_socket_url)
19+
end
20+
1621
Shakapacker::DevServerRunner.run(ARGV)
1722
end

config/environments/development.rb

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,19 @@
11
# frozen_string_literal: true
22

33
require 'active_support/core_ext/integer/time'
4+
require_relative '../initializers/github_codespaces'
45

56
Rails.application.configure do
67
# Settings specified here will take precedence over those in config/application.rb.
78

8-
# Allowed IPs for the Vagrant setup
9-
config.web_console.allowed_ips = '192.168.0.0/16'
9+
if GithubCodespaces.active? || ENV.fetch('USER', nil) == 'vagrant'
10+
# Allow the webconsole to be used; all traffic is proxied and thus appears to come from a private IP
11+
# By default, GitHub requires an authorization to access a Codespaces domain.
12+
# Vagrant is running locally in a private network and thus not accessible from the outside anyway.
13+
private_ips = %w[10.0.0.0/8 172.16.0.0/12 192.168.0.0/16]
14+
config.web_console.permissions = private_ips
15+
private_ips.each {|ip| BetterErrors::Middleware.allow_ip! ip }
16+
end
1017

1118
# In the development environment your application's code is reloaded any time
1219
# it changes. This slows down response time but is perfect for development

config/initializers/content_security_policy.rb

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
require_relative 'sentry_csp'
1010
require_relative 'sentry_javascript'
1111
require_relative 'devise'
12+
require_relative 'github_codespaces'
1213

1314
module CSP
1415
def self.apply_yml_settings_for(policy)
@@ -35,6 +36,13 @@ def self.apply_omniauth_settings_for(policy)
3536
end
3637
end
3738

39+
def self.apply_codespaces_settings_for(policy)
40+
%w[wss https].each do |scheme|
41+
url = GithubCodespaces.url_for(:webpack_dev_server, scheme)
42+
add_policy(policy, :connect_src, [url])
43+
end
44+
end
45+
3846
def self.add_policy(policy, directive, additional_settings)
3947
all_settings = additional_settings
4048
existing_settings = if directive == 'report_uri'
@@ -98,9 +106,10 @@ def self.get_host_source(url)
98106
# "An iframe which has both allow-scripts and allow-same-origin for its sandbox attribute can escape its sandboxing."
99107
policy.sandbox 'allow-downloads', 'allow-forms', 'allow-modals', 'allow-popups', 'allow-same-origin', 'allow-scripts'
100108

101-
CSP.apply_yml_settings_for policy
102-
CSP.apply_sentry_settings_for policy if SentryJavascript.active?
103-
CSP.apply_omniauth_settings_for policy if Devise.omniauth_configs.present?
109+
CSP.apply_yml_settings_for policy
110+
CSP.apply_sentry_settings_for policy if SentryJavascript.active?
111+
CSP.apply_omniauth_settings_for policy if Devise.omniauth_configs.present?
112+
CSP.apply_codespaces_settings_for policy if GithubCodespaces.active?
104113
end
105114

106115
# Generate session nonces for permitted importmap, inline scripts, and inline styles.
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# frozen_string_literal: true
2+
3+
class GithubCodespaces
4+
def self.active?
5+
ENV['CODESPACES'] == 'true'
6+
end
7+
8+
def self.client_web_socket_url
9+
"#{url_for(:webpack_dev_server, 'wss')}/ws"
10+
end
11+
12+
def self.url_for(server, scheme = 'https')
13+
"#{scheme}://#{domain_for(server)}"
14+
end
15+
16+
def self.domain_for(server)
17+
port = send(server)
18+
hostname_for(port)
19+
end
20+
21+
class << self
22+
private
23+
24+
def hostname_for(port)
25+
codespace_name = ENV.fetch('CODESPACE_NAME')
26+
forwarding_domain = ENV.fetch('GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN')
27+
28+
"#{codespace_name}-#{port}.#{forwarding_domain}"
29+
end
30+
31+
def rails_server
32+
ENV.fetch('PORT', 7500)
33+
end
34+
35+
def webpack_dev_server
36+
ENV.fetch('SHAKAPACKER_DEV_SERVER_PORT', 3045)
37+
end
38+
end
39+
end
40+
41+
if GithubCodespaces.active? && defined? Rails
42+
Rails.application.configure do
43+
# Allow the Rails server to be accessed from the Codespaces domain
44+
config.hosts << GithubCodespaces.domain_for(:rails_server)
45+
46+
# Disable an additional CSRF protection, where the browser's ORIGIN header is
47+
# checked against the site's request URL. Since the Codespaces proxy is not setting
48+
# all required X-FORWARDED-* headers, we currently need to disable this check.
49+
config.action_controller.forgery_protection_origin_check = false
50+
end
51+
end

docs/LOCAL_SETUP_DEVCONTAINER.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# Devcontainer setup
22

3-
With the devcontainer-based setup, you won't need to (manually) install CodeHarbor and all dependencies on your local instance. Instead, a Docker setup containing all requirements will be configured. The development environment is defined in the `.devcontainer` repository folder and will be applied when you open the project in a supported editor or IDE.
3+
With the devcontainer-based setup, you won't need to (manually) install CodeHarbor and all dependencies on your local instance. Instead, a Docker setup containing all requirements will be configured.
4+
5+
You can either run a devcontainer locally (with Docker) or remotely (e.g., with GitHub Codespaces). In both cases, the development environment is defined in the `.devcontainer` repository folder and will be applied when you open the project in a supported editor or IDE.
46

57
## Local setup
68

@@ -53,6 +55,14 @@ Click on the blue "Reopen in Container" button in the bottom right corner of you
5355
**RubyMine:** / **IntelliJ IDEA:**
5456
Open the file `.devcontainer/devcontainer.json` and click on the blue Docker icon in the top left corner of your editor. More information for [RubyMine](https://www.jetbrains.com/help/ruby/connect-to-devcontainer.html#create_dev_container_inside_ide) or [IntelliJ IDEA](https://www.jetbrains.com/help/idea/connect-to-devcontainer.html#create_dev_container_inside_ide).
5557

58+
## Remote setup with GitHub Codespaces
59+
60+
You can also run the devcontainer remotely with GitHub Codespaces. This way, you can develop CodeHarbor in the cloud without the need to install any dependencies on your local machine.
61+
62+
To get started with GitHub Codespaces, click on the ["Open in GitHub Codespaces"](https://codespaces.new/openHPI/codeharbor) button at the top of the [README.md file](../README.md). This will open the project in a new Codespace. You can find more information on how to set up your project for Codespaces in the [official documentation](https://docs.github.com/en/codespaces/setting-up-your-project-for-codespaces/adding-a-dev-container-configuration/introduction-to-dev-containers).
63+
5664
# Start CodeHarbor
5765

5866
When developing with the devcontainer, you can run CodeHarbor in the same way as you would on your local machine. The only difference is that you're running it inside the devcontainer. You can find more information on how to run CodeHarbor in the [LOCAL_SETUP.md](LOCAL_SETUP.md#start-codeharbor). All ports are forwarded to your local machine, so you can access CodeHarbor in your browser as usual.
67+
68+
In GitHub Codespaces, the ports are forwarded automatically, so you can access CodeHarbor in your browser by clicking on the "Open in Browser" button in the Codespaces environment as soon as the Rails server was started. [More information](https://docs.github.com/de/codespaces/developing-in-a-codespace/forwarding-ports-in-your-codespace).

0 commit comments

Comments
 (0)