Merge branch 'master' into 1.23.X-merge-to-2.X.X

# Conflicts:
#	docker/debian-base.dockerfile
#	package-lock.json
#	server/database.js
#	server/model/monitor.js
#	server/uptime-kuma-server.js
#	server/util-server.js
This commit is contained in:
Louis Lam 2023-11-13 21:15:51 +08:00
commit ace1fe00c2
316 changed files with 9487 additions and 4997 deletions

View file

@ -14,7 +14,8 @@
"vscode": { "vscode": {
"extensions": [ "extensions": [
"streetsidesoftware.code-spell-checker", "streetsidesoftware.code-spell-checker",
"dbaeumer.vscode-eslint" "dbaeumer.vscode-eslint",
"GitHub.copilot-chat"
] ]
} }
}, },

View file

@ -1,6 +1,6 @@
/.idea /.idea
/node_modules /node_modules
/data /data*
/cypress /cypress
/out /out
/test /test
@ -30,7 +30,6 @@ SECURITY.md
tsconfig.json tsconfig.json
.env .env
/tmp /tmp
/babel.config.js
/ecosystem.config.js /ecosystem.config.js
/extra/healthcheck.exe /extra/healthcheck.exe
/extra/healthcheck /extra/healthcheck

View file

@ -1,6 +1,7 @@
module.exports = { module.exports = {
ignorePatterns: [ ignorePatterns: [
"test/*", "test/*.js",
"test/cypress",
"server/modules/apicache/*", "server/modules/apicache/*",
"src/util.js" "src/util.js"
], ],
@ -14,13 +15,18 @@ module.exports = {
extends: [ extends: [
"eslint:recommended", "eslint:recommended",
"plugin:vue/vue3-recommended", "plugin:vue/vue3-recommended",
"plugin:jsdoc/recommended-error",
], ],
parser: "vue-eslint-parser", parser: "vue-eslint-parser",
parserOptions: { parserOptions: {
parser: "@babel/eslint-parser", parser: "@typescript-eslint/parser",
sourceType: "module", sourceType: "module",
requireConfigFile: false, requireConfigFile: false,
}, },
plugins: [
"jsdoc",
"@typescript-eslint",
],
rules: { rules: {
"yoda": "error", "yoda": "error",
eqeqeq: [ "warn", "smart" ], eqeqeq: [ "warn", "smart" ],
@ -71,7 +77,7 @@ module.exports = {
"no-var": "error", "no-var": "error",
"key-spacing": "warn", "key-spacing": "warn",
"keyword-spacing": "warn", "keyword-spacing": "warn",
"space-infix-ops": "warn", "space-infix-ops": "error",
"arrow-spacing": "warn", "arrow-spacing": "warn",
"no-trailing-spaces": "error", "no-trailing-spaces": "error",
"no-constant-condition": [ "error", { "no-constant-condition": [ "error", {
@ -97,7 +103,43 @@ module.exports = {
}], }],
"no-control-regex": "off", "no-control-regex": "off",
"one-var": [ "error", "never" ], "one-var": [ "error", "never" ],
"max-statements-per-line": [ "error", { "max": 1 }] "max-statements-per-line": [ "error", { "max": 1 }],
"jsdoc/check-tag-names": [
"error",
{
"definedTags": [ "link" ]
}
],
"jsdoc/no-undefined-types": "off",
"jsdoc/no-defaults": [
"error",
{ "noOptionalParamNames": true }
],
"jsdoc/require-throws": "warn",
"jsdoc/require-jsdoc": [
"error",
{
"require": {
"FunctionDeclaration": true,
"MethodDefinition": true,
}
}
],
"jsdoc/no-blank-block-descriptions": "error",
"jsdoc/require-returns-description": "warn",
"jsdoc/require-returns-check": [
"error",
{ "reportMissingReturnForUndefinedTypes": false }
],
"jsdoc/require-returns": [
"warn",
{
"forceRequireReturn": true,
"forceReturnsWithAsync": true
}
],
"jsdoc/require-param-type": "warn",
"jsdoc/require-param-description": "warn"
}, },
"overrides": [ "overrides": [
{ {
@ -122,6 +164,22 @@ module.exports = {
context: true, context: true,
jestPuppeteer: true, jestPuppeteer: true,
}, },
},
// Override for TypeScript
{
"files": [
"**/*.ts",
],
extends: [
"plugin:@typescript-eslint/recommended",
],
"rules": {
"jsdoc/require-returns-type": "off",
"jsdoc/require-param-type": "off",
"@typescript-eslint/no-explicit-any": "off",
"prefer-const": "off",
}
} }
] ]
}; };

View file

@ -12,8 +12,6 @@ labels:
DO NOT PROVIDE ANY DETAILS HERE. Please privately report to https://github.com/louislam/uptime-kuma/security/advisories/new. DO NOT PROVIDE ANY DETAILS HERE. Please privately report to https://github.com/louislam/uptime-kuma/security/advisories/new.
Why need this issue? It is because GitHub Advisory do not send a notification to @louislam, it is a workaround to do so. Why need this issue? It is because GitHub Advisory do not send a notification to @louislam, it is a workaround to do so.
Your GitHub Advisory URL: Your GitHub Advisory URL:

View file

@ -22,7 +22,7 @@ jobs:
strategy: strategy:
matrix: matrix:
os: [macos-latest, ubuntu-latest, windows-latest, ARM64] os: [macos-latest, ubuntu-latest, windows-latest, ARM64]
node: [ 14, 20 ] node: [ 14, 20.5 ]
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/ # See supported Node.js release schedule at https://nodejs.org/en/about/releases/
steps: steps:
@ -71,27 +71,28 @@ jobs:
- run: git config --global core.autocrlf false # Mainly for Windows - run: git config --global core.autocrlf false # Mainly for Windows
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Use Node.js 14 - name: Use Node.js 20
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
node-version: 14 node-version: 20
- run: npm install - run: npm install
- run: npm run lint - run: npm run lint
e2e-tests: # TODO: Temporarily disable, as it cannot pass the test in 2.0.0 yet
needs: [ check-linters ] # e2e-tests:
runs-on: ubuntu-latest # needs: [ check-linters ]
steps: # runs-on: ubuntu-latest
- run: git config --global core.autocrlf false # Mainly for Windows # steps:
- uses: actions/checkout@v3 # - run: git config --global core.autocrlf false # Mainly for Windows
# - uses: actions/checkout@v3
- name: Use Node.js 14 #
uses: actions/setup-node@v3 # - name: Use Node.js 14
with: # uses: actions/setup-node@v3
node-version: 14 # with:
- run: npm install # node-version: 14
- run: npm run build # - run: npm install
- run: npm run cy:test # - run: npm run build
# - run: npm run cy:test
frontend-unit-tests: frontend-unit-tests:
needs: [ check-linters ] needs: [ check-linters ]

43
.github/workflows/codeql-analysis.yml vendored Normal file
View file

@ -0,0 +1,43 @@
name: "CodeQL"
on:
push:
branches: [ "master", "1.23.X"]
pull_request:
branches: [ "master", "1.23.X"]
schedule:
- cron: '16 22 * * 0'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
timeout-minutes: 360
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'go', 'javascript-typescript' ]
steps:
- name: Checkout repository
uses: actions/checkout@v3
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
- name: Autobuild
uses: github/codeql-action/autobuild@v2
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
with:
category: "/language:${{matrix.language}}"

View file

@ -0,0 +1,17 @@
name: prevent-file-change
on:
pull_request:
jobs:
check-file-changes:
runs-on: ubuntu-latest
steps:
- name: Prevent file change
uses: xalvarez/prevent-file-change-action@v1
with:
githubToken: ${{ secrets.GITHUB_TOKEN }}
# Regex, /src/lang/*.json is not allowed to be changed, except for /src/lang/en.json
pattern: '^(?!src/lang/en\.json$)src/lang/.*\.json$'
trustedAuthors: UptimeKumaBot

1
.gitignore vendored
View file

@ -7,6 +7,7 @@ dist-ssr
/data /data
!/data/.gitkeep !/data/.gitkeep
/data*
.vscode .vscode
/private /private

View file

@ -34,18 +34,21 @@ Yes or no, it depends on what you will try to do. Since I don't want to waste yo
Here are some references: Here are some references:
### ✅ Usually accepted: ### ✅ Usually accepted
- Bug fix - Bug fix
- Security fix - Security fix
- Adding notification providers - Adding notification providers
- Adding new language files (see [these instructions](https://github.com/louislam/uptime-kuma/blob/master/src/lang/README.md)) - Adding new language files (see [these instructions](https://github.com/louislam/uptime-kuma/blob/master/src/lang/README.md))
- Adding new language keys: `$t("...")` - Adding new language keys: `$t("...")`
### ⚠️ Discussion required: ### ⚠️ Discussion required
- Large pull requests - Large pull requests
- New features - New features
### ❌ Won't be merged: ### ❌ Won't be merged
- A dedicated PR for translating existing languages (see [these instructions](https://github.com/louislam/uptime-kuma/blob/master/src/lang/README.md)) - A dedicated PR for translating existing languages (see [these instructions](https://github.com/louislam/uptime-kuma/blob/master/src/lang/README.md))
- Do not pass the auto-test - Do not pass the auto-test
- Any breaking changes - Any breaking changes
@ -65,7 +68,6 @@ I will assign your pull request to a [milestone](https://github.com/louislam/upt
Also, please don't rush or ask for an ETA, because I have to understand the pull request, make sure it is no breaking changes and stick to my vision of this project, especially for large pull requests. Also, please don't rush or ask for an ETA, because I have to understand the pull request, make sure it is no breaking changes and stick to my vision of this project, especially for large pull requests.
### Recommended Pull Request Guideline ### Recommended Pull Request Guideline
Before deep into coding, discussion first is preferred. Creating an empty pull request for discussion would be recommended. Before deep into coding, discussion first is preferred. Creating an empty pull request for discussion would be recommended.
@ -112,6 +114,18 @@ I personally do not like something that requires so many configurations before y
- IDE that supports [`ESLint`](https://eslint.org/) and EditorConfig (I am using [`IntelliJ IDEA`](https://www.jetbrains.com/idea/)) - IDE that supports [`ESLint`](https://eslint.org/) and EditorConfig (I am using [`IntelliJ IDEA`](https://www.jetbrains.com/idea/))
- A SQLite GUI tool (f.ex. [`SQLite Expert Personal`](https://www.sqliteexpert.com/download.html) or [`DBeaver Community`](https://dbeaver.io/download/)) - A SQLite GUI tool (f.ex. [`SQLite Expert Personal`](https://www.sqliteexpert.com/download.html) or [`DBeaver Community`](https://dbeaver.io/download/))
### GitHub Codespace
If you don't want to setup an local environment, you can now develop on GitHub Codespace, read more:
https://github.com/louislam/uptime-kuma/tree/master/.devcontainer
## Git Branches
- `master`: 2.X.X development. If you want to add a new feature, your pull request should base on this.
- `1.23.X`: 1.23.X development. If you want to fix a bug for v1 and v2, your pull request should base on this.
- All other branches are unused, outdated or for dev.
## Install Dependencies for Development ## Install Dependencies for Development
```bash ```bash
@ -131,7 +145,8 @@ npm run dev
``` ```
But sometimes, you would like to restart the server, but not the frontend, you can run these commands in two terminals: But sometimes, you would like to restart the server, but not the frontend, you can run these commands in two terminals:
```
```bash
npm run start-frontend-dev npm run start-frontend-dev
npm run start-server-dev npm run start-server-dev
``` ```
@ -140,15 +155,14 @@ npm run start-server-dev
It binds to `0.0.0.0:3001` by default. It binds to `0.0.0.0:3001` by default.
It is mainly a socket.io app + express.js. It is mainly a socket.io app + express.js.
express.js is used for: express.js is used for:
- entry point such as redirecting to a status page or the dashboard - entry point such as redirecting to a status page or the dashboard
- serving the frontend built files (index.html, .js and .css etc.) - serving the frontend built files (index.html, .js and .css etc.)
- serving internal APIs of the status page - serving internal APIs of the status page
### Structure in /server/ ### Structure in /server/
- jobs/ (Jobs that are running in another process) - jobs/ (Jobs that are running in another process)
@ -187,8 +201,7 @@ The data and socket logic are in `src/mixins/socket.js`.
## Database Migration ## Database Migration
1. Create `patch-{name}.sql` in `./db/` See: https://github.com/louislam/uptime-kuma/tree/master/db/knex_migrations
2. Add your patch filename in the `patchList` list in `./server/database.js`
## Unit Test ## Unit Test
@ -236,6 +249,42 @@ Since there is no way to make a pull request to wiki's repo, I have set up anoth
https://github.com/louislam/uptime-kuma-wiki https://github.com/louislam/uptime-kuma-wiki
## Docker
### Arch
- amd64
- arm64
- armv7
### Docker Tags
#### v2
- `2`, `latest-2`: v2 with full features such as Chromium and bundled MariaDB
- `2.x.x`
- `2-slim`: v2 with basic features
- `2.x.x-slim`
- `beta2`: Latest beta build
- `2.x.x-beta.x`
- `nightly2`: Dev build
- `base2`: Basic Debian setup without Uptime Kuma source code (Full features)
- `base2-slim`: Basic Debian setup without Uptime Kuma source code
- `pr-test2`: For testing pull request without setting up a local environment
#### v1
- `1`, `latest`, `1-debian`, `debian`: Latest version of v1
- `1.x.x`, `1.x.x-debian`
- `1.x.x-beta.x`: Beta build
- `beta`: Latest beta build
- `nightly`: Dev build
- `base-debian`: Basic Debian setup without Uptime Kuma source code
- `pr-test`: For testing pull request without setting up a local environment
- `base-alpine`: (Deprecated) Basic Alpine setup without Uptime Kuma source code
- `1-alpine`, `alpine`: (Deprecated)
- `1.x.x-alpine`: (Deprecated)
## Maintainer ## Maintainer
Check the latest issues and pull requests: Check the latest issues and pull requests:
@ -246,12 +295,12 @@ https://github.com/louislam/uptime-kuma/issues?q=sort%3Aupdated-desc
1. Draft a release note 1. Draft a release note
2. Make sure the repo is cleared 2. Make sure the repo is cleared
3. If the healthcheck is updated, remember to re-compile it: `npm run build-docker-builder-go` 3. If the healthcheck is updated, remember to re-compile it: `npm run build-docker-builder-go`
3. `npm run release-final with env vars: `VERSION` and `GITHUB_TOKEN` 4. `npm run release-final` with env vars: `VERSION` and `GITHUB_TOKEN`
4. Wait until the `Press any key to continue` 5. Wait until the `Press any key to continue`
5. `git push` 6. `git push`
6. Publish the release note as 1.X.X 7. Publish the release note as 1.X.X
7. Press any key to continue 8. Press any key to continue
8. Deploy to the demo server: `npm run deploy-demo-server` 9. Deploy to the demo server: `npm run deploy-demo-server`
Checking: Checking:
@ -284,3 +333,11 @@ git remote add production https://github.com/louislam/uptime-kuma.wiki.git
git pull git pull
git push production master git push production master
``` ```
## Useful Commands
Change the base of a pull request such as `master` to `1.23.X`
```bash
git rebase --onto <new parent> <old parent>
```

View file

@ -23,17 +23,17 @@ It is a temporary live demo, all data will be deleted after 10 minutes. Use the
## ⭐ Features ## ⭐ Features
* Monitoring uptime for HTTP(s) / TCP / HTTP(s) Keyword / HTTP(s) Json Query / Ping / DNS Record / Push / Steam Game Server / Docker Containers - Monitoring uptime for HTTP(s) / TCP / HTTP(s) Keyword / HTTP(s) Json Query / Ping / DNS Record / Push / Steam Game Server / Docker Containers
* Fancy, Reactive, Fast UI/UX - Fancy, Reactive, Fast UI/UX
* Notifications via Telegram, Discord, Gotify, Slack, Pushover, Email (SMTP), and [90+ notification services, click here for the full list](https://github.com/louislam/uptime-kuma/tree/master/src/components/notifications) - Notifications via Telegram, Discord, Gotify, Slack, Pushover, Email (SMTP), and [90+ notification services, click here for the full list](https://github.com/louislam/uptime-kuma/tree/master/src/components/notifications)
* 20-second intervals - 20-second intervals
* [Multi Languages](https://github.com/louislam/uptime-kuma/tree/master/src/lang) - [Multi Languages](https://github.com/louislam/uptime-kuma/tree/master/src/lang)
* Multiple status pages - Multiple status pages
* Map status pages to specific domains - Map status pages to specific domains
* Ping chart - Ping chart
* Certificate info - Certificate info
* Proxy support - Proxy support
* 2FA support - 2FA support
## 🔧 How to Install ## 🔧 How to Install
@ -43,25 +43,27 @@ It is a temporary live demo, all data will be deleted after 10 minutes. Use the
docker run -d --restart=always -p 3001:3001 -v uptime-kuma:/app/data --name uptime-kuma louislam/uptime-kuma:1 docker run -d --restart=always -p 3001:3001 -v uptime-kuma:/app/data --name uptime-kuma louislam/uptime-kuma:1
``` ```
⚠️ Please use a **local volume** only. Other types such as NFS are not supported.
Uptime Kuma is now running on http://localhost:3001 Uptime Kuma is now running on http://localhost:3001
> [!WARNING]
> File Systems like **NFS** (Network File System) are **NOT** supported. Please map to a local directory or volume.
### 💪🏻 Non-Docker ### 💪🏻 Non-Docker
Requirements: Requirements:
- Platform - Platform
- ✅ Major Linux distros such as Debian, Ubuntu, CentOS, Fedora and ArchLinux etc. - ✅ Major Linux distros such as Debian, Ubuntu, CentOS, Fedora and ArchLinux etc.
- ✅ Windows 10 (x64), Windows Server 2012 R2 (x64) or higher - ✅ Windows 10 (x64), Windows Server 2012 R2 (x64) or higher
- ❌ Replit / Heroku - ❌ Replit / Heroku
- [Node.js](https://nodejs.org/en/download/) 14 / 16 / 18 / 20.4 - [Node.js](https://nodejs.org/en/download/) 14 / 16 / 18 / 20.4
- [npm](https://docs.npmjs.com/cli/) >= 7 - [npm](https://docs.npmjs.com/cli/) 9
- [Git](https://git-scm.com/downloads) - [Git](https://git-scm.com/downloads)
- [pm2](https://pm2.keymetrics.io/) - For running Uptime Kuma in the background - [pm2](https://pm2.keymetrics.io/) - For running Uptime Kuma in the background
```bash ```bash
# Update your npm to the latest version # Update your npm
npm install npm -g npm install npm@9 -g
git clone https://github.com/louislam/uptime-kuma.git git clone https://github.com/louislam/uptime-kuma.git
cd uptime-kuma cd uptime-kuma
@ -76,9 +78,8 @@ npm install pm2 -g && pm2 install pm2-logrotate
# Start Server # Start Server
pm2 start server/server.js --name uptime-kuma pm2 start server/server.js --name uptime-kuma
``` ```
Uptime Kuma is now running on http://localhost:3001 Uptime Kuma is now running on http://localhost:3001
More useful PM2 Commands More useful PM2 Commands
@ -91,10 +92,6 @@ pm2 monit
pm2 save && pm2 startup pm2 save && pm2 startup
``` ```
### Windows Portable (x64)
https://github.com/louislam/uptime-kuma/releases/download/1.23.1/uptime-kuma-windows-x64-portable-1.23.1.zip
### Advanced Installation ### Advanced Installation
If you need more options or need to browse via a reverse proxy, please read: If you need more options or need to browse via a reverse proxy, please read:
@ -113,10 +110,6 @@ I will assign requests/issues to the next milestone.
https://github.com/louislam/uptime-kuma/milestones https://github.com/louislam/uptime-kuma/milestones
Project Plan:
https://github.com/users/louislam/projects/4/views/1
## ❤️ Sponsors ## ❤️ Sponsors
Thank you so much! (GitHub Sponsors will be updated manually. OpenCollective sponsors will be updated automatically, the list will be cached by GitHub though. It may need some time to be updated) Thank you so much! (GitHub Sponsors will be updated manually. OpenCollective sponsors will be updated automatically, the list will be cached by GitHub though. It may need some time to be updated)
@ -143,18 +136,18 @@ Telegram Notification Sample:
## Motivation ## Motivation
* I was looking for a self-hosted monitoring tool like "Uptime Robot", but it is hard to find a suitable one. One of the close ones is statping. Unfortunately, it is not stable and no longer maintained. - I was looking for a self-hosted monitoring tool like "Uptime Robot", but it is hard to find a suitable one. One of the close ones is statping. Unfortunately, it is not stable and no longer maintained.
* Want to build a fancy UI. - Want to build a fancy UI.
* Learn Vue 3 and vite.js. - Learn Vue 3 and vite.js.
* Show the power of Bootstrap 5. - Show the power of Bootstrap 5.
* Try to use WebSocket with SPA instead of REST API. - Try to use WebSocket with SPA instead of REST API.
* Deploy my first Docker image to Docker Hub. - Deploy my first Docker image to Docker Hub.
If you love this project, please consider giving me a ⭐. If you love this project, please consider giving me a ⭐.
## 🗣️ Discussion / Ask for Help ## 🗣️ Discussion / Ask for Help
⚠️ For any general or technical questions, please don't send me an email, as I am unable to provide support in that manner. I will not response if you asked such questions. ⚠️ For any general or technical questions, please don't send me an email, as I am unable to provide support in that manner. I will not respond if you asked such questions.
I recommend using Google, GitHub Issues, or Uptime Kuma's Subreddit for finding answers to your question. If you cannot find the information you need, feel free to ask: I recommend using Google, GitHub Issues, or Uptime Kuma's Subreddit for finding answers to your question. If you cannot find the information you need, feel free to ask:
@ -164,7 +157,6 @@ I recommend using Google, GitHub Issues, or Uptime Kuma's Subreddit for finding
My Reddit account: [u/louislamlam](https://reddit.com/u/louislamlam). My Reddit account: [u/louislamlam](https://reddit.com/u/louislamlam).
You can mention me if you ask a question on Reddit. You can mention me if you ask a question on Reddit.
## Contribute ## Contribute
### Test Pull Requests ### Test Pull Requests
@ -179,15 +171,18 @@ https://github.com/louislam/uptime-kuma/wiki/Test-Pull-Requests
Check out the latest beta release here: https://github.com/louislam/uptime-kuma/releases Check out the latest beta release here: https://github.com/louislam/uptime-kuma/releases
### Bug Reports / Feature Requests ### Bug Reports / Feature Requests
If you want to report a bug or request a new feature, feel free to open a [new issue](https://github.com/louislam/uptime-kuma/issues). If you want to report a bug or request a new feature, feel free to open a [new issue](https://github.com/louislam/uptime-kuma/issues).
### Translations ### Translations
If you want to translate Uptime Kuma into your language, please visit [Weblate Readme](https://github.com/louislam/uptime-kuma/blob/master/src/lang/README.md). If you want to translate Uptime Kuma into your language, please visit [Weblate Readme](https://github.com/louislam/uptime-kuma/blob/master/src/lang/README.md).
## Spelling & Grammar ### Spelling & Grammar
Feel free to correct the grammar in the documentation or code. Feel free to correct the grammar in the documentation or code.
My mother language is not english and my grammar is not that great. My mother language is not english and my grammar is not that great.
### Create Pull Requests ### Create Pull Requests
If you want to modify Uptime Kuma, please read this guide and follow the rules here: https://github.com/louislam/uptime-kuma/blob/master/CONTRIBUTING.md If you want to modify Uptime Kuma, please read this guide and follow the rules here: https://github.com/louislam/uptime-kuma/blob/master/CONTRIBUTING.md

View file

@ -1,7 +0,0 @@
const config = {};
if (process.env.TEST_FRONTEND) {
config.presets = [ "@babel/preset-env" ];
}
module.exports = config;

View file

@ -1,4 +1,3 @@
import legacy from "@vitejs/plugin-legacy";
import vue from "@vitejs/plugin-vue"; import vue from "@vitejs/plugin-vue";
import { defineConfig } from "vite"; import { defineConfig } from "vite";
import visualizer from "rollup-plugin-visualizer"; import visualizer from "rollup-plugin-visualizer";
@ -24,9 +23,6 @@ export default defineConfig({
plugins: [ plugins: [
commonjs(), commonjs(),
vue(), vue(),
legacy({
targets: [ "since 2015" ],
}),
visualizer({ visualizer({
filename: "tmp/dist-stats.html" filename: "tmp/dist-stats.html"
}), }),

559
db/knex_init_db.js Normal file
View file

@ -0,0 +1,559 @@
const { R } = require("redbean-node");
const { log } = require("../src/util");
/**
* DO NOT ADD ANYTHING HERE!
* IF YOU NEED TO ADD FIELDS, ADD IT TO ./db/knex_migrations
* See ./db/knex_migrations/README.md for more information
* @returns {Promise<void>}
*/
async function createTables() {
log.info("mariadb", "Creating basic tables for MariaDB");
const knex = R.knex;
// TODO: Should check later if it is really the final patch sql file.
// docker_host
await knex.schema.createTable("docker_host", (table) => {
table.increments("id");
table.integer("user_id").unsigned().notNullable();
table.string("docker_daemon", 255);
table.string("docker_type", 255);
table.string("name", 255);
});
// group
await knex.schema.createTable("group", (table) => {
table.increments("id");
table.string("name", 255).notNullable();
table.datetime("created_date").notNullable().defaultTo(knex.fn.now());
table.boolean("public").notNullable().defaultTo(false);
table.boolean("active").notNullable().defaultTo(true);
table.integer("weight").notNullable().defaultTo(1000);
table.integer("status_page_id").unsigned();
});
// proxy
await knex.schema.createTable("proxy", (table) => {
table.increments("id");
table.integer("user_id").unsigned().notNullable();
table.string("protocol", 10).notNullable();
table.string("host", 255).notNullable();
table.smallint("port").notNullable(); // TODO: Maybe a issue with MariaDB, need migration to int
table.boolean("auth").notNullable();
table.string("username", 255).nullable();
table.string("password", 255).nullable();
table.boolean("active").notNullable().defaultTo(true);
table.boolean("default").notNullable().defaultTo(false);
table.datetime("created_date").notNullable().defaultTo(knex.fn.now());
table.index("user_id", "proxy_user_id");
});
// user
await knex.schema.createTable("user", (table) => {
table.increments("id");
table.string("username", 255).notNullable().unique().collate("utf8_general_ci");
table.string("password", 255);
table.boolean("active").notNullable().defaultTo(true);
table.string("timezone", 150);
table.string("twofa_secret", 64);
table.boolean("twofa_status").notNullable().defaultTo(false);
table.string("twofa_last_token", 6);
});
// monitor
await knex.schema.createTable("monitor", (table) => {
table.increments("id");
table.string("name", 150);
table.boolean("active").notNullable().defaultTo(true);
table.integer("user_id").unsigned()
.references("id").inTable("user")
.onDelete("SET NULL")
.onUpdate("CASCADE");
table.integer("interval").notNullable().defaultTo(20);
table.text("url");
table.string("type", 20);
table.integer("weight").defaultTo(2000);
table.string("hostname", 255);
table.integer("port");
table.datetime("created_date").notNullable().defaultTo(knex.fn.now());
table.string("keyword", 255);
table.integer("maxretries").notNullable().defaultTo(0);
table.boolean("ignore_tls").notNullable().defaultTo(false);
table.boolean("upside_down").notNullable().defaultTo(false);
table.integer("maxredirects").notNullable().defaultTo(10);
table.text("accepted_statuscodes_json").notNullable().defaultTo("[\"200-299\"]");
table.string("dns_resolve_type", 5);
table.string("dns_resolve_server", 255);
table.string("dns_last_result", 255);
table.integer("retry_interval").notNullable().defaultTo(0);
table.string("push_token", 20).defaultTo(null);
table.text("method").notNullable().defaultTo("GET");
table.text("body").defaultTo(null);
table.text("headers").defaultTo(null);
table.text("basic_auth_user").defaultTo(null);
table.text("basic_auth_pass").defaultTo(null);
table.integer("docker_host").unsigned()
.references("id").inTable("docker_host");
table.string("docker_container", 255);
table.integer("proxy_id").unsigned()
.references("id").inTable("proxy");
table.boolean("expiry_notification").defaultTo(true);
table.text("mqtt_topic");
table.string("mqtt_success_message", 255);
table.string("mqtt_username", 255);
table.string("mqtt_password", 255);
table.string("database_connection_string", 2000);
table.text("database_query");
table.string("auth_method", 250);
table.text("auth_domain");
table.text("auth_workstation");
table.string("grpc_url", 255).defaultTo(null);
table.text("grpc_protobuf").defaultTo(null);
table.text("grpc_body").defaultTo(null);
table.text("grpc_metadata").defaultTo(null);
table.text("grpc_method").defaultTo(null);
table.text("grpc_service_name").defaultTo(null);
table.boolean("grpc_enable_tls").notNullable().defaultTo(false);
table.string("radius_username", 255);
table.string("radius_password", 255);
table.string("radius_calling_station_id", 50);
table.string("radius_called_station_id", 50);
table.string("radius_secret", 255);
table.integer("resend_interval").notNullable().defaultTo(0);
table.integer("packet_size").notNullable().defaultTo(56);
table.string("game", 255);
});
// heartbeat
await knex.schema.createTable("heartbeat", (table) => {
table.increments("id");
table.boolean("important").notNullable().defaultTo(false);
table.integer("monitor_id").unsigned().notNullable()
.references("id").inTable("monitor")
.onDelete("CASCADE")
.onUpdate("CASCADE");
table.smallint("status").notNullable();
table.text("msg");
table.datetime("time").notNullable();
table.integer("ping");
table.integer("duration").notNullable().defaultTo(0);
table.integer("down_count").notNullable().defaultTo(0);
table.index("important");
table.index([ "monitor_id", "time" ], "monitor_time_index");
table.index("monitor_id");
table.index([ "monitor_id", "important", "time" ], "monitor_important_time_index");
});
// incident
await knex.schema.createTable("incident", (table) => {
table.increments("id");
table.string("title", 255).notNullable();
table.text("content", 255).notNullable();
table.string("style", 30).notNullable().defaultTo("warning");
table.datetime("created_date").notNullable().defaultTo(knex.fn.now());
table.datetime("last_updated_date");
table.boolean("pin").notNullable().defaultTo(true);
table.boolean("active").notNullable().defaultTo(true);
table.integer("status_page_id").unsigned();
});
// maintenance
await knex.schema.createTable("maintenance", (table) => {
table.increments("id");
table.string("title", 150).notNullable();
table.text("description").notNullable();
table.integer("user_id").unsigned()
.references("id").inTable("user")
.onDelete("SET NULL")
.onUpdate("CASCADE");
table.boolean("active").notNullable().defaultTo(true);
table.string("strategy", 50).notNullable().defaultTo("single");
table.datetime("start_date");
table.datetime("end_date");
table.time("start_time");
table.time("end_time");
table.string("weekdays", 250).defaultTo("[]");
table.text("days_of_month").defaultTo("[]");
table.integer("interval_day");
table.index("active");
table.index([ "strategy", "active" ], "manual_active");
table.index("user_id", "maintenance_user_id");
});
// status_page
await knex.schema.createTable("status_page", (table) => {
table.increments("id");
table.string("slug", 255).notNullable().unique().collate("utf8_general_ci");
table.string("title", 255).notNullable();
table.text("description");
table.string("icon", 255).notNullable();
table.string("theme", 30).notNullable();
table.boolean("published").notNullable().defaultTo(true);
table.boolean("search_engine_index").notNullable().defaultTo(true);
table.boolean("show_tags").notNullable().defaultTo(false);
table.string("password");
table.datetime("created_date").notNullable().defaultTo(knex.fn.now());
table.datetime("modified_date").notNullable().defaultTo(knex.fn.now());
table.text("footer_text");
table.text("custom_css");
table.boolean("show_powered_by").notNullable().defaultTo(true);
table.string("google_analytics_tag_id");
});
// maintenance_status_page
await knex.schema.createTable("maintenance_status_page", (table) => {
table.increments("id");
table.integer("status_page_id").unsigned().notNullable()
.references("id").inTable("status_page")
.onDelete("CASCADE")
.onUpdate("CASCADE");
table.integer("maintenance_id").unsigned().notNullable()
.references("id").inTable("maintenance")
.onDelete("CASCADE")
.onUpdate("CASCADE");
});
// maintenance_timeslot
await knex.schema.createTable("maintenance_timeslot", (table) => {
table.increments("id");
table.integer("maintenance_id").unsigned().notNullable()
.references("id").inTable("maintenance")
.onDelete("CASCADE")
.onUpdate("CASCADE");
table.datetime("start_date").notNullable();
table.datetime("end_date");
table.boolean("generated_next").defaultTo(false);
table.index("maintenance_id");
table.index([ "maintenance_id", "start_date", "end_date" ], "active_timeslot_index");
table.index("generated_next", "generated_next_index");
});
// monitor_group
await knex.schema.createTable("monitor_group", (table) => {
table.increments("id");
table.integer("monitor_id").unsigned().notNullable()
.references("id").inTable("monitor")
.onDelete("CASCADE")
.onUpdate("CASCADE");
table.integer("group_id").unsigned().notNullable()
.references("id").inTable("group")
.onDelete("CASCADE")
.onUpdate("CASCADE");
table.integer("weight").notNullable().defaultTo(1000);
table.boolean("send_url").notNullable().defaultTo(false);
table.index([ "monitor_id", "group_id" ], "fk");
});
// monitor_maintenance
await knex.schema.createTable("monitor_maintenance", (table) => {
table.increments("id");
table.integer("monitor_id").unsigned().notNullable()
.references("id").inTable("monitor")
.onDelete("CASCADE")
.onUpdate("CASCADE");
table.integer("maintenance_id").unsigned().notNullable()
.references("id").inTable("maintenance")
.onDelete("CASCADE")
.onUpdate("CASCADE");
table.index("maintenance_id", "maintenance_id_index2");
table.index("monitor_id", "monitor_id_index");
});
// notification
await knex.schema.createTable("notification", (table) => {
table.increments("id");
table.string("name", 255);
table.boolean("active").notNullable().defaultTo(true);
table.integer("user_id").unsigned();
table.boolean("is_default").notNullable().defaultTo(false);
table.text("config", "longtext");
});
// monitor_notification
await knex.schema.createTable("monitor_notification", (table) => {
table.increments("id").unsigned(); // TODO: no auto increment????
table.integer("monitor_id").unsigned().notNullable()
.references("id").inTable("monitor")
.onDelete("CASCADE")
.onUpdate("CASCADE");
table.integer("notification_id").unsigned().notNullable()
.references("id").inTable("notification")
.onDelete("CASCADE")
.onUpdate("CASCADE");
table.index([ "monitor_id", "notification_id" ], "monitor_notification_index");
});
// tag
await knex.schema.createTable("tag", (table) => {
table.increments("id");
table.string("name", 255).notNullable();
table.string("color", 255).notNullable();
table.datetime("created_date").notNullable().defaultTo(knex.fn.now());
});
// monitor_tag
await knex.schema.createTable("monitor_tag", (table) => {
table.increments("id");
table.integer("monitor_id").unsigned().notNullable()
.references("id").inTable("monitor")
.onDelete("CASCADE")
.onUpdate("CASCADE");
table.integer("tag_id").unsigned().notNullable()
.references("id").inTable("tag")
.onDelete("CASCADE")
.onUpdate("CASCADE");
table.text("value");
});
// monitor_tls_info
await knex.schema.createTable("monitor_tls_info", (table) => {
table.increments("id");
table.integer("monitor_id").unsigned().notNullable(); //TODO: no fk ?
table.text("info_json");
});
// notification_sent_history
await knex.schema.createTable("notification_sent_history", (table) => {
table.increments("id");
table.string("type", 50).notNullable();
table.integer("monitor_id").unsigned().notNullable();
table.integer("days").notNullable();
table.unique([ "type", "monitor_id", "days" ]);
table.index([ "type", "monitor_id", "days" ], "good_index");
});
// setting
await knex.schema.createTable("setting", (table) => {
table.increments("id");
table.string("key", 200).notNullable().unique().collate("utf8_general_ci");
table.text("value");
table.string("type", 20);
});
// status_page_cname
await knex.schema.createTable("status_page_cname", (table) => {
table.increments("id");
table.integer("status_page_id").unsigned()
.references("id").inTable("status_page")
.onDelete("CASCADE")
.onUpdate("CASCADE");
table.string("domain").notNullable().unique().collate("utf8_general_ci");
});
/*********************
* Converted Patch here
*********************/
// 2023-06-30-1348-http-body-encoding.js
// ALTER TABLE monitor ADD http_body_encoding VARCHAR(25);
// UPDATE monitor SET http_body_encoding = 'json' WHERE (type = 'http' or type = 'keyword') AND http_body_encoding IS NULL;
await knex.schema.table("monitor", function (table) {
table.string("http_body_encoding", 25);
});
await knex("monitor")
.where(function () {
this.where("type", "http").orWhere("type", "keyword");
})
.whereNull("http_body_encoding")
.update({
http_body_encoding: "json",
});
// 2023-06-30-1354-add-description-monitor.js
// ALTER TABLE monitor ADD description TEXT default null;
await knex.schema.table("monitor", function (table) {
table.text("description").defaultTo(null);
});
// 2023-06-30-1357-api-key-table.js
/*
CREATE TABLE [api_key] (
[id] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
[key] VARCHAR(255) NOT NULL,
[name] VARCHAR(255) NOT NULL,
[user_id] INTEGER NOT NULL,
[created_date] DATETIME DEFAULT (DATETIME('now')) NOT NULL,
[active] BOOLEAN DEFAULT 1 NOT NULL,
[expires] DATETIME DEFAULT NULL,
CONSTRAINT FK_user FOREIGN KEY ([user_id]) REFERENCES [user]([id]) ON DELETE CASCADE ON UPDATE CASCADE
);
*/
await knex.schema.createTable("api_key", function (table) {
table.increments("id").primary();
table.string("key", 255).notNullable();
table.string("name", 255).notNullable();
table.integer("user_id").unsigned().notNullable()
.references("id").inTable("user")
.onDelete("CASCADE")
.onUpdate("CASCADE");
table.dateTime("created_date").defaultTo(knex.fn.now()).notNullable();
table.boolean("active").defaultTo(1).notNullable();
table.dateTime("expires").defaultTo(null);
});
// 2023-06-30-1400-monitor-tls.js
/*
ALTER TABLE monitor
ADD tls_ca TEXT default null;
ALTER TABLE monitor
ADD tls_cert TEXT default null;
ALTER TABLE monitor
ADD tls_key TEXT default null;
*/
await knex.schema.table("monitor", function (table) {
table.text("tls_ca").defaultTo(null);
table.text("tls_cert").defaultTo(null);
table.text("tls_key").defaultTo(null);
});
// 2023-06-30-1401-maintenance-cron.js
/*
-- 999 characters. https://stackoverflow.com/questions/46134830/maximum-length-for-cron-job
DROP TABLE maintenance_timeslot;
ALTER TABLE maintenance ADD cron TEXT;
ALTER TABLE maintenance ADD timezone VARCHAR(255);
ALTER TABLE maintenance ADD duration INTEGER;
*/
await knex.schema
.dropTableIfExists("maintenance_timeslot")
.table("maintenance", function (table) {
table.text("cron");
table.string("timezone", 255);
table.integer("duration");
});
// 2023-06-30-1413-add-parent-monitor.js.
/*
ALTER TABLE monitor
ADD parent INTEGER REFERENCES [monitor] ([id]) ON DELETE SET NULL ON UPDATE CASCADE;
*/
await knex.schema.table("monitor", function (table) {
table.integer("parent").unsigned()
.references("id").inTable("monitor")
.onDelete("SET NULL")
.onUpdate("CASCADE");
});
/*
patch-add-invert-keyword.sql
ALTER TABLE monitor
ADD invert_keyword BOOLEAN default 0 not null;
*/
await knex.schema.table("monitor", function (table) {
table.boolean("invert_keyword").defaultTo(0).notNullable();
});
/*
patch-added-json-query.sql
ALTER TABLE monitor
ADD json_path TEXT;
ALTER TABLE monitor
ADD expected_value VARCHAR(255);
*/
await knex.schema.table("monitor", function (table) {
table.text("json_path");
table.string("expected_value", 255);
});
/*
patch-added-kafka-producer.sql
ALTER TABLE monitor
ADD kafka_producer_topic VARCHAR(255);
ALTER TABLE monitor
ADD kafka_producer_brokers TEXT;
ALTER TABLE monitor
ADD kafka_producer_ssl INTEGER;
ALTER TABLE monitor
ADD kafka_producer_allow_auto_topic_creation VARCHAR(255);
ALTER TABLE monitor
ADD kafka_producer_sasl_options TEXT;
ALTER TABLE monitor
ADD kafka_producer_message TEXT;
*/
await knex.schema.table("monitor", function (table) {
table.string("kafka_producer_topic", 255);
table.text("kafka_producer_brokers");
table.integer("kafka_producer_ssl");
table.string("kafka_producer_allow_auto_topic_creation", 255);
table.text("kafka_producer_sasl_options");
table.text("kafka_producer_message");
});
/*
patch-add-certificate-expiry-status-page.sql
ALTER TABLE status_page
ADD show_certificate_expiry BOOLEAN default 0 NOT NULL;
*/
await knex.schema.table("status_page", function (table) {
table.boolean("show_certificate_expiry").defaultTo(0).notNullable();
});
/*
patch-monitor-oauth-cc.sql
ALTER TABLE monitor
ADD oauth_client_id TEXT default null;
ALTER TABLE monitor
ADD oauth_client_secret TEXT default null;
ALTER TABLE monitor
ADD oauth_token_url TEXT default null;
ALTER TABLE monitor
ADD oauth_scopes TEXT default null;
ALTER TABLE monitor
ADD oauth_auth_method TEXT default null;
*/
await knex.schema.table("monitor", function (table) {
table.text("oauth_client_id").defaultTo(null);
table.text("oauth_client_secret").defaultTo(null);
table.text("oauth_token_url").defaultTo(null);
table.text("oauth_scopes").defaultTo(null);
table.text("oauth_auth_method").defaultTo(null);
});
/*
patch-add-timeout-monitor.sql
ALTER TABLE monitor
ADD timeout DOUBLE default 0 not null;
*/
await knex.schema.table("monitor", function (table) {
table.double("timeout").defaultTo(0).notNullable();
});
/*
patch-add-gamedig-given-port.sql
ALTER TABLE monitor
ADD gamedig_given_port_only BOOLEAN default 1 not null;
*/
await knex.schema.table("monitor", function (table) {
table.boolean("gamedig_given_port_only").defaultTo(1).notNullable();
});
log.info("mariadb", "Created basic tables for MariaDB");
}
module.exports = {
createTables,
};

View file

@ -0,0 +1,41 @@
exports.up = function (knex) {
return knex.schema
.createTable("stat_minutely", function (table) {
table.increments("id");
table.comment("This table contains the minutely aggregate statistics for each monitor");
table.integer("monitor_id").unsigned().notNullable()
.references("id").inTable("monitor")
.onDelete("CASCADE")
.onUpdate("CASCADE");
table.integer("timestamp")
.notNullable()
.comment("Unix timestamp rounded down to the nearest minute");
table.float("ping").notNullable().comment("Average ping in milliseconds");
table.smallint("up").notNullable();
table.smallint("down").notNullable();
table.unique([ "monitor_id", "timestamp" ]);
})
.createTable("stat_daily", function (table) {
table.increments("id");
table.comment("This table contains the daily aggregate statistics for each monitor");
table.integer("monitor_id").unsigned().notNullable()
.references("id").inTable("monitor")
.onDelete("CASCADE")
.onUpdate("CASCADE");
table.integer("timestamp")
.notNullable()
.comment("Unix timestamp rounded down to the nearest day");
table.float("ping").notNullable().comment("Average ping in milliseconds");
table.smallint("up").notNullable();
table.smallint("down").notNullable();
table.unique([ "monitor_id", "timestamp" ]);
});
};
exports.down = function (knex) {
return knex.schema
.dropTable("stat_minutely")
.dropTable("stat_daily");
};

View file

@ -0,0 +1,16 @@
exports.up = function (knex) {
// Add new column heartbeat.end_time
return knex.schema
.alterTable("heartbeat", function (table) {
table.datetime("end_time").nullable().defaultTo(null);
});
};
exports.down = function (knex) {
// Rename heartbeat.start_time to heartbeat.time
return knex.schema
.alterTable("heartbeat", function (table) {
table.dropColumn("end_time");
});
};

View file

@ -0,0 +1,14 @@
exports.up = function (knex) {
// update monitor.push_token to 32 length
return knex.schema
.alterTable("monitor", function (table) {
table.string("push_token", 32).alter();
});
};
exports.down = function (knex) {
return knex.schema
.alterTable("monitor", function (table) {
table.string("push_token", 20).alter();
});
};

View file

@ -0,0 +1,56 @@
# Info
https://knexjs.org/guide/migrations.html#knexfile-in-other-languages
## Basic rules
- All tables must have a primary key named `id`
- Filename format: `YYYY-MM-DD-HHMM-patch-name.js`
- Avoid native SQL syntax, use knex methods, because Uptime Kuma supports SQLite and MariaDB.
## Template
```js
exports.up = function(knex) {
};
exports.down = function(knex) {
};
// exports.config = { transaction: false };
```
## Example
Filename: 2023-06-30-1348-create-user-and-product.js
```js
exports.up = function(knex) {
return knex.schema
.createTable('user', function (table) {
table.increments('id');
table.string('first_name', 255).notNullable();
table.string('last_name', 255).notNullable();
})
.createTable('product', function (table) {
table.increments('id');
table.decimal('price').notNullable();
table.string('name', 1000).notNullable();
}).then(() => {
knex("products").insert([
{ price: 10, name: "Apple" },
{ price: 20, name: "Orange" },
]);
});
};
exports.down = function(knex) {
return knex.schema
.dropTable("product")
.dropTable("user");
};
```
https://knexjs.org/guide/migrations.html#transactions-in-migrations

View file

@ -0,0 +1,3 @@
# Don't create a new migration file here
Please go to ./db/knex_migrations/README.md

View file

@ -1,5 +1,7 @@
-- You should not modify if this have pushed to Github, unless it does serious wrong with the db. -- You should not modify if this have pushed to Github, unless it does serious wrong with the db.
BEGIN TRANSACTION; BEGIN TRANSACTION;
ALTER TABLE monitor_group ALTER TABLE monitor_group
ADD send_url BOOLEAN DEFAULT 0 NOT NULL; ADD send_url BOOLEAN DEFAULT 0 NOT NULL;
COMMIT; COMMIT;

View file

@ -1,4 +1,7 @@
-- You should not modify if this have pushed to Github, unless it does serious wrong with the db. -- You should not modify if this have pushed to Github, unless it does serious wrong with the db.
BEGIN TRANSACTION; BEGIN TRANSACTION;
ALTER TABLE status_page ADD google_analytics_tag_id VARCHAR;
ALTER TABLE monitor
ADD game VARCHAR(255);
COMMIT; COMMIT;

View file

@ -0,0 +1,7 @@
-- You should not modify if this have pushed to Github, unless it does serious wrong with the db.
BEGIN TRANSACTION;
ALTER TABLE status_page
ADD google_analytics_tag_id VARCHAR;
COMMIT;

View file

@ -1,6 +1,7 @@
-- You should not modify if this have pushed to Github, unless it does serious wrong with the db.
BEGIN TRANSACTION; BEGIN TRANSACTION;
ALTER TABLE monitor ALTER TABLE monitor
ADD parent INTEGER REFERENCES [monitor] ([id]) ON DELETE SET NULL ON UPDATE CASCADE; ADD parent INTEGER REFERENCES [monitor] ([id]) ON DELETE SET NULL ON UPDATE CASCADE;
COMMIT COMMIT;

View file

@ -1,3 +1,4 @@
-- You should not modify if this have pushed to Github, unless it does serious wrong with the db.
BEGIN TRANSACTION; BEGIN TRANSACTION;
ALTER TABLE monitor ALTER TABLE monitor
@ -15,4 +16,4 @@ ALTER TABLE monitor
ALTER TABLE monitor ALTER TABLE monitor
ADD radius_secret VARCHAR(255); ADD radius_secret VARCHAR(255);
COMMIT COMMIT;

View file

@ -3,4 +3,5 @@ BEGIN TRANSACTION;
ALTER TABLE monitor ALTER TABLE monitor
ADD timeout DOUBLE default 0 not null; ADD timeout DOUBLE default 0 not null;
COMMIT; COMMIT;

View file

@ -1,5 +1,6 @@
-- You should not modify if this have pushed to Github, unless it does serious wrong with the db. -- You should not modify if this have pushed to Github, unless it does serious wrong with the db.
BEGIN TRANSACTION; BEGIN TRANSACTION;
CREATE TABLE [api_key] ( CREATE TABLE [api_key] (
[id] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, [id] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
[key] VARCHAR(255) NOT NULL, [key] VARCHAR(255) NOT NULL,
@ -10,4 +11,5 @@ CREATE TABLE [api_key] (
[expires] DATETIME DEFAULT NULL, [expires] DATETIME DEFAULT NULL,
CONSTRAINT FK_user FOREIGN KEY ([user_id]) REFERENCES [user]([id]) ON DELETE CASCADE ON UPDATE CASCADE CONSTRAINT FK_user FOREIGN KEY ([user_id]) REFERENCES [user]([id]) ON DELETE CASCADE ON UPDATE CASCADE
); );
COMMIT; COMMIT;

View file

@ -1,5 +1,7 @@
-- You should not modify if this have pushed to Github, unless it does serious wrong with the db. -- You should not modify if this have pushed to Github, unless it does serious wrong with the db.
BEGIN TRANSACTION; BEGIN TRANSACTION;
ALTER TABLE monitor ALTER TABLE monitor
ADD packet_size INTEGER DEFAULT 56 NOT NULL; ADD packet_size INTEGER DEFAULT 56 NOT NULL;
COMMIT; COMMIT;

View file

@ -18,5 +18,4 @@ drop table setting;
alter table setting_dg_tmp rename to setting; alter table setting_dg_tmp rename to setting;
COMMIT; COMMIT;

View file

@ -0,0 +1,11 @@
-- You should not modify if this have pushed to Github, unless it does serious wrong with the db.
BEGIN TRANSACTION;
ALTER TABLE status_page
ADD footer_text TEXT;
ALTER TABLE status_page
ADD custom_css TEXT;
ALTER TABLE status_page
ADD show_powered_by BOOLEAN NOT NULL DEFAULT 1;
COMMIT;

View file

@ -1,3 +1,4 @@
-- You should not modify if this have pushed to Github, unless it does serious wrong with the db.
BEGIN TRANSACTION; BEGIN TRANSACTION;
CREATE TABLE monitor_tls_info ( CREATE TABLE monitor_tls_info (

View file

@ -1,5 +0,0 @@
BEGIN TRANSACTION;
ALTER TABLE monitor
ADD game VARCHAR(255);
COMMIT

View file

@ -1,6 +0,0 @@
-- You should not modify if this have pushed to Github, unless it does serious wrong with the db.
BEGIN TRANSACTION;
ALTER TABLE status_page ADD footer_text TEXT;
ALTER TABLE status_page ADD custom_css TEXT;
ALTER TABLE status_page ADD show_powered_by BOOLEAN NOT NULL DEFAULT 1;
COMMIT;

View file

@ -1,8 +0,0 @@
# DON'T UPDATE TO alpine3.13, 1.14, see #41.
FROM node:16-alpine3.12
WORKDIR /app
# Install apprise, iputils for non-root ping, setpriv
RUN apk add --no-cache iputils setpriv dumb-init python3 py3-cryptography py3-pip py3-six py3-yaml py3-click py3-markdown py3-requests py3-requests-oauthlib git && \
pip3 --no-cache-dir install apprise==1.4.0 && \
rm -rf /root/.cache

View file

@ -1,12 +1,9 @@
# DON'T UPDATE TO bullseye-slim, see #372. # If the image changed, the second stage image should be changed too
# There is no 20-buster-slim for armv7 unfortunately, 18-buster-slim is the last one for Uptime Kuma v1. FROM node:20-bookworm-slim AS base2-slim
FROM node:18-buster-slim
ARG TARGETPLATFORM ARG TARGETPLATFORM
WORKDIR /app
# Specify --no-install-recommends to skip unused dependencies, make the base much smaller! # Specify --no-install-recommends to skip unused dependencies, make the base much smaller!
# python3* = apprise's dependencies # apprise = for notifications (From testing repo)
# sqlite3 = for debugging # sqlite3 = for debugging
# iputils-ping = for ping # iputils-ping = for ping
# util-linux = for setpriv (Should be dropped in 2.0.0?) # util-linux = for setpriv (Should be dropped in 2.0.0?)
@ -15,29 +12,25 @@ WORKDIR /app
# ca-certificates = keep the cert up-to-date # ca-certificates = keep the cert up-to-date
# sudo = for start service nscd with non-root user # sudo = for start service nscd with non-root user
# nscd = for better DNS caching # nscd = for better DNS caching
# (pip) apprise = for notifications RUN echo "deb http://deb.debian.org/debian testing main" >> /etc/apt/sources.list && \
RUN apt-get update && \ apt update && \
apt-get --yes --no-install-recommends install \ apt --yes --no-install-recommends -t testing install apprise sqlite3 ca-certificates && \
python3 python3-pip python3-cryptography python3-six python3-yaml python3-click python3-markdown python3-requests python3-requests-oauthlib \ apt --yes --no-install-recommends -t stable install \
sqlite3 \
iputils-ping \ iputils-ping \
util-linux \ util-linux \
dumb-init \ dumb-init \
curl \ curl \
ca-certificates \
sudo \ sudo \
nscd && \ nscd && \
pip3 --no-cache-dir install apprise==1.4.5 && \
rm -rf /var/lib/apt/lists/* && \ rm -rf /var/lib/apt/lists/* && \
apt --yes autoremove apt --yes autoremove
# Install cloudflared # Install cloudflared
RUN set -eux && \ RUN curl https://pkg.cloudflare.com/cloudflare-main.gpg --output /usr/share/keyrings/cloudflare-main.gpg && \
mkdir -p --mode=0755 /usr/share/keyrings && \ echo 'deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared bullseye main' | tee /etc/apt/sources.list.d/cloudflared.list && \
curl --fail --show-error --silent --location --insecure https://pkg.cloudflare.com/cloudflare-main.gpg --output /usr/share/keyrings/cloudflare-main.gpg && \ apt update && \
echo 'deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared buster main' | tee /etc/apt/sources.list.d/cloudflared.list && \ apt install --yes --no-install-recommends -t stable cloudflared && \
apt-get update && \
apt-get install --yes --no-install-recommends cloudflared && \
cloudflared version && \ cloudflared version && \
rm -rf /var/lib/apt/lists/* && \ rm -rf /var/lib/apt/lists/* && \
apt --yes autoremove apt --yes autoremove
@ -46,3 +39,13 @@ RUN set -eux && \
COPY ./docker/etc/nscd.conf /etc/nscd.conf COPY ./docker/etc/nscd.conf /etc/nscd.conf
COPY ./docker/etc/sudoers /etc/sudoers COPY ./docker/etc/sudoers /etc/sudoers
# Full Base Image
# MariaDB, Chromium and fonts
FROM base2-slim AS base2
ENV UPTIME_KUMA_ENABLE_EMBEDDED_MARIADB=1
RUN apt update && \
apt --yes --no-install-recommends install chromium fonts-indic fonts-noto fonts-noto-cjk mariadb-server && \
rm -rf /var/lib/apt/lists/* && \
apt --yes autoremove && \
chown -R node:node /var/lib/mysql

View file

@ -0,0 +1,14 @@
version: '3.8'
services:
uptime-kuma:
container_name: uptime-kuma-dev
image: louislam/uptime-kuma:nightly2
volumes:
#- ./data:/app/data
- ../server:/app/server
- ../db:/app/db
ports:
- "3001:3001" # <Host Port>:<Container Port>
- "3307:3306"

View file

@ -1,14 +1,15 @@
# Simple docker-compose.yml version: '3.8'
# You can change your port or volume location
version: '3.3'
services: services:
uptime-kuma: uptime-kuma:
image: louislam/uptime-kuma:1 image: louislam/uptime-kuma:1
container_name: uptime-kuma container_name: uptime-kuma
volumes: volumes:
- ./uptime-kuma-data:/app/data - uptime-kuma:/app/data
ports: ports:
- 3001:3001 # <Host Port>:<Container Port> - "3001:3001" # <Host Port>:<Container Port>
restart: always restart: always
volumes:
uptime-kuma:

View file

@ -1,6 +1,8 @@
ARG BASE_IMAGE=louislam/uptime-kuma:base2
############################################ ############################################
# Build in Golang # Build in Golang
# Run npm run build-healthcheck-armv7 in the host first, another it will be super slow where it is building the armv7 healthcheck # Run npm run build-healthcheck-armv7 in the host first, otherwise it will be super slow where it is building the armv7 healthcheck
# Check file: builder-go.dockerfile # Check file: builder-go.dockerfile
############################################ ############################################
FROM louislam/uptime-kuma:builder-go AS build_healthcheck FROM louislam/uptime-kuma:builder-go AS build_healthcheck
@ -8,49 +10,50 @@ FROM louislam/uptime-kuma:builder-go AS build_healthcheck
############################################ ############################################
# Build in Node.js # Build in Node.js
############################################ ############################################
FROM louislam/uptime-kuma:base-debian AS build FROM louislam/uptime-kuma:base2 AS build
USER node
WORKDIR /app WORKDIR /app
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=1 ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=1
COPY .npmrc .npmrc COPY --chown=node:node .npmrc .npmrc
COPY package.json package.json COPY --chown=node:node package.json package.json
COPY package-lock.json package-lock.json COPY --chown=node:node package-lock.json package-lock.json
RUN npm ci --omit=dev RUN npm ci --omit=dev
COPY . . COPY . .
COPY --from=build_healthcheck /app/extra/healthcheck /app/extra/healthcheck COPY --chown=node:node --from=build_healthcheck /app/extra/healthcheck /app/extra/healthcheck
RUN chmod +x /app/extra/entrypoint.sh RUN mkdir ./data
############################################ ############################################
# ⭐ Main Image # ⭐ Main Image
############################################ ############################################
FROM louislam/uptime-kuma:base-debian AS release FROM $BASE_IMAGE AS release
USER node
WORKDIR /app WORKDIR /app
LABEL org.opencontainers.image.source="https://github.com/louislam/uptime-kuma"
ENV UPTIME_KUMA_IS_CONTAINER=1 ENV UPTIME_KUMA_IS_CONTAINER=1
# Copy app files from build layer # Copy app files from build layer
COPY --from=build /app /app COPY --chown=node:node --from=build /app /app
EXPOSE 3001 EXPOSE 3001
VOLUME ["/app/data"]
HEALTHCHECK --interval=60s --timeout=30s --start-period=180s --retries=5 CMD extra/healthcheck HEALTHCHECK --interval=60s --timeout=30s --start-period=180s --retries=5 CMD extra/healthcheck
ENTRYPOINT ["/usr/bin/dumb-init", "--", "extra/entrypoint.sh"] ENTRYPOINT ["/usr/bin/dumb-init", "--"]
CMD ["node", "server/server.js"] CMD ["node", "server/server.js"]
############################################ ############################################
# Mark as Nightly # Mark as Nightly
############################################ ############################################
FROM release AS nightly FROM release AS nightly
USER node
RUN npm run mark-as-nightly RUN npm run mark-as-nightly
############################################ ############################################
# Build an image for testing pr # Build an image for testing pr
############################################ ############################################
FROM louislam/uptime-kuma:base-debian AS pr-test FROM louislam/uptime-kuma:base2 AS pr-test2
WORKDIR /app WORKDIR /app
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=1 ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=1
## Install Git ## Install Git
@ -78,7 +81,7 @@ CMD ["npm", "run", "start-pr-test"]
############################################ ############################################
# Upload the artifact to Github # Upload the artifact to Github
############################################ ############################################
FROM louislam/uptime-kuma:base-debian AS upload-artifact FROM louislam/uptime-kuma:base2 AS upload-artifact
WORKDIR / WORKDIR /
RUN apt update && \ RUN apt update && \
apt --yes install curl file apt --yes install curl file

View file

@ -1,27 +0,0 @@
FROM louislam/uptime-kuma:base-alpine AS build
WORKDIR /app
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=1
COPY .npmrc .npmrc
COPY package.json package.json
COPY package-lock.json package-lock.json
RUN npm ci --omit=dev
COPY . .
RUN chmod +x /app/extra/entrypoint.sh
FROM louislam/uptime-kuma:base-alpine AS release
WORKDIR /app
# Copy app files from build layer
COPY --from=build /app /app
EXPOSE 3001
VOLUME ["/app/data"]
HEALTHCHECK --interval=60s --timeout=30s --start-period=180s --retries=5 CMD node extra/healthcheck.js
ENTRYPOINT ["/usr/bin/dumb-init", "--", "extra/entrypoint.sh"]
CMD ["node", "server/server.js"]
FROM release AS nightly
RUN npm run mark-as-nightly

View file

@ -36,6 +36,8 @@ if (! exists) {
/** /**
* Commit updated files * Commit updated files
* @param {string} version Version to update to * @param {string} version Version to update to
* @returns {void}
* @throws Error committing files
*/ */
function commit(version) { function commit(version) {
let msg = "Update to " + version; let msg = "Update to " + version;
@ -55,6 +57,7 @@ function commit(version) {
/** /**
* Create a tag with the specified version * Create a tag with the specified version
* @param {string} version Tag to create * @param {string} version Tag to create
* @returns {void}
*/ */
function tag(version) { function tag(version) {
let res = childProcess.spawnSync("git", [ "tag", version ]); let res = childProcess.spawnSync("git", [ "tag", version ]);
@ -68,6 +71,7 @@ function tag(version) {
* Check if a tag exists for the specified version * Check if a tag exists for the specified version
* @param {string} version Version to check * @param {string} version Version to check
* @returns {boolean} Does the tag already exist * @returns {boolean} Does the tag already exist
* @throws Version is not valid
*/ */
function tagExists(version) { function tagExists(version) {
if (! version) { if (! version) {

View file

@ -15,6 +15,7 @@ download(url);
/** /**
* Downloads the latest version of the dist from a GitHub release. * Downloads the latest version of the dist from a GitHub release.
* @param {string} url The URL to download from. * @param {string} url The URL to download from.
* @returns {void}
* *
* Generated by Trelent * Generated by Trelent
*/ */

View file

@ -1,21 +0,0 @@
#!/usr/bin/env sh
# set -e Exit the script if an error happens
set -e
PUID=${PUID=0}
PGID=${PGID=0}
files_ownership () {
# -h Changes the ownership of an encountered symbolic link and not that of the file or directory pointed to by the symbolic link.
# -R Recursively descends the specified directories
# -c Like verbose but report only when a change is made
chown -hRc "$PUID":"$PGID" /app/data
}
echo "==> Performing startup jobs and maintenance tasks"
files_ownership
echo "==> Starting application with user $PUID group $PGID"
# --clear-groups Clear supplementary groups.
exec setpriv --reuid "$PUID" --regid "$PGID" --clear-groups "$@"

View file

@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Drawing; using System.Drawing;
@ -28,9 +28,15 @@ namespace UptimeKuma {
Environment.CurrentDirectory = cwd; Environment.CurrentDirectory = cwd;
} }
bool isIntranet = args.Contains("--intranet");
if (isIntranet) {
Console.WriteLine("The --intranet argument was provided, so we will not try to access the internet. The first time this application runs you'll need to run it without the --intranet param or copy the result from another machine to the intranet server.");
}
Application.EnableVisualStyles(); Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false); Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new UptimeKumaApplicationContext()); Application.Run(new UptimeKumaApplicationContext(isIntranet));
} }
} }
@ -49,8 +55,9 @@ namespace UptimeKuma {
private RegistryKey registryKey = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true); private RegistryKey registryKey = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
private readonly bool intranetOnly;
public UptimeKumaApplicationContext() { public UptimeKumaApplicationContext(bool intranetOnly) {
// Single instance only // Single instance only
bool createdNew; bool createdNew;
@ -59,6 +66,8 @@ namespace UptimeKuma {
return; return;
} }
this.intranetOnly = intranetOnly;
var startingText = "Starting server..."; var startingText = "Starting server...";
trayIcon = new NotifyIcon(); trayIcon = new NotifyIcon();
trayIcon.Text = startingText; trayIcon.Text = startingText;
@ -98,6 +107,10 @@ namespace UptimeKuma {
} }
void DownloadFiles() { void DownloadFiles() {
if (intranetOnly) {
return;
}
var form = new DownloadForm(); var form = new DownloadForm();
form.Closed += Exit; form.Closed += Exit;
form.Show(); form.Show();
@ -173,7 +186,9 @@ namespace UptimeKuma {
} }
void CheckForUpdate(object sender, EventArgs e) { void CheckForUpdate(object sender, EventArgs e) {
var needUpdate = false; if (intranetOnly) {
return;
}
// Check version.json exists // Check version.json exists
if (File.Exists("version.json")) { if (File.Exists("version.json")) {
@ -204,8 +219,12 @@ namespace UptimeKuma {
} }
void VisitGitHub(object sender, EventArgs e) void VisitGitHub(object sender, EventArgs e) {
{ if (intranetOnly) {
MessageBox.Show("You have parsed in --intranet so we will not try to access the internet or visit github.com, please go to https://github.com/louislam/uptime-kuma if you want to visit github.");
return;
}
Process.Start("https://github.com/louislam/uptime-kuma"); Process.Start("https://github.com/louislam/uptime-kuma");
} }

View file

@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.1.0")] [assembly: AssemblyVersion("1.0.2.0")]
[assembly: AssemblyFileVersion("1.0.1.0")] [assembly: AssemblyFileVersion("1.0.2.0")]

View file

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="packages\Costura.Fody.5.7.0\build\Costura.Fody.props" Condition="Exists('packages\Costura.Fody.5.7.0\build\Costura.Fody.props')" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@ -42,9 +41,6 @@
<PostBuildEvent>COPY "$(SolutionDir)bin\Debug\uptime-kuma.exe" "%UserProfile%\Desktop\uptime-kuma-win64\"</PostBuildEvent> <PostBuildEvent>COPY "$(SolutionDir)bin\Debug\uptime-kuma.exe" "%UserProfile%\Desktop\uptime-kuma-win64\"</PostBuildEvent>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="Costura, Version=5.7.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>packages\Costura.Fody.5.7.0\lib\netstandard1.0\Costura.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Win32.Primitives, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> <Reference Include="Microsoft.Win32.Primitives, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.Win32.Primitives.4.3.0\lib\net46\Microsoft.Win32.Primitives.dll</HintPath> <HintPath>packages\Microsoft.Win32.Primitives.4.3.0\lib\net46\Microsoft.Win32.Primitives.dll</HintPath>
</Reference> </Reference>
@ -201,12 +197,7 @@
<PropertyGroup> <PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105.The missing file is {0}.</ErrorText> <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105.The missing file is {0}.</ErrorText>
</PropertyGroup> </PropertyGroup>
<Error Condition="!Exists('packages\Costura.Fody.5.7.0\build\Costura.Fody.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Costura.Fody.5.7.0\build\Costura.Fody.props'))" />
<Error Condition="!Exists('packages\Costura.Fody.5.7.0\build\Costura.Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Costura.Fody.5.7.0\build\Costura.Fody.targets'))" />
<Error Condition="!Exists('packages\Fody.6.6.4\build\Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Fody.6.6.4\build\Fody.targets'))" />
<Error Condition="!Exists('packages\NETStandard.Library.2.0.3\build\netstandard2.0\NETStandard.Library.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\NETStandard.Library.2.0.3\build\netstandard2.0\NETStandard.Library.targets'))" /> <Error Condition="!Exists('packages\NETStandard.Library.2.0.3\build\netstandard2.0\NETStandard.Library.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\NETStandard.Library.2.0.3\build\netstandard2.0\NETStandard.Library.targets'))" />
</Target> </Target>
<Import Project="packages\Costura.Fody.5.7.0\build\Costura.Fody.targets" Condition="Exists('packages\Costura.Fody.5.7.0\build\Costura.Fody.targets')" />
<Import Project="packages\Fody.6.6.4\build\Fody.targets" Condition="Exists('packages\Fody.6.6.4\build\Fody.targets')" />
<Import Project="packages\NETStandard.Library.2.0.3\build\netstandard2.0\NETStandard.Library.targets" Condition="Exists('packages\NETStandard.Library.2.0.3\build\netstandard2.0\NETStandard.Library.targets')" /> <Import Project="packages\NETStandard.Library.2.0.3\build\netstandard2.0\NETStandard.Library.targets" Condition="Exists('packages\NETStandard.Library.2.0.3\build\netstandard2.0\NETStandard.Library.targets')" />
</Project> </Project>

View file

@ -1,7 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="Costura.Fody" version="5.7.0" targetFramework="net472" developmentDependency="true" />
<package id="Fody" version="6.6.4" targetFramework="net472" developmentDependency="true" />
<package id="Microsoft.NETCore.Platforms" version="7.0.0" targetFramework="net472" /> <package id="Microsoft.NETCore.Platforms" version="7.0.0" targetFramework="net472" />
<package id="Microsoft.Win32.Primitives" version="4.3.0" targetFramework="net472" /> <package id="Microsoft.Win32.Primitives" version="4.3.0" targetFramework="net472" />
<package id="NETStandard.Library" version="2.0.3" targetFramework="net472" /> <package id="NETStandard.Library" version="2.0.3" targetFramework="net472" />

View file

@ -4,12 +4,12 @@ const fs = require("fs");
* to avoid the runtime deprecation warning triggered for using `fs.rmdirSync` with `{ recursive: true }` in Node.js v16, * to avoid the runtime deprecation warning triggered for using `fs.rmdirSync` with `{ recursive: true }` in Node.js v16,
* or the `recursive` property removing completely in the future Node.js version. * or the `recursive` property removing completely in the future Node.js version.
* See the link below. * See the link below.
*
* @todo Once we drop the support for Node.js v14 (or at least versions before v14.14.0), we can safely replace this function with `fs.rmSync`, since `fs.rmSync` was add in Node.js v14.14.0 and currently we supports all the Node.js v14 versions that include the versions before the v14.14.0, and this function have almost the same signature with `fs.rmSync`. * @todo Once we drop the support for Node.js v14 (or at least versions before v14.14.0), we can safely replace this function with `fs.rmSync`, since `fs.rmSync` was add in Node.js v14.14.0 and currently we supports all the Node.js v14 versions that include the versions before the v14.14.0, and this function have almost the same signature with `fs.rmSync`.
* @link https://nodejs.org/docs/latest-v16.x/api/deprecations.html#dep0147-fsrmdirpath--recursive-true- the deprecation infomation of `fs.rmdirSync` * @link https://nodejs.org/docs/latest-v16.x/api/deprecations.html#dep0147-fsrmdirpath--recursive-true- the deprecation infomation of `fs.rmdirSync`
* @link https://nodejs.org/docs/latest-v16.x/api/fs.html#fsrmsyncpath-options the document of `fs.rmSync` * @link https://nodejs.org/docs/latest-v16.x/api/fs.html#fsrmsyncpath-options the document of `fs.rmSync`
* @param {fs.PathLike} path Valid types for path values in "fs". * @param {fs.PathLike} path Valid types for path values in "fs".
* @param {fs.RmDirOptions} [options] options for `fs.rmdirSync`, if `fs.rmSync` is available and property `recursive` is true, it will automatically have property `force` with value `true`. * @param {fs.RmDirOptions} options options for `fs.rmdirSync`, if `fs.rmSync` is available and property `recursive` is true, it will automatically have property `force` with value `true`.
* @returns {void}
*/ */
const rmSync = (path, options) => { const rmSync = (path, options) => {
if (typeof fs.rmSync === "function") { if (typeof fs.rmSync === "function") {

3
extra/push-examples/.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
java/Index.class
csharp/index.exe
typescript-fetch/index.js

View file

@ -0,0 +1,10 @@
#!/bin/bash
# Filename: index.sh
PUSH_URL="https://example.com/api/push/key?status=up&msg=OK&ping="
INTERVAL=60
while true; do
curl -s -o /dev/null $PUSH_URL
echo "Pushed!"
sleep $INTERVAL
done

View file

@ -0,0 +1,24 @@
using System;
using System.Net;
using System.Threading;
/**
* Compile: C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe index.cs
* Run: index.exe
*/
class Index
{
const string PushURL = "https://example.com/api/push/key?status=up&msg=OK&ping=";
const int Interval = 60;
static void Main(string[] args)
{
while (true)
{
WebClient client = new WebClient();
client.DownloadString(PushURL);
Console.WriteLine("Pushed!");
Thread.Sleep(Interval * 1000);
}
}
}

View file

@ -0,0 +1 @@
docker run -d --restart=always --name uptime-kuma-push louislam/uptime-kuma:push "https://example.com/api/push/key?status=up&msg=OK&ping=" 60

View file

@ -0,0 +1,20 @@
package main
import (
"fmt"
"net/http"
"time"
)
func main() {
const PushURL = "https://example.com/api/push/key?status=up&msg=OK&ping="
const Interval = 60
for {
_, err := http.Get(PushURL)
if err == nil {
fmt.Println("Pushed!")
}
time.Sleep(Interval * time.Second)
}
}

View file

@ -0,0 +1,32 @@
import java.net.HttpURLConnection;
import java.net.URL;
/**
* Compile: javac index.java
* Run: java Index
*/
class Index {
public static final String PUSH_URL = "https://example.com/api/push/key?status=up&msg=OK&ping=";
public static final int INTERVAL = 60;
public static void main(String[] args) {
while (true) {
try {
URL url = new URL(PUSH_URL);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("GET");
con.getResponseCode();
con.disconnect();
System.out.println("Pushed!");
} catch (Exception e) {
e.printStackTrace();
}
try {
Thread.sleep(INTERVAL * 1000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}

View file

@ -0,0 +1,11 @@
// Supports: Node.js >= 18, Deno, Bun
const pushURL = "https://example.com/api/push/key?status=up&msg=OK&ping=";
const interval = 60;
const push = async () => {
await fetch(pushURL);
console.log("Pushed!");
};
push();
setInterval(push, interval * 1000);

View file

@ -0,0 +1,5 @@
{
"scripts": {
"start": "node index.js"
}
}

View file

@ -0,0 +1,13 @@
<?php
const PUSH_URL = "https://example.com/api/push/key?status=up&msg=OK&ping=";
const interval = 60;
while (true) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, PUSH_URL);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_exec($ch);
curl_close($ch);
echo "Pushed!\n";
sleep(interval);
}

View file

@ -0,0 +1,9 @@
# Filename: index.ps1
$pushURL = "https://example.com/api/push/key?status=up&msg=OK&ping="
$interval = 60
while ($true) {
$res = Invoke-WebRequest -Uri $pushURL
Write-Host "Pushed!"
Start-Sleep -Seconds $interval
}

View file

@ -0,0 +1,10 @@
import urllib.request
import time
push_url = "https://example.com/api/push/key?status=up&msg=OK&ping="
interval = 60
while True:
urllib.request.urlopen(push_url)
print("Pushed!\n")
time.sleep(interval)

View file

@ -0,0 +1,19 @@
# How to run
Node.js (ts-node)
```bash
ts-node index.ts
```
Deno
```bash
deno run --allow-net index.ts
```
Bun.js
```bash
bun index.ts
```

View file

@ -0,0 +1,11 @@
// Supports: Deno, Bun, Node.js >= 18 (ts-node)
const pushURL : string = "https://example.com/api/push/key?status=up&msg=OK&ping=";
const interval : number = 60;
const push = async () => {
await fetch(pushURL);
console.log("Pushed!");
};
push();
setInterval(push, interval * 1000);

View file

@ -0,0 +1,13 @@
{
"scripts": {
"ts-node": "ts-node index.ts",
"deno": "deno run --allow-net index.ts",
"bun": "bun index.ts"
},
"devDependencies": {
"@types/node": "^20.6.0",
"ts-node": "^10.9.1",
"tslib": "^2.6.2",
"typescript": "^5.2.2"
}
}

40
extra/rebase-pr.js Normal file
View file

@ -0,0 +1,40 @@
const { execSync } = require("child_process");
/**
* Rebase a PR onto such as 1.23.X or master
* @returns {Promise<void>}
*/
async function main() {
const branch = process.argv[2];
// Use gh to get current branch's pr id
let currentBranchPRID = execSync("gh pr view --json number --jq \".number\"").toString().trim();
console.log("Pr ID: ", currentBranchPRID);
// Use gh commend to get pr commits
const prCommits = JSON.parse(execSync(`gh pr view ${currentBranchPRID} --json commits`).toString().trim()).commits;
console.log("Found commits: ", prCommits.length);
// Sort the commits by authoredDate
prCommits.sort((a, b) => {
return new Date(a.authoredDate) - new Date(b.authoredDate);
});
// Get the oldest commit id
const oldestCommitID = prCommits[0].oid;
console.log("Oldest commit id of this pr:", oldestCommitID);
// Get the latest commit id of the target branch
const latestCommitID = execSync(`git rev-parse origin/${branch}`).toString().trim();
console.log("Latest commit id of " + branch + ":", latestCommitID);
// Get the original parent commit id of the oldest commit
const originalParentCommitID = execSync(`git log --pretty=%P -n 1 "${oldestCommitID}"`).toString().trim();
console.log("Original parent commit id of the oldest commit:", originalParentCommitID);
// Rebase the pr onto the target branch
execSync(`git rebase --onto ${latestCommitID} ${originalParentCommitID}`);
}
main();

Some files were not shown because too many files have changed in this diff Show more