Merge branch 'main' into module-screenshots
merge main
This commit is contained in:
7
.github/workflows/ci.yaml
vendored
7
.github/workflows/ci.yaml
vendored
@@ -21,11 +21,14 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
bun-version: latest
|
bun-version: latest
|
||||||
- run: bun test
|
- run: bun test
|
||||||
fmt:
|
pretty:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: oven-sh/setup-bun@v1
|
- uses: oven-sh/setup-bun@v1
|
||||||
with:
|
with:
|
||||||
bun-version: latest
|
bun-version: latest
|
||||||
- run: bun fmt:ci
|
- name: Format
|
||||||
|
run: bun fmt:ci
|
||||||
|
- name: Lint
|
||||||
|
run: bun install && bun lint
|
||||||
|
|||||||
BIN
.images/git-config-params.png
Normal file
BIN
.images/git-config-params.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 82 KiB |
BIN
.images/jupyter-notebook.png
Normal file
BIN
.images/jupyter-notebook.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 654 KiB |
@@ -11,14 +11,14 @@ tags: [helper]
|
|||||||
|
|
||||||
<!-- Describes what this module does -->
|
<!-- Describes what this module does -->
|
||||||
|
|
||||||
<!-- Add a screencast or screenshot here put them in .images directory -->
|
|
||||||
|
|
||||||
```hcl
|
```hcl
|
||||||
module "MODULE_NAME" {
|
module "MODULE_NAME" {
|
||||||
source = "https://registry.coder.com/modules/MODULE_NAME"
|
source = "https://registry.coder.com/modules/MODULE_NAME"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
<!-- Add a screencast or screenshot here put them in .images directory -->
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
### Example 1
|
### Example 1
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env sh
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
BOLD='\033[0;1m'
|
BOLD='\033[0;1m'
|
||||||
echo "$${BOLD}Installing MODULE_NAME..."
|
printf "$${BOLD}Installing MODULE_NAME..."
|
||||||
# Add code here
|
# Add code here
|
||||||
# Use varibles from the templatefile function in main.tf
|
# Use varibles from the templatefile function in main.tf
|
||||||
# e.g. LOG_PATH, PORT, etc.
|
# e.g. LOG_PATH, PORT, etc.
|
||||||
|
|||||||
@@ -26,6 +26,12 @@ variable "port" {
|
|||||||
default = 13337
|
default = 13337
|
||||||
}
|
}
|
||||||
|
|
||||||
|
variable "display_name" {
|
||||||
|
type = string
|
||||||
|
description = "The display name for the code-server application."
|
||||||
|
default = "code-server"
|
||||||
|
}
|
||||||
|
|
||||||
variable "settings" {
|
variable "settings" {
|
||||||
type = map(string)
|
type = map(string)
|
||||||
description = "A map of settings to apply to code-server."
|
description = "A map of settings to apply to code-server."
|
||||||
@@ -75,7 +81,7 @@ resource "coder_script" "code-server" {
|
|||||||
resource "coder_app" "code-server" {
|
resource "coder_app" "code-server" {
|
||||||
agent_id = var.agent_id
|
agent_id = var.agent_id
|
||||||
slug = "code-server"
|
slug = "code-server"
|
||||||
display_name = "code-server"
|
display_name = var.display_name
|
||||||
url = "http://localhost:${var.port}/${var.folder != "" ? "?folder=${urlencode(var.folder)}" : ""}"
|
url = "http://localhost:${var.port}/${var.folder != "" ? "?folder=${urlencode(var.folder)}" : ""}"
|
||||||
icon = "/icon/code.svg"
|
icon = "/icon/code.svg"
|
||||||
subdomain = false
|
subdomain = false
|
||||||
|
|||||||
@@ -41,9 +41,9 @@ done
|
|||||||
if [ ! -f ~/.local/share/code-server/Machine/settings.json ]; then
|
if [ ! -f ~/.local/share/code-server/Machine/settings.json ]; then
|
||||||
echo "⚙️ Creating settings file..."
|
echo "⚙️ Creating settings file..."
|
||||||
mkdir -p ~/.local/share/code-server/Machine
|
mkdir -p ~/.local/share/code-server/Machine
|
||||||
echo "${SETTINGS}" > ~/.local/share/code-server/Machine/settings.json
|
echo "${SETTINGS}" >~/.local/share/code-server/Machine/settings.json
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "👷 Running code-server in the background..."
|
echo "👷 Running code-server in the background..."
|
||||||
echo "Check logs at ${LOG_PATH}!"
|
echo "Check logs at ${LOG_PATH}!"
|
||||||
$CODE_SERVER --auth none --port ${PORT} >${LOG_PATH} 2>&1 &
|
$CODE_SERVER --auth none --port ${PORT} >${LOG_PATH} 2>&1 &
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env sh
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
BOLD='\033[0;1m'
|
BOLD='\033[0;1m'
|
||||||
echo "$${BOLD}Installing filebrowser \n\n"
|
printf "$${BOLD}Installing filebrowser \n\n"
|
||||||
|
|
||||||
curl -fsSL https://raw.githubusercontent.com/filebrowser/get/master/get.sh | bash
|
curl -fsSL https://raw.githubusercontent.com/filebrowser/get/master/get.sh | bash
|
||||||
|
|
||||||
|
|||||||
@@ -26,12 +26,13 @@ variable "agent_id" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
resource "coder_script" "git_clone" {
|
resource "coder_script" "git_clone" {
|
||||||
agent_id = var.agent_id
|
agent_id = var.agent_id
|
||||||
display_name = "Git Clone"
|
|
||||||
icon = "/icons/git.svg"
|
|
||||||
script = templatefile("${path.module}/run.sh", {
|
script = templatefile("${path.module}/run.sh", {
|
||||||
CLONE_PATH : var.path != "" ? var.path : join("/", ["~", basename(var.url)]),
|
CLONE_PATH : var.path != "" ? var.path : join("/", ["~", basename(var.url)]),
|
||||||
REPO_URL : var.url,
|
REPO_URL : var.url,
|
||||||
})
|
})
|
||||||
run_on_start = true
|
display_name = "Git Clone"
|
||||||
|
icon = "/icons/git.svg"
|
||||||
|
run_on_start = true
|
||||||
|
start_blocks_login = true
|
||||||
}
|
}
|
||||||
|
|||||||
48
git-config/README.md
Normal file
48
git-config/README.md
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
---
|
||||||
|
display_name: Git Config
|
||||||
|
description: Stores Git configuration from Coder credentials
|
||||||
|
icon: ../.icons/git.svg
|
||||||
|
maintainer_github: coder
|
||||||
|
verified: true
|
||||||
|
tags: [helper, git]
|
||||||
|
---
|
||||||
|
|
||||||
|
# git-config
|
||||||
|
|
||||||
|
Runs a script that updates git credentials in the workspace to match the user's Coder credentials, optionally allowing to the developer to override the defaults.
|
||||||
|
|
||||||
|
```hcl
|
||||||
|
module "git-config" {
|
||||||
|
source = "https://registry.coder.com/modules/git-config"
|
||||||
|
agent_id = coder_agent.example.id
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
TODO: Add screenshot
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Allow users to override both username and email
|
||||||
|
|
||||||
|
```hcl
|
||||||
|
module "git-config" {
|
||||||
|
source = "https://registry.coder.com/modules/git-config"
|
||||||
|
agent_id = coder_agent.example.id
|
||||||
|
allow_email_change = true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
TODO: Add screenshot
|
||||||
|
|
||||||
|
## Disallowing users from overriding both username and email
|
||||||
|
|
||||||
|
```hcl
|
||||||
|
module "git-config" {
|
||||||
|
source = "https://registry.coder.com/modules/git-config"
|
||||||
|
agent_id = coder_agent.example.id
|
||||||
|
allow_username_change = false
|
||||||
|
allow_email_change = false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
TODO: Add screenshot
|
||||||
43
git-config/main.test.ts
Normal file
43
git-config/main.test.ts
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
import { describe, expect, it } from "bun:test";
|
||||||
|
import {
|
||||||
|
executeScriptInContainer,
|
||||||
|
runTerraformApply,
|
||||||
|
runTerraformInit,
|
||||||
|
testRequiredVariables,
|
||||||
|
} from "../test";
|
||||||
|
|
||||||
|
describe("git-config", async () => {
|
||||||
|
await runTerraformInit(import.meta.dir);
|
||||||
|
|
||||||
|
testRequiredVariables(import.meta.dir, {
|
||||||
|
agent_id: "foo",
|
||||||
|
});
|
||||||
|
|
||||||
|
it("fails without git", async () => {
|
||||||
|
const state = await runTerraformApply(import.meta.dir, {
|
||||||
|
agent_id: "foo",
|
||||||
|
});
|
||||||
|
const output = await executeScriptInContainer(state, "alpine");
|
||||||
|
expect(output.exitCode).toBe(1);
|
||||||
|
expect(output.stdout).toEqual([
|
||||||
|
"\u001B[0;1mChecking git-config!",
|
||||||
|
"Git is not installed!",
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("runs with git", async () => {
|
||||||
|
const state = await runTerraformApply(import.meta.dir, {
|
||||||
|
agent_id: "foo",
|
||||||
|
});
|
||||||
|
const output = await executeScriptInContainer(state, "alpine/git");
|
||||||
|
expect(output.exitCode).toBe(0);
|
||||||
|
expect(output.stdout).toEqual([
|
||||||
|
"\u001B[0;1mChecking git-config!",
|
||||||
|
"git-config: No user.email found, setting to ",
|
||||||
|
"git-config: No user.name found, setting to default",
|
||||||
|
"",
|
||||||
|
"\u001B[0;1mgit-config: using email: ",
|
||||||
|
"\u001B[0;1mgit-config: using username: default",
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
61
git-config/main.tf
Normal file
61
git-config/main.tf
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
terraform {
|
||||||
|
required_version = ">= 1.0"
|
||||||
|
|
||||||
|
required_providers {
|
||||||
|
coder = {
|
||||||
|
source = "coder/coder"
|
||||||
|
version = ">= 0.12"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "agent_id" {
|
||||||
|
type = string
|
||||||
|
description = "The ID of a Coder agent."
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "allow_username_change" {
|
||||||
|
type = bool
|
||||||
|
description = "Allow developers to change their git username."
|
||||||
|
default = true
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "allow_email_change" {
|
||||||
|
type = bool
|
||||||
|
description = "Allow developers to change their git email."
|
||||||
|
default = false
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
data "coder_workspace" "me" {}
|
||||||
|
|
||||||
|
data "coder_parameter" "user_email" {
|
||||||
|
count = var.allow_email_change ? 1 : 0
|
||||||
|
name = "user_email"
|
||||||
|
type = "string"
|
||||||
|
default = ""
|
||||||
|
description = "Git user.email to be used for commits. Leave empty to default to Coder username."
|
||||||
|
display_name = "Git config user.email"
|
||||||
|
mutable = true
|
||||||
|
}
|
||||||
|
|
||||||
|
data "coder_parameter" "username" {
|
||||||
|
count = var.allow_username_change ? 1 : 0
|
||||||
|
name = "username"
|
||||||
|
type = "string"
|
||||||
|
default = ""
|
||||||
|
description = "Git user.name to be used for commits. Leave empty to default to Coder username."
|
||||||
|
display_name = "Git config user.name"
|
||||||
|
mutable = true
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "coder_script" "git_config" {
|
||||||
|
agent_id = var.agent_id
|
||||||
|
script = templatefile("${path.module}/run.sh", {
|
||||||
|
GIT_USERNAME = try(data.coder_parameter.username[0].value, "") == "" ? data.coder_workspace.me.owner : try(data.coder_parameter.username[0].value, "")
|
||||||
|
GIT_EMAIL = try(data.coder_parameter.user_email[0].value, "") == "" ? data.coder_workspace.me.owner_email : try(data.coder_parameter.user_email[0].value, "")
|
||||||
|
})
|
||||||
|
display_name = "Git Config"
|
||||||
|
icon = "/icon/git.svg"
|
||||||
|
run_on_start = true
|
||||||
|
}
|
||||||
24
git-config/run.sh
Normal file
24
git-config/run.sh
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
BOLD='\033[0;1m'
|
||||||
|
printf "$${BOLD}Checking git-config!\n"
|
||||||
|
|
||||||
|
# Check if git is installed
|
||||||
|
command -v git >/dev/null 2>&1 || {
|
||||||
|
echo "Git is not installed!"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Set git username and email if missing
|
||||||
|
if [ -z $(git config --get user.email) ]; then
|
||||||
|
printf "git-config: No user.email found, setting to ${GIT_EMAIL}\n"
|
||||||
|
git config --global user.email "${GIT_EMAIL}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z $(git config --get user.name) ]; then
|
||||||
|
printf "git-config: No user.name found, setting to ${GIT_USERNAME}\n"
|
||||||
|
git config --global user.name "${GIT_USERNAME}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf "\n$${BOLD}git-config: using email: $(git config --get user.email)\n"
|
||||||
|
printf "$${BOLD}git-config: using username: $(git config --get user.name)\n\n"
|
||||||
10
jfrog/run.sh
10
jfrog/run.sh
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env sh
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
BOLD='\033[0;1m'
|
BOLD='\033[0;1m'
|
||||||
echo "$${BOLD}Installing JFrog CLI..."
|
printf "$${BOLD}Installing JFrog CLI..."
|
||||||
|
|
||||||
# Install the JFrog CLI.
|
# Install the JFrog CLI.
|
||||||
curl -fL https://install-cli.jfrog.io | sudo sh
|
curl -fL https://install-cli.jfrog.io | sudo sh
|
||||||
@@ -20,11 +20,11 @@ if [ -z "${REPOSITORY_NPM}" ]; then
|
|||||||
else
|
else
|
||||||
echo "📦 Configuring npm..."
|
echo "📦 Configuring npm..."
|
||||||
jf npmc --global --repo-resolve "${JFROG_URL}/artifactory/api/npm/${REPOSITORY_NPM}"
|
jf npmc --global --repo-resolve "${JFROG_URL}/artifactory/api/npm/${REPOSITORY_NPM}"
|
||||||
cat << EOF > ~/.npmrc
|
cat <<EOF >~/.npmrc
|
||||||
email = ${ARTIFACTORY_USERNAME}
|
email = ${ARTIFACTORY_USERNAME}
|
||||||
registry = ${JFROG_URL}/artifactory/api/npm/${REPOSITORY_NPM}
|
registry = ${JFROG_URL}/artifactory/api/npm/${REPOSITORY_NPM}
|
||||||
EOF
|
EOF
|
||||||
jf rt curl /api/npm/auth >> ~/.npmrc
|
jf rt curl /api/npm/auth >>~/.npmrc
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Configure the `pip` to use the Artifactory "python" repository.
|
# Configure the `pip` to use the Artifactory "python" repository.
|
||||||
@@ -33,7 +33,7 @@ if [ -z "${REPOSITORY_PYPI}" ]; then
|
|||||||
else
|
else
|
||||||
echo "🐍 Configuring pip..."
|
echo "🐍 Configuring pip..."
|
||||||
mkdir -p ~/.pip
|
mkdir -p ~/.pip
|
||||||
cat << EOF > ~/.pip/pip.conf
|
cat <<EOF >~/.pip/pip.conf
|
||||||
[global]
|
[global]
|
||||||
index-url = https://${ARTIFACTORY_USERNAME}:${ARTIFACTORY_ACCESS_TOKEN}@${JFROG_HOST}/artifactory/api/pypi/${REPOSITORY_PYPI}/simple
|
index-url = https://${ARTIFACTORY_USERNAME}:${ARTIFACTORY_ACCESS_TOKEN}@${JFROG_HOST}/artifactory/api/pypi/${REPOSITORY_PYPI}/simple
|
||||||
EOF
|
EOF
|
||||||
@@ -46,4 +46,4 @@ else
|
|||||||
echo "🐹 Configuring go..."
|
echo "🐹 Configuring go..."
|
||||||
export GOPROXY="https://${ARTIFACTORY_USERNAME}:${ARTIFACTORY_ACCESS_TOKEN}@${JFROG_HOST}/artifactory/api/go/${REPOSITORY_GO}"
|
export GOPROXY="https://${ARTIFACTORY_USERNAME}:${ARTIFACTORY_ACCESS_TOKEN}@${JFROG_HOST}/artifactory/api/go/${REPOSITORY_GO}"
|
||||||
fi
|
fi
|
||||||
echo "🥳 Configuration complete!"
|
echo "🥳 Configuration complete!"
|
||||||
|
|||||||
21
jupyter-notebook/README.md
Normal file
21
jupyter-notebook/README.md
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
display_name: Jupyter Notebook
|
||||||
|
description: A module that adds Jupyter Notebook in your Coder template.
|
||||||
|
icon: ../.icons/jupyter.svg
|
||||||
|
maintainer_github: coder
|
||||||
|
verified: true
|
||||||
|
tags: [jupyter, helper, ide, web]
|
||||||
|
---
|
||||||
|
|
||||||
|
# Jupyter Notebook
|
||||||
|
|
||||||
|
A module that adds Jupyter Notebook in your Coder template.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
```hcl
|
||||||
|
module "jupyter-notebook" {
|
||||||
|
source = "https://registry.coder.com/modules/jupyter-notebook"
|
||||||
|
agent_id = coder_agent.example.id
|
||||||
|
}
|
||||||
|
```
|
||||||
49
jupyter-notebook/main.tf
Normal file
49
jupyter-notebook/main.tf
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
terraform {
|
||||||
|
required_version = ">= 1.0"
|
||||||
|
|
||||||
|
required_providers {
|
||||||
|
coder = {
|
||||||
|
source = "coder/coder"
|
||||||
|
version = ">= 0.12"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Add required variables for your modules and remove any unneeded variables
|
||||||
|
variable "agent_id" {
|
||||||
|
type = string
|
||||||
|
description = "The ID of a Coder agent."
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "log_path" {
|
||||||
|
type = string
|
||||||
|
description = "The path to log jupyter notebook to."
|
||||||
|
default = "/tmp/jupyter-notebook.log"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "port" {
|
||||||
|
type = number
|
||||||
|
description = "The port to run jupyter-notebook on."
|
||||||
|
default = 19999
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "coder_script" "jupyter-notebook" {
|
||||||
|
agent_id = var.agent_id
|
||||||
|
display_name = "jupyter-notebook"
|
||||||
|
icon = "/icon/jupyter.svg"
|
||||||
|
script = templatefile("${path.module}/run.sh", {
|
||||||
|
LOG_PATH : var.log_path,
|
||||||
|
PORT : var.port
|
||||||
|
})
|
||||||
|
run_on_start = true
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "coder_app" "jupyter-notebook" {
|
||||||
|
agent_id = var.agent_id
|
||||||
|
slug = "jupyter-notebook"
|
||||||
|
display_name = "Jupyter Notebook"
|
||||||
|
url = "http://localhost:${var.port}"
|
||||||
|
icon = "/icon/jupyter.svg"
|
||||||
|
subdomain = true
|
||||||
|
share = "owner"
|
||||||
|
}
|
||||||
25
jupyter-notebook/run.sh
Executable file
25
jupyter-notebook/run.sh
Executable file
@@ -0,0 +1,25 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
BOLD='\033[0;1m'
|
||||||
|
|
||||||
|
printf "$${BOLD}Installing jupyter-notebook!\n"
|
||||||
|
|
||||||
|
# check if jupyter-notebook is installed
|
||||||
|
if ! command -v jupyter-notebook >/dev/null 2>&1; then
|
||||||
|
# install jupyter-notebook
|
||||||
|
# check if python3 pip is installed
|
||||||
|
if ! command -v pip3 >/dev/null 2>&1; then
|
||||||
|
echo "pip3 is not installed"
|
||||||
|
echo "Please install pip3 in your Dockerfile/VM image before running this script"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
# install jupyter-notebook
|
||||||
|
pip3 install --upgrade --no-cache-dir --no-warn-script-location jupyter
|
||||||
|
echo "🥳 jupyter-notebook has been installed\n\n"
|
||||||
|
else
|
||||||
|
echo "🥳 jupyter-notebook is already installed\n\n"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "👷 Starting jupyter-notebook in background..."
|
||||||
|
echo "check logs at ${LOG_PATH}"
|
||||||
|
$HOME/.local/bin/jupyter notebook --NotebookApp.ip='0.0.0.0' --ServerApp.port=${PORT} --no-browser --ServerApp.token='' --ServerApp.password='' >${LOG_PATH} 2>&1 &
|
||||||
@@ -2,13 +2,13 @@
|
|||||||
|
|
||||||
BOLD='\033[0;1m'
|
BOLD='\033[0;1m'
|
||||||
|
|
||||||
echo "$${BOLD}Installing jupyterlab!\n"
|
printf "$${BOLD}Installing jupyterlab!\n"
|
||||||
|
|
||||||
# check if jupyterlab is installed
|
# check if jupyterlab is installed
|
||||||
if ! command -v jupyterlab > /dev/null 2>&1; then
|
if ! command -v jupyterlab >/dev/null 2>&1; then
|
||||||
# install jupyterlab
|
# install jupyterlab
|
||||||
# check if python3 pip is installed
|
# check if python3 pip is installed
|
||||||
if ! command -v pip3 > /dev/null 2>&1; then
|
if ! command -v pip3 >/dev/null 2>&1; then
|
||||||
echo "pip3 is not installed"
|
echo "pip3 is not installed"
|
||||||
echo "Please install pip3 in your Dockerfile/VM image before running this script"
|
echo "Please install pip3 in your Dockerfile/VM image before running this script"
|
||||||
exit 1
|
exit 1
|
||||||
@@ -22,4 +22,4 @@ fi
|
|||||||
|
|
||||||
echo "👷 Starting jupyterlab in background..."
|
echo "👷 Starting jupyterlab in background..."
|
||||||
echo "check logs at ${LOG_PATH}"
|
echo "check logs at ${LOG_PATH}"
|
||||||
$HOME/.local/bin/jupyter lab --ServerApp.ip='0.0.0.0' --ServerApp.port=${PORT} --no-browser --ServerApp.token='' --ServerApp.password='' >${LOG_PATH} 2>&1 &
|
$HOME/.local/bin/jupyter lab --ServerApp.ip='0.0.0.0' --ServerApp.port=${PORT} --no-browser --ServerApp.token='' --ServerApp.password='' >${LOG_PATH} 2>&1 &
|
||||||
|
|||||||
96
lint.ts
Normal file
96
lint.ts
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
import { readFile, readdir, stat } from "fs/promises";
|
||||||
|
import * as path from "path";
|
||||||
|
import * as marked from "marked";
|
||||||
|
import grayMatter from "gray-matter";
|
||||||
|
|
||||||
|
const files = await readdir(".", { withFileTypes: true });
|
||||||
|
const dirs = files.filter(
|
||||||
|
(f) => f.isDirectory() && !f.name.startsWith(".") && f.name !== "node_modules"
|
||||||
|
);
|
||||||
|
|
||||||
|
let badExit = false;
|
||||||
|
|
||||||
|
// error reports an error to the console and sets badExit to true
|
||||||
|
// so that the process will exit with a non-zero exit code.
|
||||||
|
const error = (...data: any[]) => {
|
||||||
|
console.error(...data);
|
||||||
|
badExit = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensures that each README has the proper format.
|
||||||
|
// Exits with 0 if all is good!
|
||||||
|
for (const dir of dirs) {
|
||||||
|
const readme = path.join(dir.name, "README.md");
|
||||||
|
// Ensure exists
|
||||||
|
try {
|
||||||
|
await stat(readme);
|
||||||
|
} catch (ex) {
|
||||||
|
throw new Error(`Missing README.md in ${dir.name}`);
|
||||||
|
}
|
||||||
|
const content = await readFile(readme, "utf8");
|
||||||
|
const matter = grayMatter(content);
|
||||||
|
const data = matter.data as {
|
||||||
|
display_name?: string;
|
||||||
|
description?: string;
|
||||||
|
icon?: string;
|
||||||
|
maintainer_github?: string;
|
||||||
|
partner_github?: string;
|
||||||
|
verified?: boolean;
|
||||||
|
tags?: string[];
|
||||||
|
};
|
||||||
|
if (!data.display_name) {
|
||||||
|
error(dir.name, "missing display_name");
|
||||||
|
}
|
||||||
|
if (!data.description) {
|
||||||
|
error(dir.name, "missing description");
|
||||||
|
}
|
||||||
|
if (!data.icon) {
|
||||||
|
error(dir.name, "missing icon");
|
||||||
|
}
|
||||||
|
if (!data.maintainer_github) {
|
||||||
|
error(dir.name, "missing maintainer_github");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await stat(path.join(".", dir.name, data.icon));
|
||||||
|
} catch (ex) {
|
||||||
|
error(dir.name, "icon does not exist", data.icon);
|
||||||
|
}
|
||||||
|
|
||||||
|
const tokens = marked.lexer(content);
|
||||||
|
// Ensure there is an h1 and some text, then a code block
|
||||||
|
|
||||||
|
let h1 = false;
|
||||||
|
let code = false;
|
||||||
|
let paragraph = false;
|
||||||
|
|
||||||
|
for (const token of tokens) {
|
||||||
|
if (token.type === "heading" && token.depth === 1) {
|
||||||
|
h1 = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (h1 && token.type === "heading") {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (token.type === "paragraph") {
|
||||||
|
paragraph = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (token.type === "code") {
|
||||||
|
code = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!h1) {
|
||||||
|
error(dir.name, "missing h1");
|
||||||
|
}
|
||||||
|
if (!paragraph) {
|
||||||
|
error(dir.name, "missing paragraph after h1");
|
||||||
|
}
|
||||||
|
if (!code) {
|
||||||
|
error(dir.name, "missing example code block after paragraph");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (badExit) {
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
@@ -3,10 +3,13 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "bun test",
|
"test": "bun test",
|
||||||
"fmt": "bun x prettier -w **/*.ts **/*.md *.md && terraform fmt **/*.tf",
|
"fmt": "bun x prettier -w **/*.ts **/*.md *.md && terraform fmt **/*.tf",
|
||||||
"fmt:ci": "bun x prettier --check **/*.ts **/*.md *.md && terraform fmt -check **/*.tf"
|
"fmt:ci": "bun x prettier --check **/*.ts **/*.md *.md && terraform fmt -check **/*.tf",
|
||||||
|
"lint": "bun run lint.ts"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"bun-types": "^1.0.3"
|
"bun-types": "^1.0.3",
|
||||||
|
"gray-matter": "^4.0.3",
|
||||||
|
"marked": "^9.0.3"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"typescript": "^5.0.0"
|
"typescript": "^5.0.0"
|
||||||
|
|||||||
@@ -31,8 +31,9 @@ resource "coder_script" "personalize" {
|
|||||||
script = templatefile("${path.module}/run.sh", {
|
script = templatefile("${path.module}/run.sh", {
|
||||||
PERSONALIZE_PATH : var.path,
|
PERSONALIZE_PATH : var.path,
|
||||||
})
|
})
|
||||||
display_name = "Personalize"
|
display_name = "Personalize"
|
||||||
icon = "/icon/personalize.svg"
|
icon = "/icon/personalize.svg"
|
||||||
log_path = var.log_path
|
log_path = var.log_path
|
||||||
run_on_start = true
|
run_on_start = true
|
||||||
|
start_blocks_login = true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "esnext",
|
"target": "esnext",
|
||||||
"module": "esnext",
|
"module": "esnext",
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"moduleResolution": "nodenext",
|
||||||
"types": ["bun-types"]
|
"types": ["bun-types"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user