diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..a2365c8 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,93 @@ +{ + "customizations": { + "vscode": { + "settings": { + "terminal.integrated.profiles.linux": { "zsh": { "path": "/bin/zsh" } }, + "terminal.integrated.profiles.osx": { "zsh": { "path": "/bin/zsh" } }, + "terminal.integrated.profiles.windows": { "zsh": { "path": "/bin/zsh" } }, + "terminal.integrated.defaultProfile.osx": "zsh", + "terminal.integrated.defaultProfile.linux": "zsh", + "terminal.integrated.defaultProfile.windows": "zsh", + "terminal.integrated.scrollback": 10000 + } + }, + "codespaces": { + "repositories": { + "edx/edx-themes": { + "permissions": "read-all" + } + } + } + }, + "features": { + "ghcr.io/devcontainers/features/sshd:1": { + "version": "latest" + }, + "ghcr.io/rocker-org/devcontainer-features/apt-packages:1": { + "packages": "ripgrep" + } + }, + "containerEnv": { + "DEVSTACK_WORKSPACE": "${containerWorkspaceFolder}/edx-repos" + }, + "updateContentCommand": ".devcontainer/updateContentCommand.sh", + "postCreateCommand": ".devcontainer/postCreateCommand.sh", + "postStartCommand": ".devcontainer/postStartCommand.sh", + "forwardPorts": [ + 1976, 1984, 1990, 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, + 2001, 3001, 3406, 5335, 7474, 8000, 8081, 8734, 8735, 9021, 9201, 9202, + 9301, 9600, 18000, 18010, 18040, 18110, 18120, 18130, 18150, 18160, + 18170, 18270, 18280, 18381, 18400, 18450, 18734, 18760, 18787, 19001, + 27017, 44567 + ], + "portsAttributes": { + "3406": { "label": "mysql80" }, + "27017": { "label": "mongo" }, + "9201": { "label": "elasticsearch710" }, + "9301": { "label": "elasticsearch710" }, + "9202": { "label": "opensearch12" }, + "9600": { "label": "opensearch12" }, + "8081": { "label": "schema-registry" }, + "18000": { "label": "lms" }, + "19876": { "label": "lms (JS test debugging)" }, + "18010": { "label": "studio" }, + "19877": { "label": "studio (JS test debugging)" }, + "44567": { "label": "forum" }, + "5335": { "label": "prospectus" }, + "18381": { "label": "discovery" }, + "18130": { "label": "ecommerce" }, + "18150": { "label": "credentials" }, + "18120": { "label": "edx_notes_api" }, + "2000": { "label": "frontend-app-learning" }, + "1998": { "label": "frontend-app-payment" }, + "18400": { "label": "frontend-app-publisher" }, + "1994": { "label": "frontend-app-gradebook" }, + "1999": { "label": "frontend-app-authn" }, + "18734": { "label": "registrar" }, + "1976": { "label": "frontend-app-program-console" }, + "3001": { "label": "frontend-app-library-authoring" }, + "2001": { "label": "frontend-app-course-authoring" }, + "1997": { "label": "frontend-app-account" }, + "1995": { "label": "frontend-app-profile" }, + "18040": { "label": "xqueue" }, + "7474": { "label": "coursegraph" }, + "18110": { "label": "insights" }, + "19001": { "label": "analyticsapi" }, + "1993": { "label": "frontend-app-ora-grading" }, + "1984": { "label": "frontend-app-communications" }, + "1990": { "label": "frontend-app-learner-record" }, + "18450": { "label": "frontend-app-support-tools" }, + "1996": { "label": "frontend-app-learner-dashboard" }, + "9021": { "label": "kafka" }, + "18787": { "label": "program-intent-engagement" }, + "1991": { "label": "frontend-app-admin-portal" }, + "8734": { "label": "frontend-app-learner-portal-enterprise" }, + "8735": { "label": "frontend-app-enterprise-public-catalog" }, + "18170": { "label": "license-manager" }, + "18160": { "label": "enterprise-catalog" }, + "18270": { "label": "enterprise-access" }, + "18280": { "label": "enterprise-subsidy" }, + "8000": { "label": "paragon-pattern-library" }, + "18760": { "label": "ai-translations" } + } +} diff --git a/.devcontainer/postCreateCommand.sh b/.devcontainer/postCreateCommand.sh new file mode 100755 index 0000000..b7d4e9b --- /dev/null +++ b/.devcontainer/postCreateCommand.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash +# postCreateCommand.sh - Finalize container setup after creation. +# +# This script will contribute to the time it takes to launch a new codespace. + +# Print each command being executed. +set -x + +echo "Invoking $0" + +# Overwrite the default welcome message. +# This is displayed the first time you open a newly created Codespace. +VSCODE_DEVCONTAINERS_CONFIG=/usr/local/etc/vscode-dev-containers +if [[ -d "$VSCODE_DEVCONTAINERS_CONFIG" ]]; then + sudo cp .devcontainer/welcome.txt ${VSCODE_DEVCONTAINERS_CONFIG}/first-run-notice.txt +fi + +# Prepare git auth so that developers can push branches directly from a +# codespaces shell. This step tells git to use auth setup by the GH CLI. +# +# In order for this to actually work, the developer still needs to log into the +# GH CLI from a Codespace terminal using `gh auth login`. That step is +# interactive and opens a browser, so cannot be part of this script. +gh auth setup-git diff --git a/.devcontainer/postStartCommand.sh b/.devcontainer/postStartCommand.sh new file mode 100755 index 0000000..53b7781 --- /dev/null +++ b/.devcontainer/postStartCommand.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash +# postStartCommand.sh - Run each time the codespace is successfully started. +# +# This script contributes the time it takes to start the codespace _every day_. + +# Print each command being executed. +set -x + +echo "Invoking $0" + +# `gh auth login` generates SSH keys under the home directory, but that part of +# the filesystem is ephemeral. Make a decent effort to store the keys in a +# persistent mount, and recover the keys if necessary. +if ls -d ~/.ssh/id_*; then + # Backup user-generated ~/.ssh folder if keys are present. + rsync -avh ~/.ssh/ /workspaces/.ssh-backup/ +elif [[ -d /workspaces/.ssh-backup ]]; then + # Recover user-generated ~/.ssh folder if absent and a backup exists. + rsync -avh /workspaces/.ssh-backup/ ~/.ssh/ +fi +# No action is taken if neither ~/.ssh nor /workspaces/.ssh-backup exists. diff --git a/.devcontainer/updateContentCommand.sh b/.devcontainer/updateContentCommand.sh new file mode 100755 index 0000000..1f05e30 --- /dev/null +++ b/.devcontainer/updateContentCommand.sh @@ -0,0 +1,81 @@ +#!/usr/bin/env bash +# updateContentCommand.sh - Finalize container setup after creation. +# +# The result of these commands are cached in pre-built codespaces and will +# not contribute to any developer delay. When new codespaces are pre-built +# behind the scenes, this script runs, so it'll probably run weekly. + +# Print each command being executed. +set -x + +echo "Invoking $0" + +# Set zsh as the default shell when SSHing into this codespace (has no impact +# on VS Code terminals). +sudo chsh -s /bin/zsh ${USER} + +# Add github.com to ssh known hosts to avoid crashing the build with a prompt. +mkdir -p ~/.ssh +ssh-keyscan -H github.com >> ~/.ssh/known_hosts + +# Checkout all edx repos using https because at this point the developer has +# not yet authed via the GH CLI. Later we'll, configure each repo to use ssh. +mkdir -p "$DEVSTACK_WORKSPACE" +mkdir -p "$DEVSTACK_WORKSPACE/src" +SHALLOW_CLONE=1 make dev.clone.https + +# Provision the core app databases. +make dev.provision +# Provision the enterprise app databases. +make dev.provision.license-manager+enterprise-catalog+enterprise-access+enterprise-subsidy + +# Make sure pyenv & pyenv-virtualenv are installed, updated, and configured +# correctly for zsh shells. +export PYENV_ROOT="/workspaces/.pyenv" +# Idempotently install or update pyenv. +if [[ -d ${PYENV_ROOT}/bin ]] +then (cd ${PYENV_ROOT}; git pull) +else GIT_TERMINAL_PROMPT=0 git clone https://github.com/pyenv/pyenv.git ${PYENV_ROOT} +fi +# Idempotently install or update pyenv-virtualenv. +if [[ -d ${PYENV_ROOT}/plugins/pyenv-virtualenv/bin ]] +then (cd ${PYENV_ROOT}/plugins/pyenv-virtualenv; git pull) +else GIT_TERMINAL_PROMPT=0 git clone https://github.com/pyenv/pyenv-virtualenv.git ${PYENV_ROOT}/plugins/pyenv-virtualenv +fi +# Configure/enable pyenv for zsh. +( +cat < ~/.oh-my-zsh/custom/edx-devstack.zsh +# Enable pyenv for this bash script too. +export PATH="$PYENV_ROOT/bin:$PATH" +eval "$(pyenv init - bash)" +eval "$(pyenv virtualenv-init - bash)" + +# Install a decent long-term python version. +PYTHON_VERSION=3.12 +pyenv install --skip-existing $PYTHON_VERSION + +# Find all repos and loop over them: +repo_dirs=( $(find $DEVSTACK_WORKSPACE -mindepth 1 -maxdepth 3 -type d -name .git) ) +repo_dirs=( ${repo_dirs[@]%/.git} ) +for repo_dir in ${repo_dirs[@]}; do + pushd $repo_dir + + # Produce a human-readable virtualenv name. + virtualenv_name="${repo_dir#$DEVSTACK_WORKSPACE/}" + virtualenv_name="${virtualenv_name//\//_}" + + # Set up all repos with virtualenvs. + pyenv virtualenv $PYTHON_VERSION $virtualenv_name + pyenv local $virtualenv_name + + # Configure all repo clones to use SSH instead of HTTPS. + sed -i 's/https:\/\/github.com\//git@github.com:/g' .git/config + + popd +done diff --git a/.devcontainer/welcome.txt b/.devcontainer/welcome.txt new file mode 100644 index 0000000..22fecc5 --- /dev/null +++ b/.devcontainer/welcome.txt @@ -0,0 +1,37 @@ +👋 Welcome to 2U Devstack for Open edX Platform in GitHub Codespaces! + +This pre-built codespace has virtualenvs configured, repositories cloned, and +databases provisioned. There's just a few more things for you to do... + +Initial Setup +============= + +1. Authenticate with github from this new codespace: + + GITHUB_TOKEN= gh auth login --hostname github.com --git-protocol ssh + +2. Navigate to your new ssh key in GitHub settings and configure SSO support: + + https://github.com/settings/keys + +3. Connect to this codespace using VS Code with the Github Codespaces extension: + + https://marketplace.visualstudio.com/items/?itemName=GitHub.codespaces + +Usage +===== + +Start your day by connecting to this workspace from VS Code and start up +services from a terminal: + + make dev.up + +Important directories: + +* /workspaces/devstack - This is the main devstack repository. +* /workspaces/devstack/edx-repos/* - Individual edx service repository clones. + +More Info +========= + +* https://2u-internal.atlassian.net/wiki/spaces/SOL/pages/2003370007/Devstack+on+Codespaces+Guide diff --git a/.gitignore b/.gitignore index b6f9c11..4172eb1 100644 --- a/.gitignore +++ b/.gitignore @@ -107,4 +107,7 @@ local.mk options.local.mk # emacs -*~ \ No newline at end of file +*~ + +# GitHub Codespaces destination path for repo clones +edx-repos/