Add support for Codespaces (#3432)

* Create devcontainer.json

* WIP

* WIP

* WIP

* Create README.md

* Try to fix cypress issue

* Add extensions

* WIP

* Minor
This commit is contained in:
Louis Lam 2023-07-17 14:54:40 +08:00 committed by GitHub
parent 25c8196641
commit 084cf01fcd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 72 additions and 3 deletions

26
.devcontainer/README.md Normal file
View file

@ -0,0 +1,26 @@
# Codespaces
Now you can modifiy Uptime Kuma on your browser without setting up a local development.
![image](https://github.com/louislam/uptime-kuma/assets/1336778/31d9f06d-dd0b-4405-8e0d-a96586ee4595)
1. Click `Code` -> `Create codespace on master`
2. Wait a few minutes until you see there are two exposed ports
3. Go to the `3000` url, see if it is working
![image](https://github.com/louislam/uptime-kuma/assets/1336778/909b2eb4-4c5e-44e4-ac26-6d20ed856e7f)
## Frontend
Since it is using Vite.js, all frontend changes will be hot-reloaded. You don't need to restart the frontend, unless you try to add a new frontend dependency.
## Restart Backend
Sometimes you need to restart the backend after changed something.
1. Click `Terminal`
1. Click `Codespaces: server-dev` in the right panel
1. Press `Ctrl + C` to stop the server
2. Press `Up` to run `npm run start-server-dev`
![image](https://github.com/louislam/uptime-kuma/assets/1336778/e0c0a350-fe46-4588-9f37-e053c85834d1)

View file

@ -0,0 +1,23 @@
{
"image": "mcr.microsoft.com/devcontainers/javascript-node:dev-20-bookworm",
"features": {
"ghcr.io/devcontainers/features/github-cli:1": {}
},
"updateContentCommand": "npm ci",
"postCreateCommand": "",
"postAttachCommand": {
"frontend-dev": "npm run start-frontend-devcontainer",
"server-dev": "npm run start-server-dev",
"open-port": "gh codespace ports visibility 3001:public -c $CODESPACE_NAME"
},
"customizations": {
"vscode": {
"extensions": [
"streetsidesoftware.code-spell-checker",
"dbaeumer.vscode-eslint",
"GitHub.copilot"
]
}
},
"forwardPorts": [3000, 3001]
}

View file

@ -17,6 +17,7 @@ export default defineConfig({
}, },
define: { define: {
"FRONTEND_VERSION": JSON.stringify(process.env.npm_package_version), "FRONTEND_VERSION": JSON.stringify(process.env.npm_package_version),
"DEVCONTAINER": process.env.DEVCONTAINER,
}, },
plugins: [ plugins: [
commonjs(), commonjs(),

View file

@ -19,6 +19,7 @@
"lint": "npm run lint:js && npm run lint:style", "lint": "npm run lint:js && npm run lint:style",
"dev": "concurrently -k -r \"wait-on tcp:3000 && npm run start-server-dev \" \"npm run start-frontend-dev\"", "dev": "concurrently -k -r \"wait-on tcp:3000 && npm run start-server-dev \" \"npm run start-frontend-dev\"",
"start-frontend-dev": "cross-env NODE_ENV=development vite --host --config ./config/vite.config.js", "start-frontend-dev": "cross-env NODE_ENV=development vite --host --config ./config/vite.config.js",
"start-frontend-devcontainer": "cross-env NODE_ENV=development DEVCONTAINER=1 vite --host --config ./config/vite.config.js",
"start": "npm run start-server", "start": "npm run start-server",
"start-server": "node server/server.js", "start-server": "node server/server.js",
"start-server-dev": "cross-env NODE_ENV=development node server/server.js", "start-server-dev": "cross-env NODE_ENV=development node server/server.js",

View file

@ -1,9 +1,12 @@
import axios from "axios"; import axios from "axios";
import { getDevContainerServerHostname, isDevContainer } from "../util-frontend";
const env = process.env.NODE_ENV || "production"; const env = process.env.NODE_ENV || "production";
// change the axios base url for development // change the axios base url for development
if (env === "development" || localStorage.dev === "dev") { if (env === "development" && isDevContainer()) {
axios.defaults.baseURL = location.protocol + "//" + getDevContainerServerHostname();
} else if (env === "development" || localStorage.dev === "dev") {
axios.defaults.baseURL = location.protocol + "//" + location.hostname + ":3001"; axios.defaults.baseURL = location.protocol + "//" + location.hostname + ":3001";
} }

View file

@ -4,6 +4,7 @@ import jwtDecode from "jwt-decode";
import Favico from "favico.js"; import Favico from "favico.js";
import dayjs from "dayjs"; import dayjs from "dayjs";
import { DOWN, MAINTENANCE, PENDING, UP } from "../util.ts"; import { DOWN, MAINTENANCE, PENDING, UP } from "../util.ts";
import { getDevContainerServerHostname, isDevContainer } from "../util-frontend.js";
const toast = useToast(); const toast = useToast();
let socket; let socket;
@ -93,7 +94,9 @@ export default {
let wsHost; let wsHost;
const env = process.env.NODE_ENV || "production"; const env = process.env.NODE_ENV || "production";
if (env === "development" || localStorage.dev === "dev") { if (env === "development" && isDevContainer()) {
wsHost = protocol + getDevContainerServerHostname();
} else if (env === "development" || localStorage.dev === "dev") {
wsHost = protocol + location.hostname + ":3001"; wsHost = protocol + location.hostname + ":3001";
} else { } else {
wsHost = protocol + location.host; wsHost = protocol + location.host;

View file

@ -72,13 +72,25 @@ export function setPageLocale() {
*/ */
export function getResBaseURL() { export function getResBaseURL() {
const env = process.env.NODE_ENV; const env = process.env.NODE_ENV;
if (env === "development" || localStorage.dev === "dev") { if (env === "development" && isDevContainer()) {
return location.protocol + "//" + getDevContainerServerHostname();
} else if (env === "development" || localStorage.dev === "dev") {
return location.protocol + "//" + location.hostname + ":3001"; return location.protocol + "//" + location.hostname + ":3001";
} else { } else {
return ""; return "";
} }
} }
export function isDevContainer() {
// eslint-disable-next-line no-undef
return (typeof DEVCONTAINER === "number" && DEVCONTAINER === 1);
}
export function getDevContainerServerHostname() {
// replace -3000 with -3001
return location.hostname.replace(/-3000\.preview\.app\.github\.dev/, "-3001.preview.app.github.dev");
}
/** /**
* *
* @param {} mqtt wheather or not the regex should take into account the fact that it is an mqtt uri * @param {} mqtt wheather or not the regex should take into account the fact that it is an mqtt uri