Merge branch 'DrMxrcy-app/gladys'

This commit is contained in:
Nicolas Meienberger 2023-04-03 23:25:36 +02:00
commit e67b3bc551
6 changed files with 91 additions and 36 deletions

View File

@ -28,6 +28,7 @@ This is the official repository for the Tipi App Store. It contains all the apps
- [gandi-livedns](https://github.com/jbbodart/gandi-livedns) - Update your Gandi DNS zone records with your WAN IP - [gandi-livedns](https://github.com/jbbodart/gandi-livedns) - Update your Gandi DNS zone records with your WAN IP
- [Ghost](https://github.com/TryGhost/Ghost) - Ghost - Turn your audience into a business - [Ghost](https://github.com/TryGhost/Ghost) - Ghost - Turn your audience into a business
- [Gitea](https://github.com/go-gitea/gitea) - Gitea - A painless self-hosted Git service - [Gitea](https://github.com/go-gitea/gitea) - Gitea - A painless self-hosted Git service
- [Gladys Assistant](https://github.com/gladysassistant/gladys) - A privacy-first, open-source home assistant
- [Gotify](https://github.com/gotify/server) - Gotify - Simple server for sending and receiving notification messages - [Gotify](https://github.com/gotify/server) - Gotify - Simple server for sending and receiving notification messages
- [Grafana](https://github.com/grafana/grafana) - The open and composable observability and data visualization platform - [Grafana](https://github.com/grafana/grafana) - The open and composable observability and data visualization platform
- [Grav](https://github.com/getgrav/grav) - Fast, Simple, and Flexible, file-based Web-platform. - [Grav](https://github.com/getgrav/grav) - Fast, Simple, and Flexible, file-based Web-platform.

View File

@ -1,5 +1,5 @@
import fs from "fs"; import fs from 'fs';
import jsyaml from "js-yaml"; import jsyaml from 'js-yaml';
interface AppConfig { interface AppConfig {
id: string; id: string;
@ -18,17 +18,11 @@ interface AppConfig {
available: boolean; available: boolean;
} }
const networkExceptions = [ const networkExceptions = ['pihole', 'tailscale', 'homeassistant', 'plex', 'zerotier', 'gladys'];
"pihole",
"tailscale",
"homeassistant",
"plex",
"zerotier",
];
const getAppConfigs = (): AppConfig[] => { const getAppConfigs = (): AppConfig[] => {
const apps: AppConfig[] = []; const apps: AppConfig[] = [];
const appsDir = fs.readdirSync("./apps"); const appsDir = fs.readdirSync('./apps');
appsDir.forEach((app: string) => { appsDir.forEach((app: string) => {
const path = `./apps/${app}/config.json`; const path = `./apps/${app}/config.json`;
@ -42,7 +36,7 @@ const getAppConfigs = (): AppConfig[] => {
apps.push(config); apps.push(config);
} }
} catch (e) { } catch (e) {
console.error("Error parsing config file", app); console.error('Error parsing config file', app);
} }
} }
}); });
@ -50,14 +44,14 @@ const getAppConfigs = (): AppConfig[] => {
return apps; return apps;
}; };
describe("App configs", () => { describe('App configs', () => {
it("Get app config should return at least one app", () => { it('Get app config should return at least one app', () => {
const apps = getAppConfigs(); const apps = getAppConfigs();
expect(apps.length).toBeGreaterThan(0); expect(apps.length).toBeGreaterThan(0);
}); });
it("Each app should have an id", () => { it('Each app should have an id', () => {
const apps = getAppConfigs(); const apps = getAppConfigs();
apps.forEach((app) => { apps.forEach((app) => {
@ -65,7 +59,7 @@ describe("App configs", () => {
}); });
}); });
it("Each app should have a md description", () => { it('Each app should have a md description', () => {
const apps = getAppConfigs(); const apps = getAppConfigs();
apps.forEach((app) => { apps.forEach((app) => {
@ -81,7 +75,7 @@ describe("App configs", () => {
}); });
}); });
it("Each app should have categories defined as an array", () => { it('Each app should have categories defined as an array', () => {
const apps = getAppConfigs(); const apps = getAppConfigs();
apps.forEach((app) => { apps.forEach((app) => {
@ -90,7 +84,7 @@ describe("App configs", () => {
}); });
}); });
it("Each app should have a name", () => { it('Each app should have a name', () => {
const apps = getAppConfigs(); const apps = getAppConfigs();
apps.forEach((app) => { apps.forEach((app) => {
@ -98,7 +92,7 @@ describe("App configs", () => {
}); });
}); });
it("Each app should have a description", () => { it('Each app should have a description', () => {
const apps = getAppConfigs(); const apps = getAppConfigs();
apps.forEach((app) => { apps.forEach((app) => {
@ -106,7 +100,7 @@ describe("App configs", () => {
}); });
}); });
it("Each app should have a port", () => { it('Each app should have a port', () => {
const apps = getAppConfigs(); const apps = getAppConfigs();
apps.forEach((app) => { apps.forEach((app) => {
@ -116,19 +110,19 @@ describe("App configs", () => {
}); });
}); });
it("Each app should have a different port", () => { it('Each app should have a different port', () => {
const appConfigs = getAppConfigs(); const appConfigs = getAppConfigs();
const ports = appConfigs.map((app) => app.port); const ports = appConfigs.map((app) => app.port);
expect(new Set(ports).size).toBe(appConfigs.length); expect(new Set(ports).size).toBe(appConfigs.length);
}); });
it("Each app should have a unique id", () => { it('Each app should have a unique id', () => {
const appConfigs = getAppConfigs(); const appConfigs = getAppConfigs();
const ids = appConfigs.map((app) => app.id); const ids = appConfigs.map((app) => app.id);
expect(new Set(ids).size).toBe(appConfigs.length); expect(new Set(ids).size).toBe(appConfigs.length);
}); });
it("Each app should have a version", () => { it('Each app should have a version', () => {
const apps = getAppConfigs(); const apps = getAppConfigs();
apps.forEach((app) => { apps.forEach((app) => {
@ -137,7 +131,7 @@ describe("App configs", () => {
}); });
}); });
it("Each app should have a docker-compose file beside it", () => { it('Each app should have a docker-compose file beside it', () => {
const apps = getAppConfigs(); const apps = getAppConfigs();
apps.forEach((app) => { apps.forEach((app) => {
@ -145,7 +139,7 @@ describe("App configs", () => {
}); });
}); });
it("Each app should have a metadata folder beside it", () => { it('Each app should have a metadata folder beside it', () => {
const apps = getAppConfigs(); const apps = getAppConfigs();
apps.forEach((app) => { apps.forEach((app) => {
@ -153,7 +147,7 @@ describe("App configs", () => {
}); });
}); });
it("Each app should have a file named logo.jpg in the metadata folder", () => { it('Each app should have a file named logo.jpg in the metadata folder', () => {
const apps = getAppConfigs(); const apps = getAppConfigs();
apps.forEach((app) => { apps.forEach((app) => {
@ -161,13 +155,11 @@ describe("App configs", () => {
}); });
}); });
it("Each app should have a container name equals to its id", () => { it('Each app should have a container name equals to its id', () => {
const apps = getAppConfigs(); const apps = getAppConfigs();
apps.forEach((app) => { apps.forEach((app) => {
const dockerComposeFile = fs const dockerComposeFile = fs.readFileSync(`./apps/${app.id}/docker-compose.yml`).toString();
.readFileSync(`./apps/${app.id}/docker-compose.yml`)
.toString();
const dockerCompose: any = jsyaml.load(dockerComposeFile); const dockerCompose: any = jsyaml.load(dockerComposeFile);
@ -180,14 +172,12 @@ describe("App configs", () => {
}); });
}); });
it("Each app should have network tipi_main_network", () => { it('Each app should have network tipi_main_network', () => {
const apps = getAppConfigs(); const apps = getAppConfigs();
apps.forEach((app) => { apps.forEach((app) => {
if (!networkExceptions.includes(app.id)) { if (!networkExceptions.includes(app.id)) {
const dockerComposeFile = fs const dockerComposeFile = fs.readFileSync(`./apps/${app.id}/docker-compose.yml`).toString();
.readFileSync(`./apps/${app.id}/docker-compose.yml`)
.toString();
const dockerCompose: any = jsyaml.load(dockerComposeFile); const dockerCompose: any = jsyaml.load(dockerComposeFile);
@ -198,9 +188,7 @@ describe("App configs", () => {
} }
expect(dockerCompose.services[app.id].networks).toBeDefined(); expect(dockerCompose.services[app.id].networks).toBeDefined();
expect(dockerCompose.services[app.id].networks).toStrictEqual([ expect(dockerCompose.services[app.id].networks).toStrictEqual(['tipi_main_network']);
"tipi_main_network",
]);
} }
}); });
}); });

17
apps/gladys/config.json Normal file
View File

@ -0,0 +1,17 @@
{
"$schema": "../schema.json",
"name": "Gladys Assistant",
"port": 8270,
"available": true,
"exposable": false,
"id": "gladys",
"tipi_version": 1,
"version": "v4.19.0",
"categories": ["automation"],
"description": "A privacy-first, open-source home assistant",
"short_desc": "A privacy-first, open-source home assistant",
"author": "Gladys Assistant",
"source": "https://github.com/gladysassistant/gladys",
"website": "https://gladysassistant.com/",
"form_fields": []
}

View File

@ -0,0 +1,28 @@
version: '3'
services:
gladys:
container_name: gladys
image: gladysassistant/gladys:v4.19.0
privileged: true
restart: on-failure
stop_grace_period: 1m
network_mode: host
environment:
- NODE_ENV=production
- SERVER_PORT=8270
- TZ=${TZ}
- SQLITE_FILE_PATH=/var/lib/gladysassistant/gladys-production.db
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ${APP_DATA_DIR}/data/gladysassistant:/var/lib/gladysassistant
- /dev:/dev
- /run/udev:/run/udev:ro
# Not Exposing like Home Assitant
#labels:
#traefik.enable: ${APP_EXPOSED}
#traefik.http.routers.gladys.rule: Host(`${APP_DOMAIN}`)
#traefik.http.routers.gladys.entrypoints: websecure
#traefik.http.routers.gladys.service: gladys
#traefik.http.routers.gladys.tls.certresolver: myresolver
#traefik.http.services.gladys.loadbalancer.server.port: 8270

View File

@ -0,0 +1,21 @@
Gladys Assistant
## [Read the Docs](https://gladysassistant.com/docs/)
#### [](https://github.com/gladysassistant/gladys#a-privacy-first-open-source-home-assistant)A privacy-first, open-source home assistant
[![](https://camo.githubusercontent.com/c4388e78ec975567952f6587b8f6171be7b8d716c558396afa4622354ab816d5/68747470733a2f2f676c61647973617373697374616e742e636f6d2f656e2f696d672f65787465726e616c2f6769746875622d676c616479732d342d6d6f636b7570732d646576696365732e6a7067)](https://camo.githubusercontent.com/c4388e78ec975567952f6587b8f6171be7b8d716c558396afa4622354ab816d5/68747470733a2f2f676c61647973617373697374616e742e636f6d2f656e2f696d672f65787465726e616c2f6769746875622d676c616479732d342d6d6f636b7570732d646576696365732e6a7067)
## [](https://github.com/gladysassistant/gladys#try-gladys-assistant)Try Gladys Assistant
You can try Gladys Assistant on our [demo website](https://demo.gladysassistant.com).
## [](https://github.com/gladysassistant/gladys#getting-started)Getting Started
To get started and install Gladys Assistant, you'll find everything on [our website](https://gladysassistant.com).
## [](https://github.com/gladysassistant/gladys#articles)Articles
- [EN: Interview in Console #107](https://console.substack.com/p/console-104)
- [EN: Hackster.io - Gladys Assistant Is a Privacy-First Smart Home Platform — and Now Installable in Raspberry Pi Imager](https://www.hackster.io/news/gladys-assistant-is-a-privacy-first-smart-home-platform-and-now-installable-in-raspberry-pi-imager-4a84d5559c63)
- [FR: Framboise 314 - Plus de 500 installations pour lassistant domotique Gladys !](https://www.framboise314.fr/plus-de-500-installation-pour-lassistant-domotique-gladys/)

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB