diff --git a/.devfile.yaml b/.devfile.yaml new file mode 100644 index 000000000..a1bfeb5bf --- /dev/null +++ b/.devfile.yaml @@ -0,0 +1,225 @@ +schemaVersion: 2.3.0 +metadata: + name: openvsx +components: + - name: tool + container: + image: quay.io/devfile/universal-developer-image:ubi8-latest + memoryRequest: 256Mi + memoryLimit: 8Gi + cpuRequest: 100m + cpuLimit: 2000m + env: + - name: OPENVSX_NAMESPACE + value: openvsx + volumeMounts: + - name: local + path: /home/user/.local/ + - name: elasticsearch + container: + image: docker.elastic.co/elasticsearch/elasticsearch:8.7.1 + memoryRequest: 256Mi + memoryLimit: 2Gi + cpuRequest: 100m + cpuLimit: 800m + endpoints: + - exposure: internal + name: elasticsearch + protocol: tcp + targetPort: 9200 + - exposure: internal + name: es9300 + protocol: tcp + targetPort: 9300 + - exposure: public + name: che-server + targetPort: 8080 + - exposure: public + name: che-webui + targetPort: 3000 + env: + - name: bootstrap.memory_lock + value: 'true' + - name: cluster.routing.allocation.disk.threshold_enabled + value: 'false' + - name: discovery.type + value: single-node + - name: xpack.ml.enabled + value: 'false' + - name: xpack.security.enabled + value: 'false' + - name: postgresql + container: + image: 'image-registry.openshift-image-registry.svc:5000/openshift/postgresql:15-el8' + memoryRequest: 256Mi + memoryLimit: 2Gi + cpuRequest: 100m + cpuLimit: '1' + env: + - name: POSTGRESQL_USER + value: openvsx + - name: POSTGRESQL_PASSWORD + value: openvsx + - name: POSTGRESQL_DATABASE + value: openvsx + - volume: + ephemeral: true + name: local + +commands: + - id: build-cli + exec: + label: "1.1. Build OVSX CLI" + component: tool + workingDir: ${PROJECTS_ROOT}/openvsx/cli + commandLine: | + yarn install && + yarn prepare + + - id: build-webui + exec: + label: "1.2. Build UI Component" + component: tool + workingDir: ${PROJECTS_ROOT}/openvsx/webui + commandLine: | + yarn install && + yarn build && + yarn build:default + + - id: build-server + exec: + label: "1.3. Build Server Component" + component: tool + workingDir: ${PROJECTS_ROOT}/openvsx + commandLine: | + server/gradlew -p server assemble downloadTestExtensions + + - id: run-server + exec: + label: "1.4. Run OpenVSX Server" + component: tool + workingDir: ${PROJECTS_ROOT}/openvsx/server + commandLine: | + ./scripts/generate-properties.sh && + sed -i 's/localhost:5432\/postgres/localhost:5432\/openvsx/g' src/dev/resources/application.yml && + sed -i 's/username: gitpod/username: openvsx/g' src/dev/resources/application.yml && + sed -i 's/password: gitpod/password: openvsx/g' src/dev/resources/application.yml && + ./gradlew runServer + + - id: run-webui + exec: + label: "1.5. Run OpenVSX WebUI" + component: tool + workingDir: ${PROJECTS_ROOT}/openvsx/webui + commandLine: | + yarn start:default + + - id: cli-publish + exec: + label: "1.6. Publish extensions by OVSX CLI" + component: tool + workingDir: ${PROJECTS_ROOT}/openvsx + commandLine: | + nvm use v${NODEJS_20_VERSION} + export OVSX_REGISTRY_URL=http://localhost:8080 + export OVSX_PAT=super_token + export PUBLISHERS="DotJoshJohnson eamodio felixfbecker formulahendry HookyQR ms-azuretools ms-mssql ms-python ms-vscode octref redhat ritwickdey sburg vscode vscodevim Wscats" + for pub in $PUBLISHERS; do cli/lib/ovsx create-namespace $pub; done + find server/build/test-extensions-builtin -name '*.vsix' -exec cli/lib/ovsx publish '{}' \; + find server/build/test-extensions -name '*.vsix' -exec cli/lib/ovsx publish '{}' \; + +# Commands to deploy OpenVSX to OpenShift + - id: build-openvsx-image + exec: + label: "2.1. Build and Publish OpenVSX Image" + component: tool + workingDir: ${PROJECTS_ROOT}/openvsx/openshift + commandLine: | + read -p "Please enter the value for OPENVSX_VERSION (default: v0.18.0): " OPENVSX_VERSION + OPENVSX_VERSION=${OPENVSX_VERSION:-v0.18.0} + export OPENVSX_VERSION + echo "OPENVSX_VERSION is set to $OPENVSX_VERSION" + podman build -t "openvsx:$OPENVSX_VERSION" --build-arg "OPENVSX_VERSION=$OPENVSX_VERSION" -f openvsx.Dockerfile .&& + oc new-project $OPENVSX_NAMESPACE + export IMAGE=image-registry.openshift-image-registry.svc:5000/$OPENVSX_NAMESPACE/openvsx && + podman tag openvsx:$OPENVSX_VERSION ${IMAGE} && + podman login --tls-verify=false -u $(oc whoami | tr -d :) -p $(oc whoami -t) image-registry.openshift-image-registry.svc:5000 && + podman push --tls-verify=false "${IMAGE}" + + - id: build-ovsx-cli-image + exec: + label: "2.2. Build and Publish OpenVSX CLI Image" + component: tool + workingDir: ${PROJECTS_ROOT}/openvsx/openshift + commandLine: | + podman build -t "openvsx-cli" -f cli.Dockerfile .&& + export IMAGE=image-registry.openshift-image-registry.svc:5000/$OPENVSX_NAMESPACE/openvsx-cli && + podman tag openvsx-cli ${IMAGE} && + podman login --tls-verify=false -u $(oc whoami | tr -d :) -p $(oc whoami -t) image-registry.openshift-image-registry.svc:5000 && + podman push --tls-verify=false "${IMAGE}" + + - id: deploy-openvsx + exec: + label: "2.3. Deploy OpenVSX" + component: tool + workingDir: ${PROJECTS_ROOT}/openvsx/openshift + commandLine: | + oc process -f openvsx-deployment.yml \ + -p OPENVSX_SERVER_IMAGE=image-registry.openshift-image-registry.svc:5000/$OPENVSX_NAMESPACE/openvsx \ + -p OPENVSX_CLI_IMAGE=image-registry.openshift-image-registry.svc:5000/$OPENVSX_NAMESPACE/openvsx-cli \ + | oc apply -f - + + - id: add-openvsx-user-with-pat + exec: + label: "2.4. Add OpenVSX user with PAT to the DB" + component: tool + commandLine: | + read -p "Please enter OpenVSX user name (default: eclipse-che): " OPENVSX_USER_NAME + OPENVSX_USER_NAME=${OPENVSX_USER_NAME:-eclipse-che} + export OPENVSX_USER_NAME + echo "OPENVSX_USER_NAME is set to $OPENVSX_USER_NAME" + read -p "Please enter the value for OpenVSX user PAT (default: eclipse_che_token): " OPENVSX_USER_PAT + OPENVSX_USER_PAT=${OPENVSX_USER_PAT:-eclipse_che_token} + export OPENVSX_USER_PAT + echo "OPENVSX_USER_PAT is set to $OPENVSX_USER_PAT" + export POSTGRESQL_POD_NAME=$(kubectl get pods -n "$OPENVSX_NAMESPACE" -o jsonpath="{.items[*].metadata.name}" | tr ' ' '\n' | grep ^postgresql) && + kubectl exec -n "${OPENVSX_NAMESPACE}" "${POSTGRESQL_POD_NAME}" -- bash -c "psql -d openvsx -c \"INSERT INTO user_data (id, login_name, role) VALUES (1001, '$OPENVSX_USER_NAME', 'privileged');\"" && + kubectl exec -n "${OPENVSX_NAMESPACE}" "${POSTGRESQL_POD_NAME}" -- bash -c "psql -d openvsx -c \"INSERT INTO personal_access_token (id, user_data, value, active, created_timestamp, accessed_timestamp, description) VALUES (1001, 1001, '$OPENVSX_USER_PAT', true, current_timestamp, current_timestamp, 'extensions publisher');\"" + + - id: enable-internal-openvsx + exec: + label: "2.5. Configure Che to use the internal OpenVSX registry" + component: tool + workingDir: ${PROJECTS_ROOT}/openvsx/openshift + commandLine: | + export CHECLUSTER_NAME="$(kubectl get checluster --all-namespaces -o json | jq -r '.items[0].metadata.name')" && + export CHECLUSTER_NAMESPACE="$(kubectl get checluster --all-namespaces -o json | jq -r '.items[0].metadata.namespace')" && + export OPENVSX_ROUTE_URL="$(oc get route internal -n "$OPENVSX_NAMESPACE" -o jsonpath='{.spec.host}')" && + export PATCH='{"spec":{"components":{"pluginRegistry":{"openVSXURL":"https://'"$OPENVSX_ROUTE_URL"'"}}}}' && + kubectl patch checluster "${CHECLUSTER_NAME}" --type=merge --patch "${PATCH}" -n "${CHECLUSTER_NAMESPACE}" + + - id: publish-extension + exec: + label: "2.6. Publish VS Code Extension to the internal OpenVSX" + component: tool + commandLine: | + read -p "Please enter extension's namespace name: " EXTENSION_NAMESPACE_NAME + EXTENSION_NAMESPACE_NAME=${EXTENSION_NAMESPACE_NAME} + export EXTENSION_NAMESPACE_NAME + echo "EXTENSION_NAMESPACE_NAME is set to $EXTENSION_NAMESPACE_NAME" + read -p "Please enter extension's download URL: " EXTENSION_DOWNLOAD_URL + EXTENSION_DOWNLOAD_URL=${EXTENSION_DOWNLOAD_URL} + export EXTENSION_DOWNLOAD_URL + echo "EXTENSION_DOWNLOAD_URL is set to $EXTENSION_DOWNLOAD_URL" + export OVSX_POD_NAME=$(kubectl get pods -n "$OPENVSX_NAMESPACE" -o jsonpath="{.items[*].metadata.name}" | tr ' ' '\n' | grep ^ovsx-cli) && + kubectl exec -n "${OPENVSX_NAMESPACE}" "${OVSX_POD_NAME}" -- bash -c "wget -O /tmp/extension.vsix '$EXTENSION_DOWNLOAD_URL' " && + kubectl exec -n "${OPENVSX_NAMESPACE}" "${OVSX_POD_NAME}" -- bash -c "ovsx create-namespace '$EXTENSION_NAMESPACE_NAME'" || true && + kubectl exec -n "${OPENVSX_NAMESPACE}" "${OVSX_POD_NAME}" -- bash -c "ovsx publish /tmp/extension.vsix" && + kubectl exec -n "${OPENVSX_NAMESPACE}" "${OVSX_POD_NAME}" -- bash -c "rm /tmp/extension.vsix" + + - id: publish-extensions + exec: + label: "2.7. Publish list of VS Code Extensions" + component: tool + workingDir: ${PROJECTS_ROOT}/openvsx/openshift + commandLine: ./scripts/publish_extensions.sh diff --git a/.vscode/extensions.json b/.vscode/extensions.json index e79d2f5ec..be63de530 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -4,6 +4,7 @@ "redhat.java", "vscjava.vscode-java-debug", "vscjava.vscode-java-test", - "richardwillis.vscode-gradle" + "richardwillis.vscode-gradle", + "redhat.vscode-yaml" ] } \ No newline at end of file diff --git a/README.md b/README.md index 22eac24e8..759d120f4 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # Eclipse Open VSX [![Gitpod Ready-to-Code](https://img.shields.io/badge/Gitpod-ready--to--code-blue?logo=gitpod)](https://gitpod.io/#https://github.com/eclipse/openvsx) +[![Contribute](https://www.eclipse.org/che/contribute.svg)](https://workspaces.openshift.com#https://github.com/eclipse/openvsx) [![Join the chat at https://gitter.im/eclipse/openvsx](https://badges.gitter.im/eclipse/openvsx.svg)](https://gitter.im/eclipse/openvsx) [![CI](https://github.com/eclipse/openvsx/workflows/CI/badge.svg)](https://github.com/eclipse/openvsx/actions?query=workflow%3ACI) @@ -17,12 +18,16 @@ See the [openvsx Wiki](https://github.com/eclipse/openvsx/wiki) for documentatio ## Development -The easiest way to get a development environment for this project is to open it in [Gitpod](https://gitpod.io/). +- The easiest way to get a development environment for this project is to open it in [Gitpod](https://gitpod.io/). [![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/eclipse/openvsx) Click _Open Browser_ on port 3000 to see the running web application. +- Open a development environment in [Red Hat OpenShift Dev Spaces](https://docs.redhat.com/en/documentation/red_hat_openshift_dev_spaces), it is an open source product based on Eclipse Che that is running on [OpenShift Dedicated](https://www.redhat.com/en/technologies/cloud-computing/openshift/dedicated). + +[![Open in Dev Spaces](https://www.eclipse.org/che/contribute.svg)](https://workspaces.openshift.com#https://github.com/eclipse/openvsx) + ### cli * `yarn build` — build the library and `ovsx` command diff --git a/doc/development.md b/doc/development.md index 72ed1ba3c..bdf383042 100644 --- a/doc/development.md +++ b/doc/development.md @@ -6,6 +6,22 @@ To get started quickly, it is recommended to use Gitpod as default with the deve [![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/eclipse/openvsx) +### Using Red Hat OpenShift Dev Spaces + +Open a development environment in Red Hat OpenShift Dev Spaces. + +[![Open in Dev Spaces](https://www.eclipse.org/che/contribute.svg)](https://workspaces.openshift.com#https://github.com/eclipse/openvsx) + +In the workspace, you'll find a set of predefined commands from the devfile.yaml that will assist you in building, running, and testing the application: +* 1.1. Build OVSX CLI +* 1.2. Build UI Component +* 1.3. Build Server Component +* 1.4. Run OpenVSX Server +* 1.5. Run OpenVSX WebUI +* 1.6. Publish extensions by OVSX CLI + +To execute any of these commands within your workspace, navigate to Terminal -> Run Task -> devfile. + ### Using Docker Compose To run the Open VSX registry in a development environment, you can use `docker compose` by following these steps: diff --git a/openshift/README.md b/openshift/README.md new file mode 100644 index 000000000..fe9277af2 --- /dev/null +++ b/openshift/README.md @@ -0,0 +1,51 @@ +# Deploying a Private OpenVSX Registry on OpenShift + +This guide provides the necessary steps to deploy a private OpenVSX registry on OpenShift. By following the instructions, you'll have a fully operational OpenVSX server and CLI deployed within your OpenShift cluster, ready to be used by Eclipse Che or other services. + +## Prerequisites +- [Deploy and run Eclipse Che on your cluster](https://eclipse.dev/che/docs/stable/administration-guide/installing-che-in-the-cloud/) +- [Create a workspace](https://eclipse.dev/che/docs/stable/end-user-guide/starting-a-workspace-from-a-git-repository-url/) from the [openvsx Git repository URL](https://github.com/eclipse/openvsx) + +## Step-by-Step Instructions +In the workspace, you'll find a set of predefined commands from the `devfile.yaml` that will assist you in preparing and deploying a private OpenVSX registry. To execute any of these commands within your workspace, navigate to Terminal -> Run Task -> devfile: + +* 2.1. Build and Publish OpenVSX Image + +Build the OpenVSX image and push it to the OpenShift internal registry. You'll ask to enter the OpenVSX version to deploy (default is v0.18.0). + +* 2.2. Build and Publish OpenVSX CLI Image + +Build the OpenVSX CLI image and push it to the OpenShift internal registry. + +* 2.3. Deploy OpenVSX + +Deploy the OpenVSX registry using the provided `openvsx-deployment.yml` template + +* 2.4. Add OpenVSX user with PAT to the DB + +This command adds a new OpenVSX user along with a Personal Access Token (PAT) to the PostgreSQL database. + +* 2.5. Configure Che to use the internal OpenVSX registry + +In case you have deployed Eclipse Che on the cluster, you can patch it to use your private OpenVSX registry. + +* 2.6. Publish VS Code Extension to the internal OpenVSX + +This command facilitates publishing a VS Code extension to the local OpenVSX registry. It prompts the user to provide the extension's namespace name and download URL. The extension is then downloaded into a temporary folder inside the ovsx-cli pod, a namespace is created (if not already present), and the extension is published to the OpenVSX registry. Afterward, the temporary file is deleted. This command is ideal for adding custom or internal extensions to a local OpenVSX instance. + +* 2.7. Publish list of VS Code Extensions + +This command facilitates publishing a list of VS Code extensions to a local OpenVSX registry based on URLs specified in the `extensions.txt` file. For each extension listed, it downloads the `.vsix` file into a temporary directory on the ovsx-cli pod, creates a namespace if it doesn’t already exist, and publishes the extension to the OpenVSX registry. After each extension is published, the temporary file is deleted from the pod. This command is ideal for managing multiple extensions by automating the download, namespace creation, and publishing steps, making it easy to maintain a custom set of extensions in a local OpenVSX instance. + +## OpenShift Template (openvsx-deployment.yml) +You can find the deployment YAML configuration in the `openvsx-deployment.yml` file. This template defines the deployments, services, and route for the PostgreSQL database, Elasticsearch, OpenVSX Server, and OpenVSX CLI. + +### Important Parameters +* `ROUTE_NAME`: The name of the route to access the OpenVSX server (default: internal) +* `NAMESPACE`: The namespace where OpenVSX will be deployed (default: openvsx) +* `POSTGRESQL_IMAGE`: The PostgreSQL image to use for the database (default: image-registry.openshift-image-registry.svc:5000/openshift/postgresql:15-el8) +* `OPENVSX_ELASTICSEARCH_IMAGE`: The image for Elasticsearch (default: docker.elastic.co/elasticsearch/elasticsearch:8.7.1). +* `OPENVSX_SERVER_IMAGE`: The image for the OpenVSX Server. +* `OPENVSX_CLI_IMAGE`: The image for the OpenVSX CLI. +* `OVSX_PAT_BASE64`: Base64 encoded OVSX personal access token. +* `GITHUB_CLIENT_ID_BASE64` and `GITHUB_CLIENT_SECRET_BASE64`: Base64 encoded GitHub Client ID and Secret to setup GitHub OAuth. diff --git a/openshift/application.yml b/openshift/application.yml new file mode 100644 index 000000000..0ea2df86a --- /dev/null +++ b/openshift/application.yml @@ -0,0 +1,111 @@ +logging: + pattern: + level: '%5p [${spring.application.name:},%X{traceId:-},%X{spanId:-}]' + +server: + port: 8080 + jetty: + threads: + max-queue-capacity: 100 + +spring: + application: + name: openvsx-server + autoconfigure: + exclude: + - org.springframework.boot.actuate.autoconfigure.tracing.zipkin.ZipkinAutoConfiguration + profiles: + include: ovsx + cache: + jcache: + config: classpath:ehcache.xml + datasource: + url: jdbc:postgresql://postgresql:5432/openvsx + username: openvsx + password: openvsx + flyway: + baseline-on-migrate: true + baseline-version: 0.1.0 + baseline-description: JobRunr tables + jpa: + open-in-view: false + properties: + hibernate: + dialect: org.hibernate.dialect.PostgreSQLDialect + hibernate: + ddl-auto: none + session: + store-type: jdbc + jdbc: + initialize-schema: never + + security: + oauth2: + client: + registration: + github: + client-id: ${GITHUB_CLIENT_ID} + client-secret: ${GITHUB_CLIENT_SECRET} + +management: + health: + probes: + enabled: true + endpoints: + web: + exposure: + include: + - health + - metrics + - prometheus + metrics: + distribution: + percentiles-histogram: + http: + server: + requests: true + client: + requests: true + +springdoc: + swagger-ui: + path: /swagger-ui + docExpansion: list + operationsSorter: alpha + supportedSubmitMethods: + - get + +org: + jobrunr: + job-scheduler: + enabled: true + background-job-server: + enabled: true + worker-count: 2 + dashboard: + enabled: false + database: + type: sql + miscellaneous: + allow-anonymous-data-usage: false + +bucket4j: + enabled: false + +ovsx: + databasesearch: + enabled: false + elasticsearch: + clear-on-start: true + host: elasticsearch:9200 + eclipse: + base-url: https://api.eclipse.org + publisher-agreement: + timezone: US/Eastern + integrity: + key-pair: create # create, renew, delete, 'undefined' + registry: + version: 'OPENVSX_VERSION' + storage: + local: + directory: /tmp/extensions diff --git a/openshift/cli.Dockerfile b/openshift/cli.Dockerfile new file mode 100644 index 000000000..6bf7a0b8b --- /dev/null +++ b/openshift/cli.Dockerfile @@ -0,0 +1,13 @@ +FROM registry.access.redhat.com/ubi9/nodejs-20-minimal:1-63.1725851021 as builder + +USER root + +RUN microdnf -y --nodocs --setopt=install_weak_deps=0 install \ + git \ + wget \ + && microdnf clean all + +USER 1001 + +RUN npm install -g ovsx \ + && ovsx --version diff --git a/openshift/extensions.txt b/openshift/extensions.txt new file mode 100644 index 000000000..6f79de746 --- /dev/null +++ b/openshift/extensions.txt @@ -0,0 +1,12 @@ +https://open-vsx.org/api/redhat/vscode-xml/0.27.1/file/redhat.vscode-xml-0.27.1.vsix +https://open-vsx.org/api/redhat/vscode-yaml/1.15.0/file/redhat.vscode-yaml-1.15.0.vsix +https://open-vsx.org/api/redhat/java/1.35.1/file/redhat.java-1.35.1.vsix +https://open-vsx.org/api/vscode/html-language-features/1.88.1/file/vscode.html-language-features-1.88.1.vsix +https://open-vsx.org/api/redhat/vscode-quarkus/1.18.1/file/redhat.vscode-quarkus-1.18.1.vsix +https://open-vsx.org/api/redhat/fabric8-analytics/0.9.5/file/redhat.fabric8-analytics-0.9.5.vsix +https://open-vsx.org/api/redhat/vscode-redhat-account/0.2.0/file/redhat.vscode-redhat-account-0.2.0.vsix +https://open-vsx.org/api/redhat/vscode-openshift-connector/linux-x64/1.16.0/file/redhat.vscode-openshift-connector-1.16.0@linux-x64.vsix +https://open-vsx.org/api/redhat/vscode-commons/0.0.6/file/redhat.vscode-commons-0.0.6.vsix +https://open-vsx.org/api/redhat/vscode-tekton-pipelines/1.0.1/file/redhat.vscode-tekton-pipelines-1.0.1.vsix +https://open-vsx.org/api/ms-python/python/2024.14.1/file/ms-python.python-2024.14.1.vsix +https://open-vsx.org/api/redhat/ansible/24.8.4/file/redhat.ansible-24.8.4.vsix diff --git a/openshift/openvsx-deployment.yml b/openshift/openvsx-deployment.yml new file mode 100644 index 000000000..df5d640dd --- /dev/null +++ b/openshift/openvsx-deployment.yml @@ -0,0 +1,396 @@ +apiVersion: template.openshift.io/v1 +kind: Template +metadata: + name: che-openvsx +objects: +- apiVersion: v1 + kind: Namespace + metadata: + name: "${NAMESPACE}" + labels: + name: openvsx +- apiVersion: v1 + kind: PersistentVolumeClaim + metadata: + name: postgres-pvc + spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: ${STORAGE_CAPACITY} +- apiVersion: apps/v1 + kind: Deployment + metadata: + name: postgresql + namespace: "${NAMESPACE}" + labels: + app: postgresql + app.kubernetes.io/component: postgresql + app.kubernetes.io/instance: postgresql + spec: + replicas: 1 + selector: + matchLabels: + deployment: postgresql + template: + metadata: + labels: + app: openvsx + deployment: postgresql + app.kubernetes.io/name: openvsx + app.kubernetes.io/instance: openvsx + app.kubernetes.io/component: postgresql + spec: + volumes: + - name: postgres-storage + persistentVolumeClaim: + claimName: postgres-pvc + containers: + - name: postgresql + image: ${POSTGERSQL_IMAGE} + imagePullPolicy: IfNotPresent + env: + - name: POSTGRESQL_DATABASE + value: openvsx + - name: POSTGRESQL_USER + value: openvsx + - name: POSTGRESQL_PASSWORD + value: openvsx + volumeMounts: + - name: postgres-storage + mountPath: /var/lib/pgsql/data + ports: + - containerPort: 5432 + protocol: TCP + resources: + requests: + cpu: 200m + memory: 512Mi + limits: + cpu: '1' + memory: 2Gi + livenessProbe: + exec: + command: + - pg_isready + - -U + - openvsx + initialDelaySeconds: 30 + periodSeconds: 10 + failureThreshold: 3 + timeoutSeconds: 5 + readinessProbe: + exec: + command: + - pg_isready + - -U + - openvsx + initialDelaySeconds: 15 + periodSeconds: 10 + failureThreshold: 3 + securityContext: + capabilities: + drop: + - ALL +- apiVersion: v1 + kind: Service + metadata: + name: postgresql + namespace: "${NAMESPACE}" + labels: + app: postgresql + app.kubernetes.io/component: postgresql + app.kubernetes.io/instance: postgresql + spec: + ports: + - name: "5432" + port: 5432 + targetPort: 5432 + protocol: TCP + selector: + deployment: postgresql +- apiVersion: apps/v1 + kind: Deployment + metadata: + name: elasticsearch + namespace: "${NAMESPACE}" + labels: + app: elasticsearch + app.kubernetes.io/component: elasticsearch + app.kubernetes.io/instance: elasticsearch + spec: + replicas: 1 + selector: + matchLabels: + deployment: elasticsearch + template: + metadata: + labels: + deployment: elasticsearch + spec: + containers: + - name: elasticsearch + image: ${OPENVSX_ELASTICSEARCH_IMAGE} + ports: + - containerPort: 9300 + protocol: TCP + - containerPort: 9200 + protocol: TCP + imagePullPolicy: IfNotPresent + env: + - name: bootstrap.memory_lock + value: 'true' + - name: cluster.routing.allocation.disk.threshold_enabled + value: 'false' + - name: discovery.type + value: single-node + - name: xpack.ml.enabled + value: 'false' + - name: xpack.security.enabled + value: 'false' + resources: + requests: + cpu: 500m + memory: 1Gi + limits: + cpu: '1' + memory: 2Gi + livenessProbe: + exec: + command: + - sh + - -c + - | + curl -s http://elasticsearch:9200 >/dev/null || exit 1 + failureThreshold: 50 + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 +- apiVersion: v1 + kind: Service + metadata: + name: elasticsearch + namespace: "${NAMESPACE}" + labels: + app: elasticsearch + app.kubernetes.io/component: elasticsearch + app.kubernetes.io/instance: elasticsearch + spec: + ports: + - name: 9200-tcp + port: 9200 + targetPort: 9200 + protocol: TCP + - name: 9300-tcp + port: 9300 + targetPort: 9300 + protocol: TCP + selector: + deployment: elasticsearch +- apiVersion: v1 + kind: PersistentVolumeClaim + metadata: + name: extensions-pvc + spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: ${EXTENSIONS_STORAGE_CAPACITY} +- apiVersion: apps/v1 + kind: Deployment + metadata: + name: openvsx-server + namespace: "${NAMESPACE}" + labels: + app: openvsx-server + app.kubernetes.io/component: openvsx-server + app.kubernetes.io/instance: openvsx-server + spec: + replicas: 1 + selector: + matchLabels: + deployment: openvsx-server + template: + metadata: + labels: + deployment: openvsx-server + spec: + containers: + - name: openvsx-server + image: ${OPENVSX_SERVER_IMAGE} + imagePullPolicy: IfNotPresent + readinessProbe: + httpGet: + path: /api/version + port: 8080 + failureThreshold: 30 + initialDelaySeconds: 140 + periodSeconds: 10 + timeoutSeconds: 5 + livenessProbe: + httpGet: + path: /api/version + port: 8080 + failureThreshold: 30 + initialDelaySeconds: 160 + periodSeconds: 20 + timeoutSeconds: 5 + terminationMessagePath: /dev/termination-log + resources: + requests: + cpu: 100m + memory: 512Mi + limits: + cpu: '1' + memory: 4Gi + env: + - name: GITHUB_CLIENT_ID + valueFrom: + secretKeyRef: + name: github-oauth + key: client-id + - name: GITHUB_CLIENT_SECRET + valueFrom: + secretKeyRef: + name: github-oauth + key: client-secret + volumeMounts: + - name: extensions-storage + mountPath: /tmp/extensions + volumes: + - name: extensions-storage + persistentVolumeClaim: + claimName: extensions-pvc +- apiVersion: v1 + kind: Service + metadata: + namespace: "${NAMESPACE}" + labels: + app: openvsx-server + app.kubernetes.io/component: openvsx-server + app.kubernetes.io/instance: openvsx-server + name: openvsx-server + spec: + ports: + - name: 8080-tcp + port: 8080 + targetPort: 8080 + selector: + deployment: openvsx-server +- apiVersion: v1 + kind: Route + metadata: + namespace: "${NAMESPACE}" + name: "${ROUTE_NAME}" + labels: + app.kubernetes.io/instance: openvsx-server + app.kubernetes.io/component: openvsx-server + spec: + to: + kind: Service + name: openvsx-server + weight: 100 + port: + targetPort: 8080 + tls: + termination: edge + insecureEdgeTerminationPolicy: Redirect +- apiVersion: v1 + kind: Secret + metadata: + name: github-oauth + namespace: "${NAMESPACE}" + type: Opaque + data: + client-id: "${GITHUB_CLIENT_ID_BASE64}" + client-secret: "${GITHUB_CLIENT_SECRET_BASE64}" +- apiVersion: v1 + kind: Secret + metadata: + name: ovsx-pat + namespace: "${NAMESPACE}" + type: Opaque + data: + token: "${OVSX_PAT_BASE64}" +- apiVersion: apps/v1 + kind: Deployment + metadata: + name: ovsx-cli + namespace: "${NAMESPACE}" + labels: + app: ovsx-cli + app.kubernetes.io/component: ovsx-cli + app.kubernetes.io/instance: ovsx-cli + spec: + replicas: 1 + selector: + matchLabels: + deployment: ovsx-cli + template: + metadata: + labels: + deployment: ovsx-cli + spec: + containers: + - name: ovsx-cli + image: ${OPENVSX_CLI_IMAGE} + imagePullPolicy: IfNotPresent + env: + - name: OVSX_REGISTRY_URL + value: http://openvsx-server:8080 + - name: OVSX_PAT + valueFrom: + secretKeyRef: + name: ovsx-pat + key: token + resources: + requests: + cpu: 20m + memory: 128Mi + limits: + cpu: 250m + memory: 256Mi + command: ["/bin/sh", "-c"] + args: ["tail -f /dev/null"] + +parameters: +- name: ROUTE_NAME + description: The name of the route to access the OpenVSX Server + value: "internal" +- name: NAMESPACE + description: The namespace where the OpenVSX will be deployed + value: "openvsx" +- name: POSTGERSQL_IMAGE + value: image-registry.openshift-image-registry.svc:5000/openshift/postgresql:15-el8 + displayName: PostgreSQL image + description: PostgreSQL image to use for the deployment of the PostgreSQL database +- name: OPENVSX_SERVER_IMAGE + displayName: OpenVSX Server image + description: OpenVSX Server image to use for the deployment of the OpenVSX Server +- name: OPENVSX_CLI_IMAGE + displayName: OpenVSX CLI image + description: OpenVSX CLI image to use for the deployment of the OpenVSX CLI +- name: OPENVSX_ELASTICSEARCH_IMAGE + value: docker.elastic.co/elasticsearch/elasticsearch:8.7.1 + displayName: OpenVSX Elasticsearch image + description: OpenVSX Elasticsearch image to use for the deployment of the OpenVSX Elasticsearch +- name: OVSX_PAT_BASE64 + value: ZWNsaXBzZV9jaGVfdG9rZW4= + displayName: OVSX personal access token + description: Base64 encoded OVSX token +- name: GITHUB_CLIENT_ID_BASE64 + value: "ZHVtbXlfdmFsdWU=" + displayName: GitHub Client ID + description: Base64 encoded GitHub Client ID +- name: GITHUB_CLIENT_SECRET_BASE64 + value: "ZHVtbXlfdmFsdWU=" + displayName: GitHub Client Secret + description: Base64 encoded GitHub Client Secret +- name: STORAGE_CAPACITY + description: "Persistent storage capacity for PostgreSQL" + value: "1Gi" +- name: EXTENSIONS_STORAGE_CAPACITY + description: "Persistent storage capacity for local extensions storage" + value: "5Gi" diff --git a/openshift/openvsx.Dockerfile b/openshift/openvsx.Dockerfile new file mode 100644 index 000000000..4b3df1841 --- /dev/null +++ b/openshift/openvsx.Dockerfile @@ -0,0 +1,47 @@ +ARG OPENVSX_VERSION + +# Builder image to compile the website +FROM registry.access.redhat.com/ubi9:9.5-1730489303 as builder + +WORKDIR /workdir + +RUN yum update -q -y && \ + yum install --nodocs -y \ + git \ + && rm -rf /var/lib/apt/lists/* + +RUN curl -fsSL https://rpm.nodesource.com/setup_20.x -o nodesource_setup.sh \ + && bash nodesource_setup.sh \ + && yum install -y nodejs \ + && node -v \ + && rm -rf nodesource_setup.sh + +RUN npm install -g corepack \ + && corepack enable \ + && corepack prepare yarn@stable --activate + +ARG OPENVSX_VERSION +ENV VERSION=$OPENVSX_VERSION + +RUN git clone --branch ${VERSION} --depth 1 https://github.com/eclipse/openvsx.git /workdir + +RUN yarn --version \ + && yarn --cwd webui \ + && yarn --cwd webui install \ + && yarn --cwd webui build \ + && yarn --cwd webui build:default + +# Main image derived from openvsx-server +FROM ghcr.io/eclipse/openvsx-server:${OPENVSX_VERSION} +ARG OPENVSX_VERSION + +COPY --from=builder --chown=openvsx:openvsx /workdir/webui/static/ BOOT-INF/classes/static/ +COPY /application.yml config/ + +USER root +RUN sed -i "s/OPENVSX_VERSION/${OPENVSX_VERSION}/g" config/application.yml +USER openvsx +# Local storage: +RUN \ + mkdir -p /tmp/extensions && \ + chmod 777 /tmp/extensions diff --git a/openshift/scripts/publish_extensions.sh b/openshift/scripts/publish_extensions.sh new file mode 100755 index 000000000..4ccb144dc --- /dev/null +++ b/openshift/scripts/publish_extensions.sh @@ -0,0 +1,40 @@ +#!/bin/bash +# This script automates the process of downloading, configuring, and publishing VS Code extensions to an OpenVSX registry +# deployed on an OpenShift cluster. + +# Path to the extensions.txt file +current_dir=$(pwd) +EXTENSIONS_FILE="$current_dir/extensions.txt" + +listOfPublishers=() +containsElement () { for e in "${@:2}"; do [[ "$e" = "$1" ]] && return 0; done; return 1; } + +# Get ovsx-cli pod name +export OVSX_POD_NAME=$(kubectl get pods -n "$OPENVSX_NAMESPACE" -o jsonpath="{.items[*].metadata.name}" | tr ' ' '\n' | grep ^ovsx-cli) + +# Read the extensions.txt file line by line +while IFS= read -r line; do + # Extract the vsix file name from the URL + vsix_url="$line" + vsix_filename=$(basename "$vsix_url") + + # Download the vsix file into the /tmp directory + echo "Downloading $vsix_url" + kubectl exec -n "${OPENVSX_NAMESPACE}" "${OVSX_POD_NAME}" -- bash -c "wget -q -P /tmp '$vsix_url' " + + # Extract namespace_name (everything before the first .) + namespace_name=$(echo "$vsix_filename" | cut -d. -f1) + + # Execute ovsx commands + # check if publisher is in the list of publishers + if ! containsElement "${namespace_name}" "${listOfPublishers[@]}"; then + listOfPublishers+=("${namespace_name}") + # create namespace + kubectl exec -n "${OPENVSX_NAMESPACE}" "${OVSX_POD_NAME}" -- bash -c "ovsx create-namespace '$namespace_name'" || true + fi + # publish extension + kubectl exec -n "${OPENVSX_NAMESPACE}" "${OVSX_POD_NAME}" -- bash -c "ovsx publish /tmp/'$vsix_filename'" + + # remove the downloaded file + kubectl exec -n "${OPENVSX_NAMESPACE}" "${OVSX_POD_NAME}" -- bash -c "rm /tmp/'$vsix_filename'" +done < "$EXTENSIONS_FILE" diff --git a/webui/src/default/default-app.tsx b/webui/src/default/default-app.tsx index 3b79ea330..651838e04 100644 --- a/webui/src/default/default-app.tsx +++ b/webui/src/default/default-app.tsx @@ -30,6 +30,10 @@ if (serverHost.startsWith('3000-')) { } else if (location.port === '3000') { // Localhost dev environment serverHost = serverHost + ':8080'; +} else if (serverHost.includes('che-webui')) { + // Eclipse Che dev environment. + // If serverHost contains 'che-webui', replace it with 'che-server' + serverHost = serverHost.replace('che-webui', 'che-server'); } const service = new ExtensionRegistryService(`${location.protocol}//${serverHost}`);