diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..b0e9158 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,34 @@ +# Docusaurus fails a build on a sidebar entry with no page, but publishes a page +# with no sidebar entry and says nothing. Seven instructor pages sat live and +# unreachable that way, including the two that set expectations honestly. + +name: CI + +on: + pull_request: + push: + branches: [main] + workflow_dispatch: + +permissions: + contents: read + +jobs: + structure: + name: Pages are reachable and links resolve + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: ./scripts/check-docs.sh + + build: + name: Site builds + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 20 + cache: npm + - run: npm ci + - run: npm run build diff --git a/docs/admins/install/adding-an-installation.md b/docs/admins/install/adding-an-installation.md new file mode 100644 index 0000000..8ce6efa --- /dev/null +++ b/docs/admins/install/adding-an-installation.md @@ -0,0 +1,100 @@ +--- +title: Adding an Installation +description: Standing up a new EduIDE installation for a course, department or university. +--- + +# Adding an Installation + +An installation is one namespace on one cluster, with its own hostnames, +branding and identity provider. Adding one is a file, a GitHub Environment and +an approval — not a bespoke deployment. + +## 1. Describe it + +Two files under `environments//` in the deployment repository. They are +split by who reads them: `env.yaml` configures the **deploy** and Helm never +sees it; `values.yaml` configures the **chart** and the workflow never +interprets it. + +`env.yaml` is deploy metadata only: + +```yaml +apiVersion: eduide.dev/v1 +kind: Environment +metadata: + name: bonn + displayName: EduIDE Bonn + tier: production # test | staging | production +spec: + cluster: eduide # must match a file in clusters/ + namespace: eduide-bonn # every namespace carries the eduide- prefix + platform: + chartVersion: 2.0.0 + channel: release # release | main +``` + +`values.yaml` is a plain Helm values file: hosts, Gateway `parentRefs`, Keycloak +and branding. Nothing else — image tags, app definitions, the preload list and +the storage class are all derived or come from the cluster. + +## 2. Create the GitHub Environment + +Named exactly as the directory, holding: + +| Secret | What | +|---|---| +| `KUBECONFIG` | the cluster's kubeconfig | +| `THEIA_KEYCLOAK_COOKIE_SECRET` | `dd if=/dev/urandom bs=32 count=1 \| base64 \| tr -d -- '\n' \| tr -- '+/' '-_'` | + +The admin API token is a repository secret and is inherited. + +Add required reviewers for anything `tier: production` or `staging`. **Do not** +add them to an environment that deploys automatically — the approval gate blocks +the automation outright and the run waits forever. + +## 3. Bootstrap the cluster + +``` +Actions -> Bootstrap cluster -> cluster: , dry_run: true +``` + +This derives the Gateway's listeners, the certificate's hostnames and the +monitored namespaces from every environment that claims the cluster. Adding an +installation therefore needs no second file edited — and cannot end up with a +certificate that omits it, which is exactly how one environment ran for six +months on a certificate covering only its neighbours. + +Read the diff, then run it again with `dry_run: false`. + +## 4. Outside the repositories + +- **DNS** for all four hostnames. +- **Keycloak**: a client matching `clientId`, with redirect URIs for all four + hosts. A wrong realm or client fails at login, not at deploy, so nothing in CI + catches it. +- **The webview wildcard certificate**, which cert-manager cannot issue over + HTTP-01. It goes in the cluster's bootstrap environment as + `THEIA_WILDCARD_CERTIFICATE_CERT` and `_KEY`. + +## 5. Deploy + +``` +Actions -> Deploy (dispatch) -> environment: +``` + +The deploy asserts which cluster it reached before touching anything, shows a +`helm diff` before applying, runs `--wait --atomic`, and prints a summary read +back from the cluster rather than echoed from its inputs. + +## A note on identity + +An installation with no identity provider configured yet must say so explicitly +with `keycloak.allowUnauthenticated: true`. The chart otherwise refuses to +render. + +That flag exists because the oauth2-proxy configuration is emitted regardless of +whether Keycloak is enabled — the operator mounts it into every session pod by +literal name, so it cannot be conditional. Left at the chart's defaults it points +the proxy at a host that does not exist, and sessions fail at the proxy rather +than running unauthenticated. That is the worst of both outcomes, so the chart +makes you choose deliberately. diff --git a/docs/admins/install/installing.md b/docs/admins/install/installing.md new file mode 100644 index 0000000..f785608 --- /dev/null +++ b/docs/admins/install/installing.md @@ -0,0 +1,147 @@ +--- +title: Installing EduIDE +description: Installing the platform on a cluster from the published charts. +--- + +# Installing EduIDE + +EduIDE ships as two Helm charts, published as OCI artifacts to +`ghcr.io/eduide/charts`. They always carry the same version, and that version +is the platform version. + +| Chart | Installed | Owns | +|---|---|---| +| `eduide-cluster` | once per **cluster** | CRDs, the conversion webhook, ClusterRoles, cert-manager issuers, the shared Gateway, PodMonitors and dashboards | +| `eduide` | once per **environment** | operator, REST service, landing page, routes, app definitions, image preloading | + +The split exists because the two halves have different cardinality. CRDs and a +Gateway must exist once on a cluster; a tenant install exists once per namespace, +and there may be several on the same cluster. Installing cluster-scoped +resources from every tenant deploy is what previously made concurrent deploys +race each other. + +## Prerequisites + +The cluster must already have: + +- **cert-manager**, for the conversion webhook's certificate and for issuing + hostname certificates +- **Gateway API CRDs** and a Gateway controller. EduIDE is tested with Envoy + Gateway +- a **storage class** for session volumes + +## Cluster half + +These two commands are the manual path. Day to day, `bootstrap-cluster.yml` and +`deploy.yml` run them for you — see +[Provisioning](../platform/provisioning.md). + +```bash +helm install eduide-cluster oci://ghcr.io/eduide/charts/eduide-cluster \ + --version 2.0.0 -n eduide-system --create-namespace \ + -f cluster-values.yaml +``` + +`cluster-values.yaml` supplies the Gateway's listeners and the certificate +names. In the TUM installations this file is not written by hand — the +`Bootstrap cluster` workflow derives it from the environment manifests, so +adding an environment does not mean remembering to edit a second file. + +## Tenant half + +```bash +helm install eduide oci://ghcr.io/eduide/charts/eduide \ + --version 2.0.0 -n eduide-test1 --create-namespace \ + -f values.yaml -f secrets.yaml +``` + +The chart refuses to install if the cluster chart is absent, rather than letting +the operator crash-loop on a missing CRD. + +## What one version pins + +A bare install with no overrides pins every image. Nothing floats. + +| Value | Source repository | Default | +|---|---|---| +| `versions.ide` | EduIDE — the IDE images | empty, meaning the chart's `appVersion` | +| `versions.cloud` | EduIDE-Cloud — operator and REST service | set by the release | +| `versions.landingPage` | EduIDE-Landing-Page | set by the release | + +They are separate because the three repositories release on different cadences, +and a one-line landing-page fix should not rebuild fifteen multi-gigabyte IDE +images. + +**Never set a single tag for everything.** A pull request only builds the images +of the repository it came from, so pointing all three at `pr-451` puts most of +the namespace into `ImagePullBackOff`. + +## Minimum values + +```yaml +hosts: + configuration: + baseHost: eduide.example.edu + landing: eduide + service: service.eduide + instance: instance.eduide + allWildcardInstances: ["*.webview."] + +keycloak: + enable: true + authUrl: https://sso.example.edu/ + realm: your-realm + clientId: eduide + +gateway: + parentRefs: + - { name: theia-shared-gateway, namespace: eduide-system, sectionName: prod-landing } + - { name: theia-shared-gateway, namespace: eduide-system, sectionName: prod-service } + - { name: theia-shared-gateway, namespace: eduide-system, sectionName: prod-instances } + - { name: theia-shared-gateway, namespace: eduide-system, sectionName: prod-webview } +``` + +Secrets — the Keycloak cookie secret and the admin API token — go in a second +values file, never on the command line. `--set` puts them in the process list +and in Actions debug logs. + +**In normal operation you do not write that file.** The deploy workflow +generates it on the runner from the environment's GitHub Environment secrets and +it never reaches the repository. The commands on this page are for a first +install on a new cluster, or for manual intervention when the pipeline is +unavailable — in which case write `secrets.yaml` yourself, keep it out of git, +and delete it afterwards. Everything non-secret belongs in `values.yaml`. + +## Four hostnames, not one + +Each installation serves: + +``` + the landing page +service. the REST service +instance. session ingress +*.webview.instance. per-session webviews +``` + +All four need DNS and all four need to be on a certificate. The webview host is +two labels below the instance host, so a wildcard covering the others does not +cover it — it needs its own certificate, and because it is a wildcard, +cert-manager cannot issue it over HTTP-01. + +**A certificate that omits a hostname fails silently.** The Gateway reports the +listener healthy — Gateway API never compares a certificate's names against a +listener's hostname — so the first symptom is a browser warning, and the second +is the landing page being unable to call its own REST service, because the +browser blocks that cross-origin request over an invalid certificate. + +## Verifying + +```bash +kubectl -n get deploy # operator, service, landing-page, garbage-collector +kubectl -n get appdefinitions.theia.cloud +kubectl -n get httproute -o wide +curl -sI https:/// # 200, and TLS must validate without -k +``` + +Then start a real session from the landing page. Everything above can be healthy +while sessions do not start. diff --git a/docs/admins/maintenance/release-policy.md b/docs/admins/maintenance/release-policy.md new file mode 100644 index 0000000..9ee3c38 --- /dev/null +++ b/docs/admins/maintenance/release-policy.md @@ -0,0 +1,65 @@ +--- +title: Release and Version Policy +description: What a version number means here, and how a release is cut. +--- + +# Release and Version Policy + +## One version, one meaning + +| Thing | Form | Example | +|---|---|---| +| git tag | `vX.Y.Z` | `v2.0.0` | +| chart `version` | `X.Y.Z` | `2.0.0` | +| image tag | `X.Y.Z` | `1.2.0` | +| chart `appVersion` | the EduIDE IDE image version | `1.2.0` | + +The chart version is the **platform** version and is what an installation pins. +`appVersion` is the tag of the IDE images, so a chart states exactly which IDEs +it runs. + +The operator, REST service and landing page carry their own versions in +`versions.cloud` and `versions.landingPage`, because they release on a different +cadence. A one-line landing-page fix should not rebuild fifteen multi-gigabyte +IDE images. + +Three spellings of a git tag existed historically — `1.1.0`, `v1.1.0` and +`v.1.1.1` — which is why nothing could reliably answer "which release produced +this image". A shared CI check now rejects anything that is not `vX.Y.Z`. Old +tags are not retagged. + +## Cutting a release + +The release train in EduIDE-Helm does it, and defaults to `dry_run: true`. + +1. **Validate** the version is semver and the tag is unused. +2. **Build every component at that tag** — but tag nothing yet. Building fifteen + large images is the flakiest step in the pipeline; tagging afterwards means a + flake costs a re-run rather than stranding immutable tags on repositories + whose images were never published. +3. **Verify every expected image exists**, for both architectures. The IDE image + list is read from EduIDE's build matrix at run time, not kept by hand — a + hand-kept copy went stale within days and would have let a release verify ten + of twelve images and pass. +4. **Only now tag and release** the component repositories. +5. **Publish both charts** at the same version. +6. **Open a bump pull request** against each production installation. Production + is never deployed automatically. + +## Channels + +An installation is `release` or `main`. + +- `release` pins whatever its values file says. Nothing that happens on `main` + can move a production image. +- `main` resolves an immutable `latest-` tag. Never a floating tag: with a + floating tag the pod template does not change between upgrades, so Helm sees + no difference, reports success without pulling, and `--atomic` has nothing to + roll back. + +## Upgrading an installation + +Change `chartVersion` in that environment's `env.yaml` and open a pull request. +CI renders the change; the diff shows what will happen before anyone approves +it. Production environments require a reviewer on the GitHub Environment, so the +approval is recorded on the run. diff --git a/docs/admins/maintenance/rollback.md b/docs/admins/maintenance/rollback.md new file mode 100644 index 0000000..712213a --- /dev/null +++ b/docs/admins/maintenance/rollback.md @@ -0,0 +1,55 @@ +--- +title: Rollback +description: Undoing a deploy that succeeded but behaves badly. +--- + +# Rollback + +Deploys run with `--wait --atomic`, so a deploy that **fails** already rolls +itself back. This page is for the other case: the deploy succeeded, the pods are +healthy, and the release is wrong. + +## Rolling back + +``` +Actions -> Rollback -> environment: +``` + +or directly: + +```bash +helm rollback eduide -n --wait +``` + +Helm restores the previous revision. `helm history eduide -n ` shows +what you are going back to. + +## What a rollback does not touch + +**Sessions, workspaces and their volumes survive.** They are custom resources and +PersistentVolumeClaims that the release does not own the lifecycle of, so a +rollback does not disturb anyone's work. A student in a session will usually not +notice. + +**CRDs are not rolled back.** They belong to `eduide-cluster`, not to the tenant +release. A rollback of the tenant chart cannot undo a CRD change. + +That second point is the important one. If a release changed a CRD's stored +version, rolling back the tenant chart leaves the new CRD in place with an older +operator that may not understand it. **A CRD-breaking change needs a major +version bump and a written runbook, not a rollback.** + +## When rollback is the wrong tool + +| Situation | Do this instead | +|---|---| +| The images are wrong but the chart is fine | Redeploy with the correct `versions.*` | +| A certificate does not cover a hostname | Fix the certificate; the release is not the problem | +| A CRD changed incompatibly | Follow the release's runbook. Rolling back the tenant chart will not help | +| The cluster chart is wrong | Roll back `eduide-cluster` in `eduide-system`, and understand that this affects **every** installation on the cluster | + +## Afterwards + +A rollback is a statement that the deployed version was wrong. Say so somewhere +durable — an issue on the release — or the same version gets deployed again next +week. diff --git a/docs/admins/platform/provisioning.md b/docs/admins/platform/provisioning.md index f8a6bbc..ce87268 100644 --- a/docs/admins/platform/provisioning.md +++ b/docs/admins/platform/provisioning.md @@ -9,17 +9,29 @@ This page covers the steps required to bootstrap a new EduIDE environment. It is ## How deployments work -All EduIDE environments are deployed through GitHub Actions pipelines defined in the deployment repository. The pipelines run `helm upgrade --install` for each chart with the environment-specific values files. You do not run Helm commands manually in normal operation — you trigger or configure the pipeline. +All EduIDE environments are deployed through GitHub Actions pipelines defined in +the deployment repository. You do not run Helm commands manually in normal +operation — you trigger or configure the pipeline. For a first install on a new +cluster, or emergency manual intervention, see +[Installing EduIDE](../install/installing.md). -The three deployment workflows are: - -| Workflow | Trigger | Approval required | +| Workflow | Trigger | Approval | |---|---|---| -| `deploy-production.yml` | Manual dispatch | Yes | -| `deploy-staging.yml` | Push to main | No | -| `deploy-pr.yml` | PR push | Yes | - -For emergency manual intervention (e.g., when a pipeline is unavailable), the underlying Helm commands are documented in the steps below. +| `deploy.yml` | Reusable; called by the others | Inherited from the environment | +| `deploy-e2e.yml` | Automatic, follows `main` | **None** — an approval gate would block it forever | +| `deploy-staging.yml` | Manual dispatch | Yes | +| `deploy-dispatch.yml` | Manual dispatch, any environment | Yes for `production` and `staging` | +| `deploy-comment.yml` | `/deploy ` on a pull request | Yes for `production` and `staging` | +| `bootstrap-cluster.yml` | Manual dispatch, once per cluster | Yes | +| `rollback.yml` | Manual dispatch | Yes | + +`e2e-test` is the environment that follows `main` and is tested automatically; +`staging` is the manual one, where a human puts something to look at before it +goes near production. Approval is a property of the GitHub Environment, not of +the workflow — which is why `e2e-test` deliberately has no required reviewers. + +The pre-restructure workflows `deploy-production.yml`, `deploy-pr.yml` and +`deploy-theia.yml` no longer exist. ## Prerequisites diff --git a/docs/contributions/README.md b/docs/contributions/README.md deleted file mode 100644 index 6de38f4..0000000 --- a/docs/contributions/README.md +++ /dev/null @@ -1,55 +0,0 @@ ---- -title: Student Contributions -sidebar_label: Overview -sidebar_position: 1 ---- - -# Student Contributions to EduIDE - -This section showcases the individual contributions of team members working on the EduIDE ecosystem. Each student documents their thesis work and other significant contributions to the project. - -## Contributing Your Documentation - -To add your own contribution page: - -1. **Copy the template**: Use `_template.md` in this directory as your starting point -2. **Name your file**: Use your name in kebab-case (e.g., `john-doe.md`) -3. **Fill in your information**: Replace all placeholder text with your actual contributions -4. **Add to sidebar**: Your page will automatically appear in the Contributions section - -## What to Include - -### Thesis Work -- Clear title and overview of your research -- Key contributions and achievements -- Technologies and tools you used -- Repositories where your work lives -- Measurable results and impact - -### Other Contributions -- Bug fixes and improvements -- Documentation and guides -- Code reviews and collaboration -- Infrastructure and tooling enhancements - -## Template Structure - -The template includes sections for: - -- **Thesis**: Your main research work and findings -- **Other Contributions**: Additional valuable work beyond your thesis -- **Documentation & Resources**: Guides, presentations, and materials you've created -- **Timeline**: A chronological view of your work -- **Acknowledgments**: Recognition of those who helped you - -## Tips for Good Documentation - -- **Be specific**: Include links to PRs, issues, and commits where possible -- **Show impact**: Explain not just what you did, but why it mattered -- **Use visuals**: Add diagrams, screenshots, or graphs if they help tell your story -- **Keep it updated**: Come back and update your page as you make new contributions -- **Link to projects**: Reference the main project pages in the Projects section - -## Questions? - -If you need help with your contribution page, reach out to the team or check existing contribution pages for examples. diff --git a/docs/contributions/_template.md b/docs/contributions/_template.md deleted file mode 100644 index 13802d9..0000000 --- a/docs/contributions/_template.md +++ /dev/null @@ -1,77 +0,0 @@ ---- -title: [Your Name] -sidebar_label: [Your Name] ---- - -# [Your Name] - Contributions to EduIDE - -## Thesis - -### Title -[Your thesis title here] - -### Overview -[Brief overview of your thesis work - 2-3 paragraphs describing the main research question, approach, and goals] - -### Key Contributions -- [Main contribution 1] -- [Main contribution 2] -- [Main contribution 3] - -### Technologies Used -- [Technology 1] -- [Technology 2] -- [Technology 3] - -### Repositories -- [Repository name](link) - [Brief description of your work in this repo] -- [Repository name](link) - [Brief description of your work in this repo] - -### Results & Impact -[Describe the outcomes of your thesis work - what was achieved, what impact it had on the EduIDE ecosystem] - ---- - -## Other Noteworthy Contributions - -### [Contribution Title 1] -**Repository**: [Repository link] -**Description**: [Detailed description of this contribution] -**Impact**: [What problem did this solve or what improvement did it bring] - -### [Contribution Title 2] -**Repository**: [Repository link] -**Description**: [Detailed description of this contribution] -**Impact**: [What problem did this solve or what improvement did it bring] - -### [Contribution Title 3] -**Repository**: [Repository link] -**Description**: [Detailed description of this contribution] -**Impact**: [What problem did this solve or what improvement did it bring] - ---- - -## Documentation & Resources - -### Written Documentation -- [Document/Guide title](link) - [Brief description] - -### Presentations & Demos -- [Presentation title](link) - [Brief description] - -### Related Issues & Pull Requests -- [#123 Issue/PR title](link) - [Brief description] - ---- - -## Timeline - -| Period | Activity | -|--------|----------| -| [Month Year - Month Year] | [Activity description] | -| [Month Year - Month Year] | [Activity description] | - ---- - -## Acknowledgments -[Optional: Acknowledge collaborators, mentors, or resources that were particularly helpful] diff --git a/docs/instructor/course-operations/cohort-management.md b/docs/instructor/course-operations/cohort-management.md index b375f24..9694373 100644 --- a/docs/instructor/course-operations/cohort-management.md +++ b/docs/instructor/course-operations/cohort-management.md @@ -1,15 +1,80 @@ --- title: Cohort Management -description: Mock cohort management guide for instructors. +description: How the platform behaves with a whole cohort on it at once, and what that means for scheduling. --- # Cohort Management -This mock page represents the workflow for managing groups, enrollment, and access policies during a term. +There is no cohort object in EduIDE. Students are not enrolled, grouped or +managed here — that all lives in Artemis. What this page is really about is +capacity: what happens when a lot of people use the platform at the same +moment, and how to schedule around it. -## Typical tasks +## The one number that matters: concurrent starts -- Review enrollment sync status -- Assign tutorial groups -- Adjust access for late registrations -- Coordinate teaching assistants +Steady-state load is easy. The hard case is 200 students clicking **Open online +IDE** within the same five minutes, because each one needs a container +scheduled, a volume attached and an IDE booted. + +The platform mitigates this in two ways, both of which have limits: + +**Pre-pulled images.** Every node keeps the IDE images on local disk, so +starting a session does not download several gigabytes first. This is why a +newly added language is slow for the first students to use it — the image has to +reach every node before it helps. + +**Warm sessions.** A configurable number of sessions can be kept running and +idle, so the first students to arrive get one immediately. Once the warm pool is +exhausted, everyone after that waits for a cold start. + +The size of that pool is set per environment by the platform team. If you know a +lab will start at a fixed time, tell them in advance — it can be raised for the +day. + +## Practical scheduling + +- **Stagger where you can.** Two labs of 100 at different hours cost far less + than one of 200. +- **Ask students to start the IDE a few minutes before the exercise**, not at + the moment you begin talking. +- **Expect the first session of the day to be slower.** Idle sessions are + reclaimed overnight. +- **Do not have everyone reload when it feels slow.** A reload abandons the + session that was starting and asks for another. + +## Session limits + +Each student may hold a small number of concurrent sessions — the exact number +is configured per environment. This exists to stop one person accumulating +sessions across devices and browser tabs and exhausting capacity for everyone. + +If a student cannot start a session and is told they have too many, the fix is +to close the ones they have forgotten about, not to raise the limit. + +## Sessions end; workspaces do not + +An idle session is shut down after a timeout. The **workspace** — the student's +files — survives, and reopening the exercise gives it back. + +This distinction matters for how you talk to students: + +- "Your session was closed" means the running IDE stopped. Reopen it. +- Work that was **committed and pushed** is safe regardless. +- Work that was only saved in the editor lives in the workspace volume, which + persists — but this is not a backup, and it is not somewhere to keep the only + copy of anything that matters. + +Tell students to commit and push at the end of every session. That is also what +Artemis grades, so the habit is the same one the course wants anyway. + +## Exams and assessed labs + +Treat a high-stakes session as an operational event, not a normal day: + +- Warn the platform team well in advance, with the exact time and headcount. +- Have a fallback that does not need the platform. If the network between the + lecture theatre and the cluster fails, no amount of capacity helps. +- Do not schedule the first-ever use of a new language image for an exam. + +See [Limitations](../limitations/honest-limitations.md) for what the platform +does not promise. diff --git a/docs/instructor/course-operations/course-setup.md b/docs/instructor/course-operations/course-setup.md index 1d5467e..5628876 100644 --- a/docs/instructor/course-operations/course-setup.md +++ b/docs/instructor/course-operations/course-setup.md @@ -1,15 +1,67 @@ --- title: Course Setup -description: Mock course setup guide for instructors. +description: What to arrange before your first session, and who arranges it. --- # Course Setup -This placeholder page will eventually describe how instructors create a course shell, configure exercises, and prepare cohorts. +Most of the setup for an EduIDE course is not done by you. The platform team +provisions the environment; your work is deciding what students need in it and +making sure the Artemis side lines up. -## Mock setup stages +## What the platform team needs from you -1. Create the course workspace -2. Import assignments and starter material -3. Configure grading and release dates -4. Invite teaching staff +Ask for these before the semester starts, not in the first week. + +| They need to know | Because | +|---|---| +| Which languages your exercises use | Each one is a separate IDE image that has to be offered and pre-pulled onto the cluster nodes | +| Roughly how many students, and when they will all arrive at once | Determines how many sessions are kept warm. A lab where 200 students start within ten minutes behaves very differently from steady use | +| Whether you need a starter template | Template images ship skeleton projects and a build-system choice. Without one, students start in an empty workspace | +| Which Artemis course this belongs to | The integration is per-course | + +Lead time for a new language image is realistically weeks, not days. If your +exercises need something not already offered, raise it early. + +## What is already available + +The platform offers a fixed set of environments, each corresponding to a +language image. Some are plain — an empty workspace with the toolchain +installed — and some ship starter templates with a build-system choice, such as +Maven or Gradle for Java, Make or Bazel for C. + +Ask the platform team which are enabled for your installation. The list differs +between installations, and building an image does not automatically make it +available. + +## What you set up yourself + +**In Artemis.** Create the programming exercise as usual. The EduIDE +integration is a property of the exercise's repository, so nothing separate has +to be configured per student. + +**Test the whole path yourself, as a student would.** Open your own exercise +from Artemis, let the IDE start, make a change, commit and push, and confirm the +result appears in Artemis. Do this before you tell 200 people to do it. The +first start on a cold environment is much slower than later ones, and it is +better that you discover that than a lecture theatre does. + +**Decide what "getting stuck" looks like.** Students will hit problems the +platform cannot solve for them — a push rejected because they edited the wrong +branch, a session that timed out overnight. Decide in advance who they ask. + +## Before the first lab + +- Confirm with the platform team that your environment is up and that the + languages you need are offered. +- Run through one exercise end to end yourself. +- Tell students that the first start is slow and the second is not, so they do + not all reload in the first minute and make it worse. +- Read [Limitations](../limitations/honest-limitations.md), and set expectations + from it rather than discovering them live. + +## What this page does not cover + +Grading, release dates, exercise import and teaching-staff invitations are all +Artemis features and are documented there. EduIDE is the environment the +exercise opens in; it does not manage the course. diff --git a/docs/instructor/teaching/feedback-rhythm.md b/docs/instructor/teaching/feedback-rhythm.md index b550e8d..edbed46 100644 --- a/docs/instructor/teaching/feedback-rhythm.md +++ b/docs/instructor/teaching/feedback-rhythm.md @@ -1,15 +1,68 @@ --- title: Feedback Rhythm -description: Mock feedback guidance for instructors. +description: Where feedback actually comes from, and what EduIDE changes about it. --- # Feedback Rhythm -This placeholder page can later document consistent expectations for turnaround times, review channels, and office-hour support. +EduIDE does not grade anything and does not give feedback. Artemis does. What +EduIDE changes is how quickly a student can act on the feedback they get, and +that is worth designing for. -## Mock guidance +## The loop -- Publish weekly feedback windows -- Use reusable rubric comments -- Separate conceptual and technical feedback -- Track unresolved learner blockers +```text +edit in EduIDE -> commit and push -> Artemis builds and tests -> result + ^ | + +----------------------------------------------------------------+ +``` + +The push is the only handoff. Everything before it is local to the workspace and +invisible to Artemis; everything after it is Artemis's business. + +This has one practical consequence that dominates all others: **students who do +not push get no feedback.** Not delayed feedback — none. The most common cause +of "the system didn't tell me anything" is work that never left the workspace. + +## What to say in week one + +- Commit and push at the end of every session, even if the work is unfinished. +- Pushing is how you ask for feedback. It is not a submission ceremony. +- The IDE keeps your files between sessions, but only pushed work reaches + Artemis. + +Say it again in week two. + +## What EduIDE makes easier + +**No environment excuse.** Everyone has the same toolchain, so "it works on my +machine" stops being a category of feedback you have to give. The failure a +student sees locally is the failure the grader sees. + +**A shorter path from feedback to fix.** The IDE is already open on the exercise; +acting on a test failure does not require rebuilding a local setup first. In a +lab, that can turn a week-long loop into a ten-minute one. + +**You can look at exactly what they have.** Because the environment is uniform, +"send me a screenshot" is usually enough to diagnose. There is no hidden local +state. + +## What it does not change + +- **Test quality.** Feedback is only as good as the exercise's tests. EduIDE + makes it faster to receive, not better. +- **Turnaround.** Build queues and test duration are Artemis's, unchanged. +- **Manual review.** If your course gives written feedback, that workload is + the same. + +## A rhythm that works + +| When | What | +|---|---| +| During a lab | Push early and often; treat the first push as a smoke test, not a submission | +| End of every session | Push, unconditionally | +| Between sessions | Students act on automated results themselves | +| Weekly | You look at aggregate results, not individuals — the common failure across a cohort is usually an exercise problem, not thirty independent student problems | + +That last row is the one people skip. When most of a cohort fails the same test, +the exercise is telling you something. diff --git a/docs/instructor/teaching/live-session-playbook.md b/docs/instructor/teaching/live-session-playbook.md index 01d0923..16909f0 100644 --- a/docs/instructor/teaching/live-session-playbook.md +++ b/docs/instructor/teaching/live-session-playbook.md @@ -1,15 +1,72 @@ --- title: Live Session Playbook -description: Mock teaching playbook for live sessions. +description: Running a lab on EduIDE, and what to do when something goes wrong in front of everyone. --- # Live Session Playbook -This page is reserved for high-signal guidance instructors need during active labs, tutorials, and workshops. +What to do in the room, in the order you will need it. -## Mock playbook +## Before -- Open the session dashboard before class starts -- Monitor stuck workspaces and failed launches -- Broadcast clarifications to all learners -- Escalate systemic issues to admins +- Open the exercise yourself, from Artemis, on the room's network. Not at home + the night before — the network between this room and the cluster is part of + the system. +- Have the exercise URL ready to paste. Do not make 200 people navigate. +- Know who to contact if the platform is down, and have that open already. + +## Starting everyone at once + +Say this, in this order: + +1. Open the exercise in Artemis and click **Open online IDE**. +2. It will take a minute or two the first time. That is normal. +3. **Do not reload.** Reloading abandons the session that is starting and puts + you at the back of the queue. + +That third point is the one that saves the session. A room full of people +reloading turns a slow start into a much slower one. + +If a student is asked to log in and then lands nowhere, they should complete the +login, go back to the Artemis exercise page, and click **Open online IDE** +again. This is a known first-login quirk, not a failure. + +## During + +**"My terminal is gone" / "the IDE looks frozen."** Reload the browser tab. The +session is server-side; the tab is just a view of it. This is the one time +reloading is the right answer. + +**"I can't push."** Almost always a git problem, not a platform problem — wrong +branch, nothing committed, or a conflict. Treat it as you would in any other +environment. + +**"My session closed."** It timed out from inactivity. Reopening the exercise +gives the workspace back. Files are not lost by a timeout. + +**"I lost my work."** Distinguish immediately: pushed work is in Artemis and is +safe. Unpushed work lives in the workspace volume and is almost certainly still +there when they reopen. Work that was never saved in the editor is gone, exactly +as it would be locally. + +## When it is not one student + +If several people report the same failure at once, stop diagnosing individuals. + +1. Try it yourself. If it fails for you too, it is the platform. +2. Tell the room what you know in one sentence, and give them something to do + that does not need the IDE. +3. Contact the platform team with: which environment, what time it started, and + what the error says. "It's broken" costs a round trip. + +**Have a fallback.** For an assessed session, decide in advance what happens if +the platform is unavailable, and say it out loud at the start so nobody +panics. A browser-based IDE has a hard dependency on the network and the +cluster; that is the trade for not having 200 local setups to debug. + +## After + +- Tell students to commit and push before they leave. That is what Artemis + grades and what survives everything. +- If something went wrong, report it even if it resolved itself. A transient + failure nobody reports is one nobody fixes. diff --git a/docs/intro.md b/docs/intro.md deleted file mode 100644 index af682b4..0000000 --- a/docs/intro.md +++ /dev/null @@ -1,60 +0,0 @@ ---- -sidebar_position: 1 -slug: / ---- - -# Welcome to EduIDE - -**EduIDE** is a scalable, cloud-native educational IDE platform built on [Eclipse Theia](https://theia-ide.org/) and integrated with the [Artemis](https://github.com/ls1intum/Artemis) learning management system. It provides students with powerful, browser-based development environments for programming exercises without requiring local installations. - -## What is EduIDE? - -EduIDE delivers a complete IDE experience directly in the browser, enabling students to: - -- Write, compile, and test code without installing tools locally -- Access consistent development environments across devices -- Benefit from intelligent code completion and language server features -- Work with real-world development tools in a managed, scalable infrastructure - -## Architecture Overview - -The EduIDE ecosystem consists of several interconnected components: - -- **[Theia Deployment](./projects/theia-deployment.md)**: Infrastructure-as-code for deploying and managing Kubernetes clusters -- **[EduIDE](./projects/eduidec.md)**: Custom IDE container images with language support and tooling -- **[Theia LSP Extension](./projects/theia-lsp-extension.md)**: Language server integration for intelligent code features -- **[Theia Shared Cache](./projects/theia-shared-cache.md)**: Distributed caching layer for improved performance -- **[Theia Scale Tests](./projects/theia-scale-tests.md)**: Load testing framework for performance validation - -## Key Features - -### 🚀 Cloud-Native Architecture - -Built on Kubernetes with [Theia Cloud](https://github.com/eclipse-theia/theia-cloud), enabling horizontal scaling and efficient resource management. - -### 🎓 Educational Focus - -Designed specifically for university programming courses with features like automated grading integration, exercise templates, and student workspace isolation. - -### 🔧 Extensible Platform - -Supports multiple programming languages (Java, Python, C, Rust, and more) with customizable IDE blueprints and configurations. - -### 📊 Observability - -Comprehensive monitoring with Prometheus and Grafana dashboards for tracking system health and user activity. - -## Getting Started - -To explore the EduIDE projects, browse the **Projects** section in the sidebar. Each project page includes: - -- An overview of the component's purpose -- Key features and capabilities -- Technical implementation details -- Links to source repositories - -For deployment and infrastructure details, start with the [Theia Deployment](./projects/theia-deployment.md) documentation. - -## Student Contributions - -EduIDE is developed and maintained by a team of dedicated students. Check out the **Contributions** section to learn about individual thesis work and contributions to the ecosystem. Each student documents their research, implementations, and the impact of their work on the platform. diff --git a/scripts/check-docs.sh b/scripts/check-docs.sh new file mode 100755 index 0000000..7ceabc7 --- /dev/null +++ b/scripts/check-docs.sh @@ -0,0 +1,97 @@ +#!/usr/bin/env bash +# Every page must be reachable, and every sidebar entry must exist. +# +# Seven instructor pages were written and never added to a sidebar, so they were +# live on the site but reachable only by guessing the URL. Two of them - +# what-you-cannot-evaluate and honest-limitations - are the most +# credibility-building pages here, and nobody could find either. +# +# Docusaurus does not warn about this. It warns about a sidebar entry with no +# file, but a file with no sidebar entry is silently published and orphaned. + +set -uo pipefail +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +cd "$ROOT" +FAILED=0 + +# plugin docs root : its sidebar file +PLUGINS=( + "docs/developer:sidebarsDeveloper.ts" + "docs/instructor:sidebarsInstructor.ts" + "docs/admins:sidebarsAdmins.ts" + "docs/student:sidebarsStudent.ts" +) + +echo "=== every page is in a sidebar, every sidebar entry has a page ===" +for pair in "${PLUGINS[@]}"; do + base="${pair%%:*}"; sb="${pair##*:}" + [[ -d "$base" ]] || { echo " FAIL $base does not exist"; FAILED=1; continue; } + [[ -f "$sb" ]] || { echo " FAIL $sb does not exist"; FAILED=1; continue; } + + # Both quote styles. A double-quoted id was previously skipped, which made its + # page look orphaned and failed this job for no reason. + # + # `label:` and `type:` values are stripped first, so what remains is document + # ids - including root-level ones like `intro`, which carry no slash and were + # previously exempt from the dangling check entirely. + ids=$(sed -E "s/(label|type)[[:space:]]*:[[:space:]]*('[^']*'|\"[^\"]*\")//g" "$sb" \ + | grep -oE "'[a-zA-Z0-9_./-]+'|\"[a-zA-Z0-9_./-]+\"" \ + | tr -d "'\"" | sort -u) + # -E: BSD sed does not take \? in a basic expression, and silently leaves the + # extension on, which makes every page look orphaned. + files=$(find "$base" \( -name '*.md' -o -name '*.mdx' \) \ + | sed -E "s|^$base/||; s|\.mdx?$||" | sort -u) + + orphans=$(comm -23 <(echo "$files") <(echo "$ids")) + if [[ -n "$orphans" ]]; then + echo " FAIL $base: page(s) in no sidebar, so unreachable except by URL:" + sed 's/^/ /' <<<"$orphans" + FAILED=1 + fi + + # A sidebar id that names no file. Docusaurus fails the build on these, but + # catching it here names the file instead of the plugin. Root-level ids count: + # filtering on '/' let a missing top-level page through silently. + dangling=$(comm -13 <(echo "$files") <(echo "$ids") || true) + if [[ -n "$dangling" ]]; then + echo " FAIL $sb: entries with no page:" + sed 's/^/ /' <<<"$dangling" + FAILED=1 + fi + + [[ -z "$orphans" && -z "$dangling" ]] && \ + echo " PASS $base ($(wc -l <<<"$files" | tr -d ' ') pages)" +done + +echo +echo "=== no page is served by zero plugins ===" +served=$(for pair in "${PLUGINS[@]}"; do find "${pair%%:*}" \( -name '*.md' -o -name '*.mdx' \); done | sort -u) +all=$(find docs \( -name '*.md' -o -name '*.mdx' \) | sort -u) +stray=$(comm -13 <(echo "$served") <(echo "$all")) +if [[ -n "$stray" ]]; then + echo " FAIL under docs/ but served by no plugin, so not published at all:" + sed 's/^/ /' <<<"$stray" + FAILED=1 +else + echo " PASS every page under docs/ belongs to a plugin" +fi + +echo +echo "=== relative links resolve ===" +broken=0 +while IFS= read -r f; do + # ](./x) and ](../x) and ](x.md) - site-absolute and external links are not + # checked here; Docusaurus resolves those itself. + while IFS= read -r link; do + [[ -n "$link" ]] || continue + target="$(dirname "$f")/${link%%#*}" + [[ -e "$target" || -e "${target}.md" || -e "${target}.mdx" ]] && continue + echo " FAIL $f -> $link" + broken=1 + done < <(grep -oE '\]\((\.\.?/[^)]+|[A-Za-z0-9_-]+\.mdx?)\)' "$f" 2>/dev/null | sed 's/^](//; s/)$//') +done < <(find docs -name '*.md' -o -name '*.mdx') +[[ $broken -eq 0 ]] && echo " PASS relative links resolve" || FAILED=1 + +echo +[[ $FAILED -eq 0 ]] && echo "ALL PASS" || echo "SOME FAILED" +exit $FAILED diff --git a/sidebars.ts b/sidebars.ts deleted file mode 100644 index cdecaf6..0000000 --- a/sidebars.ts +++ /dev/null @@ -1,41 +0,0 @@ -import type {SidebarsConfig} from '@docusaurus/plugin-content-docs'; - -// This runs in Node.js - Don't use client-side code here (browser APIs, JSX...) - -/** - * Creating a sidebar enables you to: - - create an ordered group of docs - - render a sidebar for each doc of that group - - provide next/previous navigation - - The sidebars can be generated from the filesystem, or explicitly defined here. - - Create as many sidebars as you want. - */ -const sidebars: SidebarsConfig = { - // By default, Docusaurus generates a sidebar from the docs folder structure - tutorialSidebar: [ - 'intro', - { - type: 'category', - label: 'Projects', - items: [ - 'projects/theia-deployment', - 'projects/theia-scale-tests', - 'projects/theia-shared-cache', - 'projects/theia-lsp-extension', - 'projects/theia-data-bridge', - 'projects/eduidec', - 'projects/theia-arc-runners', - 'projects/theia-workspace-garbage-collector', - ], - }, - { - type: 'category', - label: 'Contributions', - items: [{type: 'autogenerated', dirName: 'contributions'}], - }, - ], -}; - -export default sidebars; diff --git a/sidebarsAdmins.ts b/sidebarsAdmins.ts index 8b6563c..ca9d4c6 100644 --- a/sidebarsAdmins.ts +++ b/sidebarsAdmins.ts @@ -3,6 +3,11 @@ import type {SidebarsConfig} from '@docusaurus/plugin-content-docs'; const sidebars: SidebarsConfig = { adminsSidebar: [ 'intro', + { + type: 'category', + label: 'Install', + items: ['install/installing', 'install/adding-an-installation'], + }, { type: 'category', label: 'Platform', @@ -36,6 +41,8 @@ const sidebars: SidebarsConfig = { label: 'Maintenance', items: [ 'maintenance/upgrades', + 'maintenance/rollback', + 'maintenance/release-policy', ], }, ], diff --git a/sidebarsInstructor.ts b/sidebarsInstructor.ts index ed94cab..a7a2c25 100644 --- a/sidebarsInstructor.ts +++ b/sidebarsInstructor.ts @@ -1,5 +1,12 @@ import type {SidebarsConfig} from '@docusaurus/plugin-content-docs'; +/** + * Every page under docs/instructor must appear here. Docusaurus warns about a + * sidebar entry with no file, but publishes a file with no sidebar entry and + * says nothing - so seven pages sat live and unreachable, including the two + * that set expectations honestly. scripts/check-docs.sh enforces both + * directions now. + */ const sidebars: SidebarsConfig = { instructorSidebar: [ 'intro', @@ -10,6 +17,8 @@ const sidebars: SidebarsConfig = { 'course-evaluation/course-fit', 'course-evaluation/evaluating-eduide-in-a-pilot', 'course-evaluation/customizable-features', + 'course-evaluation/what-you-can-evaluate', + 'course-evaluation/what-you-cannot-evaluate', ], }, { @@ -17,6 +26,17 @@ const sidebars: SidebarsConfig = { label: 'Prerequisites', items: ['prerequisites/course-requirements', 'prerequisites/operational-dependencies'], }, + { + type: 'category', + label: 'Running a Course', + items: ['course-operations/course-setup', 'course-operations/cohort-management'], + }, + { + type: 'category', + label: 'Teaching', + items: ['teaching/live-session-playbook', 'teaching/feedback-rhythm'], + }, + 'limitations/honest-limitations', ], };