diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 000000000..90bfc97be --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,3 @@ +# Make sure RUBY_VERSION matches the Ruby version in .ruby-version +ARG RUBY_VERSION=3.3.5 +FROM ghcr.io/rails/devcontainer/images/ruby:$RUBY_VERSION diff --git a/.devcontainer/compose.yaml b/.devcontainer/compose.yaml new file mode 100644 index 000000000..722bb6b70 --- /dev/null +++ b/.devcontainer/compose.yaml @@ -0,0 +1,40 @@ +name: "codeharbor" + +services: + rails-app: + build: + context: .. + dockerfile: .devcontainer/Dockerfile + + volumes: + - ../..:/workspaces:cached + + # Overrides default command so things don't shut down after the process ends. + command: sleep infinity + + # Uncomment the next line to use a non-root user for all processes. + # user: vscode + + # Use "forwardPorts" in **devcontainer.json** to forward an app port locally. + # (Adding the "ports" property to this file will not forward from a Codespace.) + depends_on: + - selenium + - postgres + + selenium: + image: selenium/standalone-chromium + restart: unless-stopped + + postgres: + image: postgres:16.4 + restart: unless-stopped + networks: + - default + volumes: + - postgres-data:/var/lib/postgresql/data + environment: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + +volumes: + postgres-data: diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 000000000..e44a1b2a6 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,48 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/ruby +{ + "name": "CodeHarbor", + "dockerComposeFile": "compose.yaml", + "service": "rails-app", + "workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}", + + // Features to add to the dev container. More info: https://containers.dev/features. + "features": { + "ghcr.io/devcontainers/features/git-lfs:1": {}, + "ghcr.io/devcontainers/features/github-cli:1": {}, + "ghcr.io/rails/devcontainer/features/activestorage": {}, + "ghcr.io/devcontainers/features/node:1": { + "installYarnUsingApt": false + }, + "ghcr.io/rails/devcontainer/features/postgres-client": {} + }, + + "containerEnv": { + "COREPACK_ENABLE_DOWNLOAD_PROMPT": "0", + "CAPYBARA_SERVER_PORT": "45678", + "SELENIUM_HOST": "selenium", + "DB_HOST": "postgres" + }, + + // Use 'forwardPorts' to make a list of ports inside the container available locally. + "forwardPorts": [3045, 7500], + + "portsAttributes": { + "3045": { + "label": "webpack-dev-server" + }, + "7500": { + "label": "rails-server" + } + }, + + // Configure tool-specific properties. + // "customizations": {}, + + // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. + // "remoteUser": "root", + + + // Use 'postCreateCommand' to run commands after the container is created. + "postCreateCommand": "bin/setup" +} diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 735c87495..7918e89a6 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -40,3 +40,13 @@ updates: labels: - dependencies - docker + + - package-ecosystem: devcontainers + directory: "/" + schedule: + interval: daily + time: "03:00" + timezone: UTC + labels: + - dependencies + - devcontainers diff --git a/README.md b/README.md index 8accd49fb..b3c227a3c 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,7 @@ CodeHarbor is a repository system for automatically gradeable programming exercises and enables instructors to exchange of such exercises via the [ProFormA XML](https://github.com/ProFormA/proformaxml) format across diverse code assessment systems. ## Server Setup and Deployment -Use [Capistrano](https://capistranorb.com/). or the provided Dockerfile (only for production). Vagrant is for local development only. - +Use [Capistrano](https://capistranorb.com/). or the provided Dockerfile (only for production). The devcontainer and Vagrant setup are for local development only. ## Development Setup diff --git a/bin/setup b/bin/setup index 63988d4ce..7d7fd436c 100755 --- a/bin/setup +++ b/bin/setup @@ -23,10 +23,12 @@ FileUtils.chdir APP_ROOT do # Install JavaScript dependencies system! "yarn install" - # puts "\n== Copying sample files ==" - # unless File.exist?("config/database.yml") - # FileUtils.cp "config/database.yml.sample", "config/database.yml" - # end + puts "\n== Copying sample files ==" + %w[action_mailer.yml content_security_policy.yml database.yml mnemosyne.yml].each do |file| + unless File.exist?("config/#{file}") + FileUtils.cp "config/#{file}.example", "config/#{file}" + end + end puts "\n== Preparing database ==" system! 'bin/rails db:prepare' diff --git a/docs/LOCAL_SETUP.md b/docs/LOCAL_SETUP.md index 7e33d3d43..69c1796e4 100644 --- a/docs/LOCAL_SETUP.md +++ b/docs/LOCAL_SETUP.md @@ -2,7 +2,7 @@ CodeHarbor consists of a web application that is connected to a PostgreSQL database. The following document will guide you through the setup of CodeHarbor with all aforementioned components. -We recommend using the **native setup** as described below. We also prepared a setup with Vagrant using a virtual machine as [described in this guide](./LOCAL_SETUP_VAGRANT.md). However, the Vagrant setup might be outdated and is not actively maintained (PRs are welcome though!) +We recommend using the **native setup** as described below or the **devcontainer setup** as [described in this guide](./LOCAL_SETUP_DEVCONTAINER.md). We also prepared a setup with Vagrant using a virtual machine as [described in this guide](./LOCAL_SETUP_VAGRANT.md). However, the Vagrant setup might be outdated and is not actively maintained (PRs are welcome though!) ## Native setup for CodeHarbor diff --git a/docs/LOCAL_SETUP_DEVCONTAINER.md b/docs/LOCAL_SETUP_DEVCONTAINER.md new file mode 100644 index 000000000..fea0a0ae4 --- /dev/null +++ b/docs/LOCAL_SETUP_DEVCONTAINER.md @@ -0,0 +1,58 @@ +# Devcontainer setup + +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. + +## Local setup + +In order to run the devcontainer locally, you need to have Docker installed on your machine. You can find the installation instructions for your operating system on the [official Docker website](https://docs.docker.com/get-docker/). Then, you'll need an editor or IDE that supports devcontainers. We recommend [Visual Studio Code](https://code.visualstudio.com/),[RubyMine](https://www.jetbrains.com/ruby/), [IntelliJ IDEA](https://www.jetbrains.com/idea/). + +### Clone the repository: + +You may either clone the repository via SSH (recommended) or HTTPS (hassle-free for read operations). If you haven't set up GitHub with your SSH key, you might follow [their official guide](https://docs.github.com/en/authentication/connecting-to-github-with-ssh). + +**SSH (recommended, requires initial setup):** +```shell +git clone git@github.com:openHPI/codeharbor.git +``` + +**HTTPS (easier for read operations):** +```shell +git clone https://github.com/openHPI/codeharbor.git +``` + +### Open the project in your editor or IDE: + +Open the project in your editor or IDE to get started: + +**Visual Studio Code:** +```shell +code codeharbor +``` + +**RubyMine:** +```shell +rubymine codeharbor +``` + +**IntelliJ IDEA:** +```shell +idea codeharbor +``` + +### Install the recommended extensions: + +When you open the project in an supported editor or IDE, you'll be prompted to install the recommended extension(s) for support with devcontainers. Click on "Install" to install the recommended extensions. + +### Start the devcontainer: + +After you've installed the recommended extension(s), you can start the devcontainer by a simple click. + +**Visual Studio Code:** +Click on the blue "Reopen in Container" button in the bottom right corner of your editor. [More information](https://code.visualstudio.com/docs/devcontainers/tutorial). + +**RubyMine:** / **IntelliJ IDEA:** +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). + +# Start CodeHarbor + +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. diff --git a/spec/support/capybara.rb b/spec/support/capybara.rb index 49c326e68..bebe21ddc 100644 --- a/spec/support/capybara.rb +++ b/spec/support/capybara.rb @@ -16,7 +16,16 @@ config.before(:each, type: :system, js: true) do # Selenium when we need JavaScript - driven_by :selenium, using: :"#{display_mode}#{browser}", &send(:"#{browser}_options") + if ENV['CAPYBARA_SERVER_PORT'] + ActionDispatch::SystemTestCase.served_by host: 'rails-app', port: ENV['CAPYBARA_SERVER_PORT'] + + driven_by :selenium, using: :headless_chrome, options: { + browser: :remote, + url: URI::HTTP.build(host: ENV.fetch('SELENIUM_HOST', nil), port: 4444).to_s, + }, &chrome_options + else + driven_by :selenium, using: :"#{display_mode}#{browser}", &send(:"#{browser}_options") + end end private diff --git a/spec/support/webmock.rb b/spec/support/webmock.rb index 01c89e789..61dff0482 100644 --- a/spec/support/webmock.rb +++ b/spec/support/webmock.rb @@ -1,3 +1,12 @@ # frozen_string_literal: true -WebMock.disable_net_connect!(allow_localhost: true) +allowed_hosts = [] + +# Allow connections to the Selenium server and the Rails app +if ENV['SELENIUM_HOST'] + allowed_hosts << ENV.fetch('SELENIUM_HOST') + # This hostname is defined for devcontainers + allowed_hosts << 'rails-app' +end + +WebMock.disable_net_connect!(allow_localhost: true, allow: allowed_hosts)