Compare commits
	
		
			1 Commits
		
	
	
		
			renovate/e
			...
			65c00b559e
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 65c00b559e | 
| @@ -5,7 +5,7 @@ name: default | |||||||
|  |  | ||||||
| steps: | steps: | ||||||
| - name: frontend_build | - name: frontend_build | ||||||
|   image: node:24 |   image: node:23 | ||||||
|   volumes: |   volumes: | ||||||
|     - name: frontend_app |     - name: frontend_app | ||||||
|       path: /tmp/frontend_build |       path: /tmp/frontend_build | ||||||
|   | |||||||
							
								
								
									
										11
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								README.md
									
									
									
									
									
								
							| @@ -1,11 +1,4 @@ | |||||||
| # VirtWeb Remote | # VirtWeb Remote | ||||||
| Web UI that allows to start and stop VMs managed by VirtWEB without having to expose the VirtWEB directly on the Internet. | WIP project | ||||||
|  |  | ||||||
| VirtWebRemote rely on OpenID to authenticate users. | This project aims to use the VirtWeb API to start and stop VM without directly exposing the VirtWEB API to the Internet. | ||||||
|  |  | ||||||
| VirtWebRemote authenticates against VirtWEB API using an API token. Both the token ID and private key are required to be able to authenticate against the VirtWEB API. |  | ||||||
|  |  | ||||||
| ## Docker image options |  | ||||||
| ```bash |  | ||||||
| docker run --rm -it pierre42100/virtweb_remote --help |  | ||||||
| ``` |  | ||||||
|   | |||||||
							
								
								
									
										950
									
								
								remote_backend/Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										950
									
								
								remote_backend/Cargo.lock
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,28 +1,28 @@ | |||||||
| [package] | [package] | ||||||
| name = "remote_backend" | name = "remote_backend" | ||||||
| version = "0.1.0" | version = "0.1.0" | ||||||
| edition = "2024" | edition = "2021" | ||||||
|  |  | ||||||
| # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||||||
|  |  | ||||||
| [dependencies] | [dependencies] | ||||||
| log = "0.4.28" | log = "0.4.21" | ||||||
| env_logger = "0.11.8" | env_logger = "0.11.3" | ||||||
| clap = { version = "4.5.50", features = ["derive", "env"] } | clap = { version = "4.5.21", features = ["derive", "env"] } | ||||||
| serde = { version = "1.0.228", features = ["derive"] } | serde = { version = "1.0.215", features = ["derive"] } | ||||||
| light-openid = { version = "1.0.4", features = ["crypto-wrapper"] } | light-openid = { version = "1.0.2", features = ["crypto-wrapper"] } | ||||||
| basic-jwt = "0.3.0" | basic-jwt = "0.2.0" | ||||||
| actix-web = "4.11.0" | actix-web = "4.5.1" | ||||||
| actix-remote-ip = "0.1.0" | actix-remote-ip = "0.1.0" | ||||||
| actix-session = { version = "0.10.1", features = ["cookie-session"] } | actix-session = { version = "0.10.1", features = ["cookie-session"] } | ||||||
| actix-identity = "0.9.0" | actix-identity = "0.8.0" | ||||||
| actix-cors = "0.7.1" | actix-cors = "0.7.0" | ||||||
| lazy_static = "1.5.0" | lazy_static = "1.4.0" | ||||||
| anyhow = "1.0.100" | anyhow = "1.0.93" | ||||||
| reqwest = { version = "0.12.24", features = ["json"] } | reqwest = { version = "0.12.9", features = ["json"] } | ||||||
| thiserror = "2.0.17" | thiserror = "2.0.3" | ||||||
| uuid = { version = "1.18.1", features = ["v4", "serde"] } | uuid = { version = "1.8.0", features = ["v4", "serde"] } | ||||||
| futures-util = "0.3.31" | futures-util = "0.3.30" | ||||||
| lazy-regex = "3.4.1" | lazy-regex = "3.1.0" | ||||||
| mime_guess = "2.0.5" | mime_guess = "2.0.4" | ||||||
| rust-embed = { version = "8.7.2" } | rust-embed = { version = "8.3.0" } | ||||||
| @@ -1,6 +1,6 @@ | |||||||
| use actix_remote_ip::RemoteIP; | use actix_remote_ip::RemoteIP; | ||||||
| use actix_web::web::Data; | use actix_web::web::Data; | ||||||
| use actix_web::{HttpResponse, Responder, web}; | use actix_web::{web, HttpResponse, Responder}; | ||||||
| use light_openid::basic_state_manager::BasicStateManager; | use light_openid::basic_state_manager::BasicStateManager; | ||||||
|  |  | ||||||
| use crate::app_config::AppConfig; | use crate::app_config::AppConfig; | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| use crate::controllers::HttpResult; | use crate::controllers::HttpResult; | ||||||
| use crate::virtweb_client; | use crate::virtweb_client; | ||||||
| use crate::virtweb_client::{GroupID, VMUuid}; | use crate::virtweb_client::{GroupID, VMUuid}; | ||||||
| use actix_web::{HttpResponse, web}; | use actix_web::{web, HttpResponse}; | ||||||
|  |  | ||||||
| #[derive(serde::Deserialize)] | #[derive(serde::Deserialize)] | ||||||
| pub struct GroupIDInPath { | pub struct GroupIDInPath { | ||||||
|   | |||||||
| @@ -1,8 +1,9 @@ | |||||||
| use actix_web::HttpResponse; |  | ||||||
| use actix_web::body::BoxBody; | use actix_web::body::BoxBody; | ||||||
| use actix_web::http::StatusCode; | use actix_web::http::StatusCode; | ||||||
|  | use actix_web::HttpResponse; | ||||||
| use std::error::Error; | use std::error::Error; | ||||||
| use std::fmt::{Display, Formatter}; | use std::fmt::{Display, Formatter}; | ||||||
|  | use std::io::ErrorKind; | ||||||
|  |  | ||||||
| pub mod auth_controller; | pub mod auth_controller; | ||||||
| pub mod group_controller; | pub mod group_controller; | ||||||
| @@ -37,7 +38,7 @@ impl actix_web::error::ResponseError for HttpErr { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     fn error_response(&self) -> HttpResponse<BoxBody> { |     fn error_response(&self) -> HttpResponse<BoxBody> { | ||||||
|         log::error!("Error while processing request! {self}"); |         log::error!("Error while processing request! {}", self); | ||||||
|  |  | ||||||
|         HttpResponse::InternalServerError().body("Failed to execute request!") |         HttpResponse::InternalServerError().body("Failed to execute request!") | ||||||
|     } |     } | ||||||
| @@ -51,7 +52,7 @@ impl From<anyhow::Error> for HttpErr { | |||||||
|  |  | ||||||
| impl From<Box<dyn Error>> for HttpErr { | impl From<Box<dyn Error>> for HttpErr { | ||||||
|     fn from(value: Box<dyn Error>) -> Self { |     fn from(value: Box<dyn Error>) -> Self { | ||||||
|         HttpErr::Err(std::io::Error::other(value.to_string()).into()) |         HttpErr::Err(std::io::Error::new(ErrorKind::Other, value.to_string()).into()) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -81,7 +82,7 @@ impl From<reqwest::header::ToStrError> for HttpErr { | |||||||
|  |  | ||||||
| impl From<actix_web::Error> for HttpErr { | impl From<actix_web::Error> for HttpErr { | ||||||
|     fn from(value: actix_web::Error) -> Self { |     fn from(value: actix_web::Error) -> Self { | ||||||
|         HttpErr::Err(std::io::Error::other(value.to_string()).into()) |         HttpErr::Err(std::io::Error::new(ErrorKind::Other, value.to_string()).into()) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -18,7 +18,7 @@ mod serve_static_debug { | |||||||
|  |  | ||||||
| #[cfg(not(debug_assertions))] | #[cfg(not(debug_assertions))] | ||||||
| mod serve_static_release { | mod serve_static_release { | ||||||
|     use actix_web::{HttpResponse, Responder, web}; |     use actix_web::{web, HttpResponse, Responder}; | ||||||
|     use rust_embed::RustEmbed; |     use rust_embed::RustEmbed; | ||||||
|  |  | ||||||
|     #[derive(RustEmbed)] |     #[derive(RustEmbed)] | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ | |||||||
| use crate::controllers::HttpResult; | use crate::controllers::HttpResult; | ||||||
| use crate::virtweb_client; | use crate::virtweb_client; | ||||||
| use crate::virtweb_client::VMUuid; | use crate::virtweb_client::VMUuid; | ||||||
| use actix_web::{HttpResponse, web}; | use actix_web::{web, HttpResponse}; | ||||||
|  |  | ||||||
| #[derive(serde::Deserialize)] | #[derive(serde::Deserialize)] | ||||||
| pub struct ReqPath { | pub struct ReqPath { | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| use actix_identity::Identity; | use actix_identity::Identity; | ||||||
| use actix_web::dev::Payload; | use actix_web::dev::Payload; | ||||||
| use actix_web::{Error, FromRequest, HttpMessage, HttpRequest}; | use actix_web::{Error, FromRequest, HttpMessage, HttpRequest}; | ||||||
| use futures_util::future::{Ready, ready}; | use futures_util::future::{ready, Ready}; | ||||||
| use std::fmt::Display; | use std::fmt::Display; | ||||||
|  |  | ||||||
| pub struct AuthExtractor { | pub struct AuthExtractor { | ||||||
|   | |||||||
| @@ -1,13 +1,13 @@ | |||||||
| use actix_cors::Cors; | use actix_cors::Cors; | ||||||
|  | use actix_identity::config::LogoutBehaviour; | ||||||
| use actix_identity::IdentityMiddleware; | use actix_identity::IdentityMiddleware; | ||||||
| use actix_identity::config::LogoutBehavior; |  | ||||||
| use actix_remote_ip::RemoteIPConfig; | use actix_remote_ip::RemoteIPConfig; | ||||||
| use actix_session::SessionMiddleware; |  | ||||||
| use actix_session::storage::CookieSessionStore; | use actix_session::storage::CookieSessionStore; | ||||||
|  | use actix_session::SessionMiddleware; | ||||||
| use actix_web::cookie::{Key, SameSite}; | use actix_web::cookie::{Key, SameSite}; | ||||||
| use actix_web::middleware::Logger; | use actix_web::middleware::Logger; | ||||||
| use actix_web::web::Data; | use actix_web::web::Data; | ||||||
| use actix_web::{App, HttpServer, web}; | use actix_web::{web, App, HttpServer}; | ||||||
| use light_openid::basic_state_manager::BasicStateManager; | use light_openid::basic_state_manager::BasicStateManager; | ||||||
| use remote_backend::app_config::AppConfig; | use remote_backend::app_config::AppConfig; | ||||||
| use remote_backend::constants; | use remote_backend::constants; | ||||||
| @@ -37,7 +37,7 @@ async fn main() -> std::io::Result<()> { | |||||||
|         .build(); |         .build(); | ||||||
|  |  | ||||||
|         let identity_middleware = IdentityMiddleware::builder() |         let identity_middleware = IdentityMiddleware::builder() | ||||||
|             .logout_behavior(LogoutBehavior::PurgeSession) |             .logout_behaviour(LogoutBehaviour::PurgeSession) | ||||||
|             .visit_deadline(Some(Duration::from_secs( |             .visit_deadline(Some(Duration::from_secs( | ||||||
|                 constants::MAX_INACTIVITY_DURATION, |                 constants::MAX_INACTIVITY_DURATION, | ||||||
|             ))) |             ))) | ||||||
|   | |||||||
| @@ -1,4 +1,4 @@ | |||||||
| use std::future::{Ready, ready}; | use std::future::{ready, Ready}; | ||||||
| use std::rc::Rc; | use std::rc::Rc; | ||||||
|  |  | ||||||
| use crate::app_config::AppConfig; | use crate::app_config::AppConfig; | ||||||
| @@ -7,8 +7,8 @@ use crate::extractors::auth_extractor::AuthExtractor; | |||||||
| use actix_web::body::EitherBody; | use actix_web::body::EitherBody; | ||||||
| use actix_web::dev::Payload; | use actix_web::dev::Payload; | ||||||
| use actix_web::{ | use actix_web::{ | ||||||
|  |     dev::{forward_ready, Service, ServiceRequest, ServiceResponse, Transform}, | ||||||
|     Error, FromRequest, HttpResponse, |     Error, FromRequest, HttpResponse, | ||||||
|     dev::{Service, ServiceRequest, ServiceResponse, Transform, forward_ready}, |  | ||||||
| }; | }; | ||||||
| use futures_util::future::LocalBoxFuture; | use futures_util::future::LocalBoxFuture; | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										18
									
								
								remote_frontend/.eslintrc.cjs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								remote_frontend/.eslintrc.cjs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | |||||||
|  | module.exports = { | ||||||
|  |   root: true, | ||||||
|  |   env: { browser: true, es2020: true }, | ||||||
|  |   extends: [ | ||||||
|  |     'eslint:recommended', | ||||||
|  |     'plugin:@typescript-eslint/recommended', | ||||||
|  |     'plugin:react-hooks/recommended', | ||||||
|  |   ], | ||||||
|  |   ignorePatterns: ['dist', '.eslintrc.cjs'], | ||||||
|  |   parser: '@typescript-eslint/parser', | ||||||
|  |   plugins: ['react-refresh'], | ||||||
|  |   rules: { | ||||||
|  |     'react-refresh/only-export-components': [ | ||||||
|  |       'warn', | ||||||
|  |       { allowConstantExport: true }, | ||||||
|  |     ], | ||||||
|  |   }, | ||||||
|  | } | ||||||
| @@ -1,28 +0,0 @@ | |||||||
| import js from '@eslint/js' |  | ||||||
| import globals from 'globals' |  | ||||||
| import reactHooks from 'eslint-plugin-react-hooks' |  | ||||||
| import reactRefresh from 'eslint-plugin-react-refresh' |  | ||||||
| import tseslint from 'typescript-eslint' |  | ||||||
|  |  | ||||||
| export default tseslint.config( |  | ||||||
|   { ignores: ['dist'] }, |  | ||||||
|   { |  | ||||||
|     extends: [js.configs.recommended, ...tseslint.configs.recommended], |  | ||||||
|     files: ['**/*.{ts,tsx}'], |  | ||||||
|     languageOptions: { |  | ||||||
|       ecmaVersion: 2020, |  | ||||||
|       globals: globals.browser, |  | ||||||
|     }, |  | ||||||
|     plugins: { |  | ||||||
|       'react-hooks': reactHooks, |  | ||||||
|       'react-refresh': reactRefresh, |  | ||||||
|     }, |  | ||||||
|     rules: { |  | ||||||
|       ...reactHooks.configs.recommended.rules, |  | ||||||
|       'react-refresh/only-export-components': [ |  | ||||||
|         'warn', |  | ||||||
|         { allowConstantExport: true }, |  | ||||||
|       ], |  | ||||||
|     }, |  | ||||||
|   }, |  | ||||||
| ) |  | ||||||
							
								
								
									
										4044
									
								
								remote_frontend/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										4044
									
								
								remote_frontend/package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -10,25 +10,22 @@ | |||||||
|     "preview": "vite preview" |     "preview": "vite preview" | ||||||
|   }, |   }, | ||||||
|   "dependencies": { |   "dependencies": { | ||||||
|     "@fluentui/react-components": "^9.72.3", |     "@fluentui/react-components": "^9.56.3", | ||||||
|     "@fluentui/react-icons": "^2.0.312", |     "@fluentui/react-icons": "^2.0.266", | ||||||
|     "filesize": "^11.0.13", |     "filesize": "^10.1.6", | ||||||
|     "react": "^18.3.1", |     "react": "^18.2.0", | ||||||
|     "react-dom": "^18.3.1" |     "react-dom": "^18.2.0" | ||||||
|   }, |   }, | ||||||
|   "devDependencies": { |   "devDependencies": { | ||||||
|     "@eslint/js": "^9.38.0", |     "@types/react": "^18.3.12", | ||||||
|     "@types/react": "^18.3.26", |     "@types/react-dom": "^18.3.1", | ||||||
|     "@types/react-dom": "^18.3.7", |     "@typescript-eslint/eslint-plugin": "^8.16.0", | ||||||
|     "@typescript-eslint/eslint-plugin": "^8.46.2", |     "@typescript-eslint/parser": "^8.16.0", | ||||||
|     "@typescript-eslint/parser": "^8.46.2", |     "@vitejs/plugin-react": "^4.3.4", | ||||||
|     "@vitejs/plugin-react": "^5.0.4", |     "eslint": "^9.0.0", | ||||||
|     "eslint": "^9.38.0", |     "eslint-plugin-react-hooks": "^5.0.0", | ||||||
|     "eslint-plugin-react-hooks": "^5.2.0", |     "eslint-plugin-react-refresh": "^0.4.14", | ||||||
|     "eslint-plugin-react-refresh": "^0.4.24", |     "typescript": "^5.7.2", | ||||||
|     "globals": "^16.4.0", |     "vite": "^6.0.1" | ||||||
|     "typescript": "^5.9.3", |  | ||||||
|     "typescript-eslint": "^8.43.0", |  | ||||||
|     "vite": "^7.1.12" |  | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -123,7 +123,7 @@ function GroupInfo(p: { group: VMGroup }): React.ReactElement { | |||||||
|                 </TableCell> |                 </TableCell> | ||||||
|                 <TableCell> |                 <TableCell> | ||||||
|                   {item.architecture} • RAM :{" "} |                   {item.architecture} • RAM :{" "} | ||||||
|                   {filesize(item.memory)} •{" "} |                   {filesize(item.memory * 1000 * 1000)} •{" "} | ||||||
|                   {item.number_vcpu} vCPU |                   {item.number_vcpu} vCPU | ||||||
|                 </TableCell> |                 </TableCell> | ||||||
|                 <TableCell>{state?.[item.uuid] ?? ""}</TableCell> |                 <TableCell>{state?.[item.uuid] ?? ""}</TableCell> | ||||||
|   | |||||||
| @@ -107,7 +107,7 @@ function VMWidget(p: { vm: VMInfoAndCaps }): React.ReactElement { | |||||||
|         } |         } | ||||||
|       /> |       /> | ||||||
|       <p className={styles.caption1} style={{ margin: "0px auto" }}> |       <p className={styles.caption1} style={{ margin: "0px auto" }}> | ||||||
|         {p.vm.architecture} • RAM : {filesize(p.vm.memory)}{" "} |         {p.vm.architecture} • RAM : {filesize(p.vm.memory * 1000 * 1000)}{" "} | ||||||
|         • {p.vm.number_vcpu} vCPU |         • {p.vm.number_vcpu} vCPU | ||||||
|       </p> |       </p> | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,26 +0,0 @@ | |||||||
| { |  | ||||||
|   "compilerOptions": { |  | ||||||
|     "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", |  | ||||||
|     "target": "ES2020", |  | ||||||
|     "useDefineForClassFields": true, |  | ||||||
|     "lib": ["ES2020", "DOM", "DOM.Iterable"], |  | ||||||
|     "module": "ESNext", |  | ||||||
|     "skipLibCheck": true, |  | ||||||
|  |  | ||||||
|     /* Bundler mode */ |  | ||||||
|     "moduleResolution": "bundler", |  | ||||||
|     "allowImportingTsExtensions": true, |  | ||||||
|     "isolatedModules": true, |  | ||||||
|     "moduleDetection": "force", |  | ||||||
|     "noEmit": true, |  | ||||||
|     "jsx": "react-jsx", |  | ||||||
|  |  | ||||||
|     /* Linting */ |  | ||||||
|     "strict": true, |  | ||||||
|     "noUnusedLocals": true, |  | ||||||
|     "noUnusedParameters": true, |  | ||||||
|     "noFallthroughCasesInSwitch": true, |  | ||||||
|     "noUncheckedSideEffectImports": true |  | ||||||
|   }, |  | ||||||
|   "include": ["src"] |  | ||||||
| } |  | ||||||
| @@ -1,7 +1,25 @@ | |||||||
| { | { | ||||||
|   "files": [], |   "compilerOptions": { | ||||||
|   "references": [ |     "target": "ES2020", | ||||||
|     { "path": "./tsconfig.app.json" }, |     "useDefineForClassFields": true, | ||||||
|     { "path": "./tsconfig.node.json" } |     "lib": ["ES2020", "DOM", "DOM.Iterable"], | ||||||
|   ] |     "module": "ESNext", | ||||||
|  |     "skipLibCheck": true, | ||||||
|  |  | ||||||
|  |     /* Bundler mode */ | ||||||
|  |     "moduleResolution": "bundler", | ||||||
|  |     "allowImportingTsExtensions": true, | ||||||
|  |     "resolveJsonModule": true, | ||||||
|  |     "isolatedModules": true, | ||||||
|  |     "noEmit": true, | ||||||
|  |     "jsx": "react-jsx", | ||||||
|  |  | ||||||
|  |     /* Linting */ | ||||||
|  |     "strict": true, | ||||||
|  |     "noUnusedLocals": true, | ||||||
|  |     "noUnusedParameters": true, | ||||||
|  |     "noFallthroughCasesInSwitch": true | ||||||
|  |   }, | ||||||
|  |   "include": ["src"], | ||||||
|  |   "references": [{ "path": "./tsconfig.node.json" }] | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,24 +1,11 @@ | |||||||
| { | { | ||||||
|   "compilerOptions": { |   "compilerOptions": { | ||||||
|     "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", |     "composite": true, | ||||||
|     "target": "ES2022", |  | ||||||
|     "lib": ["ES2023"], |  | ||||||
|     "module": "ESNext", |  | ||||||
|     "skipLibCheck": true, |     "skipLibCheck": true, | ||||||
|  |     "module": "ESNext", | ||||||
|     /* Bundler mode */ |  | ||||||
|     "moduleResolution": "bundler", |     "moduleResolution": "bundler", | ||||||
|     "allowImportingTsExtensions": true, |     "allowSyntheticDefaultImports": true, | ||||||
|     "isolatedModules": true, |     "strict": true | ||||||
|     "moduleDetection": "force", |  | ||||||
|     "noEmit": true, |  | ||||||
|  |  | ||||||
|     /* Linting */ |  | ||||||
|     "strict": true, |  | ||||||
|     "noUnusedLocals": true, |  | ||||||
|     "noUnusedParameters": true, |  | ||||||
|     "noFallthroughCasesInSwitch": true, |  | ||||||
|     "noUncheckedSideEffectImports": true |  | ||||||
|   }, |   }, | ||||||
|   "include": ["vite.config.ts"] |   "include": ["vite.config.ts"] | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| import { defineConfig } from 'vite' | import { defineConfig } from 'vite' | ||||||
| import react from '@vitejs/plugin-react' | import react from '@vitejs/plugin-react' | ||||||
|  |  | ||||||
| // https://vite.dev/config/ | // https://vitejs.dev/config/ | ||||||
| export default defineConfig({ | export default defineConfig({ | ||||||
|   plugins: [react()], |   plugins: [react()], | ||||||
| }) | }) | ||||||
|   | |||||||
| @@ -1,3 +1,9 @@ | |||||||
| { | { | ||||||
|   "extends": ["local>renovate/presets"] |   "$schema": "https://docs.renovatebot.com/renovate-schema.json", | ||||||
|  |   "packageRules": [ | ||||||
|  |     { | ||||||
|  |       "matchUpdateTypes": ["major", "minor", "patch"], | ||||||
|  |       "automerge": true | ||||||
|  |     } | ||||||
|  |   ] | ||||||
| } | } | ||||||
		Reference in New Issue
	
	Block a user