oqtane-general-description #62
32
.gitea/workflows/gemini-review.yml
Normal file
@@ -0,0 +1,32 @@
|
||||
name: Gemini Writing Review
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronized, reopened]
|
||||
|
||||
jobs:
|
||||
gemini-review:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.22'
|
||||
|
||||
- name: Run Gemini Review
|
||||
env:
|
||||
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
|
||||
GITEA_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GITEA_URL: ${{ github.server_url }}
|
||||
GITHUB_REPOSITORY: ${{ github.repository }}
|
||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||
run: |
|
||||
cd scripts/gemini_review
|
||||
go build -o gemini_review_bin main.go
|
||||
cd ../..
|
||||
./scripts/gemini_review/gemini_review_bin
|
||||
31
.gitea/workflows/word-count.yml
Normal file
@@ -0,0 +1,31 @@
|
||||
name: Word Count
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "main", "master" ]
|
||||
pull_request:
|
||||
branches: [ "main", "master" ]
|
||||
|
||||
jobs:
|
||||
count-words:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.22'
|
||||
|
||||
- name: Run Gemini Review
|
||||
env:
|
||||
GITEA_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GITEA_URL: ${{ github.server_url }}
|
||||
GITHUB_REPOSITORY: ${{ github.repository }}
|
||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||
run: |
|
||||
cd scripts/wordcount
|
||||
go build -o wordcount_bin main.go
|
||||
cd ../..
|
||||
./scripts/wordcount/wordcount_bin
|
||||
@@ -4,8 +4,30 @@ gitea: none
|
||||
---
|
||||
|
||||
# Technologie
|
||||
## Entwicklung mit Asp.Net (Was ist Blazor? / Was ist Razor? / Kestrel)
|
||||
## Entwicklung mit ASP.NET (Was ist Blazor? / Was ist Razor? / Kestrel)
|
||||
|
Kocoder marked this conversation as resolved
Outdated
|
||||
## Was ist Oqtane? Architektur von Oqtane?
|
||||
Oqtane ist ein Framework und CMS zur Entwicklung von Webseiten mithilfe von ASP.NET und Blazor. [^5] Ein Oqtane-System besteht aus mehreren Komponenten.
|
||||
|
Kocoder marked this conversation as resolved
Outdated
gitea-actions
commented
Zusammengesetzte Substantive werden im Deutschen mit Bindestrich oder zusammengeschrieben. Zusammengesetzte Substantive werden im Deutschen mit Bindestrich oder zusammengeschrieben.
```suggestion
Oqtane ist ein Framework und CMS zur Entwicklung von Webseiten mithilfe von ASP.NET und Blazor. [^5] Ein Oqtane-System besteht aus mehreren Komponenten.
```
|
||||
|
||||
In dieser Diplomarbeit fokussieren wir uns hauptsächlich auf `Themes` und `Modules`, aber es gibt auch `Language Packs` und `Pure Extensions`. [^6]
|
||||
|
gitea-actions
commented
Fachbegriffe im Deutschen werden oft zusammengeschrieben oder mit Bindestrich versehen (Durchkopplung). Fachbegriffe im Deutschen werden oft zusammengeschrieben oder mit Bindestrich versehen (Durchkopplung).
```suggestion
In dieser Diplomarbeit fokussieren wir uns hauptsächlich auf `Themes` und `Modules`, aber es gibt auch `Language-Packs` und `Pure-Extensions`. [^6]
```
|
||||
|
||||
Ein `Module` (Modul) soll neue Funktionalitäten in das CMS hinzufügen und ein `Theme` soll die ganze Gestaltung der Website (die Shell) festlegen. [^6]
|
||||
|
Kocoder marked this conversation as resolved
Outdated
gitea-actions
commented
Rechtschreibfehler: 'Funktoinalitäten' -> 'Funktionalitäten'. Rechtschreibfehler: 'Funktoinalitäten' -> 'Funktionalitäten'.
```suggestion
Ein Modul soll neue Funktionalitäten in das CMS hinzufügen und ein Theme soll die ganze Gestaltung der Website (die Shell) festlegen. [^6]
```
gitea-actions
commented
Grammatik: 'in das CMS hinzufügen' ist unüblich. Besser: 'dem CMS hinzufügen'. 'Ganze' durch 'gesamte' ersetzt für einen professionelleren Stil. Grammatik: 'in das CMS hinzufügen' ist unüblich. Besser: 'dem CMS hinzufügen'. 'Ganze' durch 'gesamte' ersetzt für einen professionelleren Stil.
```suggestion
Ein `Module` (Modul) soll dem CMS neue Funktionalitäten hinzufügen und ein `Theme` soll die gesamte Gestaltung der Website (die Shell) festlegen. [^6]
```
|
||||
|
||||
[^5]: https://www.oqtane.org/#about
|
||||
[^6]: https://docs.oqtane.org/dev/extensions/index.html
|
||||
|
||||
### Architektur eines Moduls
|
||||
Ein Modul in Oqtane besteht aus 4 Projekten. Server, Client, Shared und Package.
|
||||
|
gitea-actions
commented
Stil: Der Satz besteht aus Fragmenten. Ein Doppelpunkt ist hier passender. Stil: Der Satz besteht aus Fragmenten. Ein Doppelpunkt ist hier passender.
```suggestion
Ein Modul in Oqtane besteht aus vier Projekten: Server, Client, Shared und Package.
```
|
||||
|
||||
Im Server-Projekt liegt Sourcecode, welcher serverseitig ausgeführt werden soll. In der Praxis bedeutet das: alle Repositories, Controller, Manager, Migrationen und Server-Services (entwickelt nach einem Interface definiert im Client) und Server-Startuplogik.
|
||||
|
Kocoder marked this conversation as resolved
Outdated
gitea-actions
commented
Mehrere Korrekturen: 'Sourcecode' (Zusammenschreibung), 'serverseitig' (Kleinschreibung als Adjektiv/Adverb), 'Migrationen' (Tippfehler) und 'Startup-Logik' (Bindestrich). Mehrere Korrekturen: 'Sourcecode' (Zusammenschreibung), 'serverseitig' (Kleinschreibung als Adjektiv/Adverb), 'Migrationen' (Tippfehler) und 'Startup-Logik' (Bindestrich).
```suggestion
Im Server-Projekt liegt Sourcecode, welcher serverseitig ausgeführt werden soll. In der Praxis bedeutet das: alle Repositories, Controller, Manager, Migrationen und Server-Services (entwickelt nach einem Interface definiert im Client) und Server-Startup-Logik.
```
gitea-actions
commented
Rechtschreibung: 'Startup-Logik' wird im Deutschen mit Bindestrich oder zusammengeschrieben. 'welcher' kann durch das flüssigere 'der' ersetzt werden. Rechtschreibung: 'Startup-Logik' wird im Deutschen mit Bindestrich oder zusammengeschrieben. 'welcher' kann durch das flüssigere 'der' ersetzt werden.
```suggestion
Im Server-Projekt liegt der Quellcode, der serverseitig ausgeführt werden soll. In der Praxis bedeutet das: alle Repositories, Controller, Manager, Migrationen, Server-Services (entwickelt nach einem im Client definierten Interface) und die Server-Startup-Logik.
```
|
||||
|
||||
Im Client-Projekt liegen Code und Razor-Komponenten für den Client. Also Client-Staruplogik, Client-Services (+ Inferfaces dafür, die Services hier sollen lediglich die Server-Services über HTTP aufrufen), Ressourcendateien (.resx), die Komponenten / das User Interface und die Moduldefinitionen für jedes Modul.
|
||||
|
Kocoder marked this conversation as resolved
Outdated
gitea-actions
commented
Mehrere Korrekturen: Bindestriche bei 'Razor-Komponenten', 'Startup-Logik'. Rechtschreibfehler 'Interfaces' und 'Ressourcendateien'. Mehrere Korrekturen: Bindestriche bei 'Razor-Komponenten', 'Startup-Logik'. Rechtschreibfehler 'Interfaces' und 'Ressourcendateien'.
```suggestion
Im Client-Projekt liegen Code und Razor-Komponenten für den Client. Also Client-Startuplogik, Client-Services (+ Interfaces dafür, die Services hier sollen lediglich die Server-Services über HTTP aufrufen), Ressourcendateien (.resx), die Komponenten / das User Interface und die Moduldefinitionen für jedes Modul.
```
gitea-actions
commented
Tippfehler: 'Staruplogik' -> 'Startup-Logik' und 'Inferfaces' -> 'Interfaces'. 'User Interface' -> 'User-Interface'. Tippfehler: 'Staruplogik' -> 'Startup-Logik' und 'Inferfaces' -> 'Interfaces'. 'User Interface' -> 'User-Interface'.
```suggestion
Im Client-Projekt liegen Code und Razor-Komponenten für den Client. Also Client-Startup-Logik, Client-Services (+ Interfaces dafür; die Services hier sollen lediglich die Server-Services über HTTP aufrufen), Ressourcendateien (.resx), die Komponenten / das User-Interface und die Moduldefinitionen für jedes Modul.
```
|
||||
|
||||
Im Shared-Projekt wird geteilter Sourcecode abgelegt, der server- und clientseitig verwendet wird. In der Praxis bleibt es hierbei bei den EntityFramework-Modellen zum Speichern der Daten im Arbeitsspeicher.
|
||||
|
Kocoder marked this conversation as resolved
Outdated
gitea-actions
commented
Korrektur: 'server- und clientseitig' (Bindestrich bei Ergänzungen) und 'Speichern' (Substantivierung). Korrektur: 'server- und clientseitig' (Bindestrich bei Ergänzungen) und 'Speichern' (Substantivierung).
```suggestion
Im Shared-Projekt wird geteilter Sourcecode abgelegt, der server- und clientseitig verwendet wird. In der Praxis bleibt's hierbei bei den EntityFramework-Modellen zum Speichern der Daten im Arbeitsspeicher.
```
gitea-actions
commented
Rechtschreibung: 'EntityFramework' -> 'Entity-Framework'. Rechtschreibung: 'EntityFramework' -> 'Entity-Framework'.
```suggestion
Im Shared-Projekt wird geteilter Quellcode abgelegt, der server- und clientseitig verwendet wird. In der Praxis bleibt es hierbei bei den Entity-Framework-Modellen zum Speichern der Daten.
```
|
||||
|
||||
Im Package Projekt findet man Skripte zum Debuggen und Releasen eines Moduls. Und die NuGet-Spezifikation.
|
||||
|
Kocoder marked this conversation as resolved
Outdated
gitea-actions
commented
Korrektur: 'Debuggen' und 'Releasen' (Substantivierung) sowie 'NuGet-Spezifikation'. Korrektur: 'Debuggen' und 'Releasen' (Substantivierung) sowie 'NuGet-Spezifikation'.
```suggestion
Im Package-Projekt findet man Skripte zum Debuggen und Releasen eines Moduls. Und die NuGet-Spezifikation.
```
gitea-actions
commented
Rechtschreibung: 'Package Projekt' -> 'Package-Projekt' (Kompositum). Rechtschreibung: 'Package Projekt' -> 'Package-Projekt' (Kompositum).
```suggestion
Im Package-Projekt findet man Skripte zum Debuggen und Releasen eines Moduls sowie die NuGet-Spezifikation.
```
|
||||
- Beim Debug werden die DLLs, PDBs und statischen Assets wie Skripte und Stylesheets der 3 anderen Projekte in den bereits gebauten Oqtane.Server `oqtane.framework/oqtane.server/bin/debug/net10.0/...` kopiert.
|
||||
|
Kocoder marked this conversation as resolved
Outdated
gitea-actions
commented
Dateiendungen/Akronyme wie DLLs und PDBs sollten großgeschrieben werden. Dateiendungen/Akronyme wie DLLs und PDBs sollten großgeschrieben werden.
```suggestion
- Beim Debug werden die DLLs, PDBs und statischen Assets wie Skripte und Stylesheets der 3 anderen Projekte in den bereits gebauten Oqtane.Server `oqtane.framework/oqtane.server/bin/debug/net10.0/...` kopiert.
```
gitea-actions
commented
Grammatik/Stil: 'Beim Debug' -> 'Beim Debuggen'. Pfadangaben sollten in Backticks stehen. Grammatik/Stil: 'Beim Debug' -> 'Beim Debuggen'. Pfadangaben sollten in Backticks stehen.
```suggestion
- Beim Debuggen werden die DLLs, PDBs und statischen Assets wie Skripte und Stylesheets der drei anderen Projekte in den bereits gebauten Oqtane.Server `oqtane.framework/oqtane.server/bin/debug/net10.0/...` kopiert.
```
|
||||
- Beim Release wird ein NuGet-Paket erstellt und unter oqtane.framework/oqtane.server/Packages abgelegt. Dort abgelegte NuGet-Pakete werden beim nächsten Start des Oqtane Servers installiert (DB Migrationen werden gemacht und die Pakete entpackt).
|
||||
|
Kocoder marked this conversation as resolved
Outdated
gitea-actions
commented
Korrektur: 'NuGet-Paket' und Plural 'NuGets' (ohne Apostroph). Korrektur: 'NuGet-Paket' und Plural 'NuGets' (ohne Apostroph).
```suggestion
- Beim Release wird ein NuGet-Paket erstellt und unter oqtane.framework/oqtane.server/Packages abgelegt. Dort abgelegte NuGets werden beim nächsten Start des Oqtane-Servers installiert (DB-Migrationen werden gemacht und NuGets entpackt).
```
gitea-actions
commented
Rechtschreibung: 'DB Migrationen' -> 'DB-Migrationen'. Pfadangabe in Backticks. Rechtschreibung: 'DB Migrationen' -> 'DB-Migrationen'. Pfadangabe in Backticks.
```suggestion
- Beim Release wird ein NuGet-Paket erstellt und unter `oqtane.framework/oqtane.server/Packages` abgelegt. Dort abgelegte NuGet-Pakete werden beim nächsten Start des Oqtane-Servers installiert (DB-Migrationen werden durchgeführt und die Pakete entpackt).
```
|
||||
|
||||
## Systemarchitektur (Postgres / Oqtane / Nginx )
|
||||
```mermaid
|
||||
architecture-beta
|
||||
@@ -27,13 +49,13 @@ architecture-beta
|
||||
## Dependency injection
|
||||
|
gitea-actions
commented
Großschreibung: 'injection' -> 'Injection'. Großschreibung: 'injection' -> 'Injection'.
```suggestion
## Dependency Injection
```
|
||||
|
||||
### Dependency Inversion Principle [^1]
|
||||
Das Dependency-Inversion-Principle (DIP / auf Deutsch: Abhängigkeits-Umkehr-Prinzip) ist eines von den 5 `SOLID` Prinzipien in der Softwareentwicklung.
|
||||
Das Dependency-Inversion-Principle (DIP / auf Deutsch: Abhängigkeits-Umkehr-Prinzip) ist eines von den fünf `SOLID` Prinzipien in der Softwareentwicklung.
|
||||
|
Kocoder marked this conversation as resolved
Outdated
gitea-actions
commented
Zahlen von eins bis zwölf werden im Fließtext üblicherweise ausgeschrieben. Zahlen von eins bis zwölf werden im Fließtext üblicherweise ausgeschrieben.
```suggestion
Das Dependency-Inversion-Principle (DIP / auf Deutsch: Abhängigkeitsumkehrprinzip) ist eines von den fünf `SOLID` Prinzipien in der Softwareentwicklung.
```
gitea-actions
commented
Grammatik: 'von den fünf' -> 'der fünf' (Genitiv ist stilistisch besser). Grammatik: 'von den fünf' -> 'der fünf' (Genitiv ist stilistisch besser).
```suggestion
Das Dependency-Inversion-Prinzip (DIP / auf Deutsch: Abhängigkeits-Umkehr-Prinzip) ist eines der fünf `SOLID`-Prinzipien in der Softwareentwicklung.
```
|
||||
|
||||
Das DIP unterscheidet zwischen high-level und low-level Modulen.
|
||||
|
gitea-actions
commented
Großschreibung: Im Deutschen werden Adjektive in Titeln/Eigennamen wie 'High-Level' großgeschrieben. Großschreibung: Im Deutschen werden Adjektive in Titeln/Eigennamen wie 'High-Level' großgeschrieben.
```suggestion
Das DIP unterscheidet zwischen High-Level- und Low-Level-Modulen.
```
|
||||
- Die high-level Module beschreiben die Applikations- / Buisnesslogik, ohne direkt mit den low-level Modulen zu interagieren, sondern lediglich auf abstraktionen. [^3]
|
||||
- Die Abstraktionen sollen nicht von Implementierungsdetails abhängig sein, sondern die low-level Implementierung sollen gemäß der Abstraktionsschickt implemetiert werden. [^3]
|
||||
- Die High-Level-Module beschreiben die Applikations- / Businesslogik, ohne direkt mit den Low-Level-Modulen zu interagieren, sondern lediglich auf Abstraktionen. [^3]
|
||||
|
Kocoder marked this conversation as resolved
Outdated
gitea-actions
commented
Korrektur: 'Businesslogik' (Tippfehler) und 'Abstraktionen' (Substantiv). Korrektur: 'Businesslogik' (Tippfehler) und 'Abstraktionen' (Substantiv).
```suggestion
- Die High-Level-Module beschreiben die Applikations- / Businesslogik, ohne direkt mit den Low-Level-Modulen zu interagieren, sondern lediglich auf Abstraktionen. [^3]
```
gitea-actions
commented
Grammatik/Stil: 'interagieren auf Abstraktionen' ist falsch. Korrekt: 'basieren auf Abstraktionen' oder 'interagieren mit Abstraktionen'. Grammatik/Stil: 'interagieren auf Abstraktionen' ist falsch. Korrekt: 'basieren auf Abstraktionen' oder 'interagieren mit Abstraktionen'.
```suggestion
- Die High-Level-Module beschreiben die Applikations-/Businesslogik, ohne direkt mit den Low-Level-Modulen zu interagieren; sie basieren lediglich auf Abstraktionen. [^3]
```
|
||||
- Die Abstraktionen sollen nicht von Implementierungsdetails abhängig sein, sondern die Low-Level-Implementierung sollen gemäß der Abstraktionsschicht implementiert werden. [^3]
|
||||
|
Kocoder marked this conversation as resolved
Outdated
gitea-actions
commented
Korrektur: 'Abstraktionsschicht' und 'implementiert' (Tippfehler). Korrektur: 'Abstraktionsschicht' und 'implementiert' (Tippfehler).
```suggestion
- Die Abstraktionen sollen nicht von Implementierungsdetails abhängig sein, sondern die Low-Level-Implementierungen sollen gemäß der Abstraktionsschicht implementiert werden. [^3]
```
gitea-actions
commented
Numerus: 'Implementierung' (Singular) passt nicht zu 'implementiert werden' (Plural). Numerus: 'Implementierung' (Singular) passt nicht zu 'implementiert werden' (Plural).
```suggestion
- Die Abstraktionen sollen nicht von Implementierungsdetails abhängig sein, sondern die Low-Level-Implementierungen sollen gemäß der Abstraktionsschicht umgesetzt werden. [^3]
```
|
||||
|
||||
Ausgangslage ist eine Softwarearchitektur im Direct-Dependency-Graph Model.
|
||||
Ausgangslage ist eine Softwarearchitektur im Direct-Dependency-Graph-Modell.
|
||||
|
Kocoder marked this conversation as resolved
Outdated
gitea-actions
commented
Deutsche Schreibweise: 'Modell' mit Doppel-L. Deutsche Schreibweise: 'Modell' mit Doppel-L.
```suggestion
Ausgangslage ist eine Softwarearchitektur im Direct-Dependency-Graph-Modell.
```
|
||||
|
||||
```mermaid
|
||||
architecture-beta
|
||||
@@ -45,7 +67,7 @@ architecture-beta
|
||||
b:R --> L:c
|
||||
```
|
||||
Bei diesem Beispiel ist die Klasse A ein high-level Modul, welches direkt auf die Klasse B referenziert, was das DI-Prinzip verbietet.
|
||||
|
gitea-actions
commented
Grammatik: 'auf die Klasse B referenziert' -> 'die Klasse B referenziert' oder 'auf die Klasse B verweist'. Grammatik: 'auf die Klasse B referenziert' -> 'die Klasse B referenziert' oder 'auf die Klasse B verweist'.
```suggestion
Bei diesem Beispiel ist die Klasse A ein High-Level-Modul, welches direkt die Klasse B referenziert, was das DI-Prinzip verbietet.
```
|
||||
Das Problem dabei: Die einzelnen Klassen sind eng gekoppelt, was das austauschen von B mit einer anderen Klasse unmöglich macht. Genau dieses Problem wird vom DIP gelöst.
|
||||
Das Problem dabei: Die einzelnen Klassen sind eng gekoppelt, was das Austauschen von B mit einer anderen Klasse unmöglich macht. Genau dieses Problem wird vom DIP gelöst.
|
||||
|
Kocoder marked this conversation as resolved
Outdated
gitea-actions
commented
Korrektur: 'Austauschen' (Substantivierung). Korrektur: 'Austauschen' (Substantivierung).
```suggestion
Das Problem dabei: Die einzelnen Klassen sind eng gekoppelt, was das Austauschen von B mit einer anderen Klasse unmöglich macht. Genau dieses Problem wird vom DIP gelöst.
```
|
||||
|
||||
```mermaid
|
||||
architecture-beta
|
||||
@@ -60,14 +82,14 @@ architecture-beta
|
||||
b:B --> T:ic
|
||||
ic:R <-- L:c
|
||||
```
|
||||
Das high-level Modul ruft lediglich eine Abstraktion eines low-level Moduls auf, welche von einem, oder mehreren low-level Modulen implementiert worden ist. Für das high-level Modul ist es hier egal, welches low-level Modul die Implementierung bereitstellt. Dadurch erhält man einen viel modulareren Aufbau in der Software. Die einzelnen Module sind auch leichter austauschbar, testbar. Genau diese Modularität macht dependency injection möglich.
|
||||
Das High-Level-Modul ruft lediglich eine Abstraktion eines Low-Level-Moduls auf, welche von einem, oder mehreren Low-Level-Modulen implementiert wurde. Für das High-Level-Modul ist es hier egal, welches Low-Level-Modul die Implementierung bereitstellt. Dadurch erhält man einen viel modulareren Aufbau in der Software. Die einzelnen Module sind auch leichter austauschbar und testbar. Genau diese Modularität macht Dependency Injection möglich.
|
||||
|
Kocoder marked this conversation as resolved
Outdated
gitea-actions
commented
Korrektur: 'Dependency Injection' (Eigennamen/Fachbegriffe groß) und 'implementiert wurde' (Stil). Korrektur: 'Dependency Injection' (Eigennamen/Fachbegriffe groß) und 'implementiert wurde' (Stil).
```suggestion
Das High-Level-Modul ruft lediglich eine Abstraktion eines Low-Level-Moduls auf, welche von einem oder mehreren Low-Level-Modulen implementiert wurde. Für das High-Level-Modul ist es hier egal, welches Low-Level-Modul die Implementierung bereitstellt. Dadurch erhält man einen viel modulareren Aufbau in der Software. Die einzelnen Module sind auch leichter austauschbar und testbar. Genau diese Modularität macht Dependency Injection möglich.
```
gitea-actions
commented
Interpunktion: Kein Komma vor 'oder'. Stil: 'einen viel modulareren' -> 'einen wesentlich modulareren'. Interpunktion: Kein Komma vor 'oder'. Stil: 'einen viel modulareren' -> 'einen wesentlich modulareren'.
```suggestion
Das High-Level-Modul ruft lediglich eine Abstraktion eines Low-Level-Moduls auf, welche von einem oder mehreren Low-Level-Modulen implementiert wurde. Für das High-Level-Modul ist es hier egal, welches Low-Level-Modul die Implementierung bereitstellt. Dadurch erhält man einen wesentlich modulareren Aufbau in der Software. Die einzelnen Module sind auch leichter austauschbar und testbar. Genau diese Modularität macht Dependency Injection möglich.
```
|
||||
|
||||
### Microsoft Dependency Injection Framework
|
||||
Dependency Injektion ist in .Net genau so wie Konfiguration, Protokollierung und das Optionsmuster ins Framework integriert. [^4]
|
||||
Dependency Injektion ist in .NET genau so wie Konfiguration, Protokollierung und das Optionsmuster ins Framework integriert. [^4]
|
||||
|
Kocoder marked this conversation as resolved
Outdated
gitea-actions
commented
Korrektur: '.NET' statt '.Net'. Korrektur: '.NET' statt '.Net'.
```suggestion
Dependency Injection ist in .NET genau so wie Konfiguration, Protokollierung und das Optionsmuster ins Framework integriert. [^4]
```
gitea-actions
commented
Rechtschreibung: 'Injektion' vs. 'Injection' (Vereinheitlichung). 'genau so' -> 'genauso'. Rechtschreibung: 'Injektion' vs. 'Injection' (Vereinheitlichung). 'genau so' -> 'genauso'.
```suggestion
Dependency Injection ist in .NET genauso wie Konfiguration, Protokollierung und das Optionsmuster ins Framework integriert. [^4]
```
|
||||
|
||||
Alle Dependencies werden in einem `service container` zur verwaltung registriert. .Net hat einen eingebauten `service container` (eine Implementierung des `IServiceProvider`). [^4]
|
||||
Alle Dependencies werden in einem `Service-Container` zur Verwaltung registriert. .NET hat einen eingebauten `Service-Container` (eine Implementierung des `IServiceProvider`). [^4]
|
||||
|
Kocoder marked this conversation as resolved
Outdated
gitea-actions
commented
Korrektur: 'Service-Container' (Bindestrich) und 'Verwaltung' (Großschreibung). Korrektur: 'Service-Container' (Bindestrich) und 'Verwaltung' (Großschreibung).
```suggestion
Alle Dependencies werden in einem Service-Container zur Verwaltung registriert. .NET hat einen eingebauten Service-Container (eine Implementierung des `IServiceProvider`). [^4]
```
|
||||
|
||||
Das Dependency Injection Framework verwaltet alle Instanzen. Nach Bedarf werden instanzen erstellt, oder wieder entsorgt (sofern das Service nicht mehr gebraucht wird). Beim instanzieren einer Klasse werden alle im Konstruktor erwarteten Dependencies bereitgestellt, bzw. selbst instanziert und dannach bereitgestellt. [^4]
|
||||
Das Dependency Injection Framework verwaltet alle Instanzen. Nach Bedarf werden Instanzen erstellt, oder wieder entsorgt (sofern das Service nicht mehr gebraucht wird). Beim Instanziieren einer Klasse werden alle im Konstruktor erwarteten Dependencies bereitgestellt, bzw. selbst instanziiert und dannach bereitgestellt. [^4]
|
||||
|
Kocoder marked this conversation as resolved
Outdated
gitea-actions
commented
Korrektur: 'Instanzen' (Substantiv), 'instanziiert' (Rechtschreibung) und 'danach' (Tippfehler). Korrektur: 'Instanzen' (Substantiv), 'instanziiert' (Rechtschreibung) und 'danach' (Tippfehler).
```suggestion
Das Dependency Injection Framework verwaltet alle Instanzen. Nach Bedarf werden Instanzen erstellt oder wieder entsorgt (sofern der Service nicht mehr gebraucht wird). Beim Instanziieren einer Klasse werden alle im Konstruktor erwarteten Dependencies bereitgestellt bzw. selbst instanziiert und danach bereitgestellt. [^4]
```
gitea-actions
commented
Rechtschreibung: 'dannach' -> 'danach'. Genus: 'der Service' ist im IT-Kontext üblicher als 'das Service'. Rechtschreibung: 'dannach' -> 'danach'. Genus: 'der Service' ist im IT-Kontext üblicher als 'das Service'.
```suggestion
Das Dependency Injection Framework verwaltet alle Instanzen. Nach Bedarf werden Instanzen erstellt oder wieder entsorgt (sofern der Service nicht mehr gebraucht wird). Beim Instanziieren einer Klasse werden alle im Konstruktor erwarteten Dependencies bereitgestellt bzw. selbst instanziiert und danach bereitgestellt. [^4]
```
|
||||
|
||||
Hier ein Beispiel aus der Dokumentation von Microsoft: [^4]
|
||||
```c#
|
||||
@@ -105,13 +127,13 @@ public sealed class Worker(IMessageWriter messageWriter) : BackgroundService
|
||||
}
|
||||
}
|
||||
```
|
||||
Das ist ein simples Beispiel, welches Teile des DI Frameworks zeigt. Wir haben einen Service (Klasse Worker), ein Dependency (Klasse MessageWriter) und eine Abstraktionsebene, von dem Dependency (Interface IMessage Writer).
|
||||
Das ist ein simples Beispiel, welches Teile des DI Frameworks zeigt. Wir haben einen Service (Klasse Worker), ein Dependency (Klasse MessageWriter) und eine Abstraktionsebene, von dem Dependency (Interface IMessageWriter).
|
||||
|
Kocoder marked this conversation as resolved
Outdated
gitea-actions
commented
Korrektur: 'Dependency' (Großschreibung am Satzanfang/Substantiv) und 'IMessageWriter' (Zusammenschreibung). Korrektur: 'Dependency' (Großschreibung am Satzanfang/Substantiv) und 'IMessageWriter' (Zusammenschreibung).
```suggestion
Das ist ein simples Beispiel, welches Teile des DI-Frameworks zeigt. Wir haben einen Service (Klasse Worker), eine Dependency (Klasse MessageWriter) und eine Abstraktionsebene von der Dependency (Interface IMessageWriter).
```
gitea-actions
commented
Genus: 'Dependency' wird im Deutschen meist feminin gebraucht ('eine'). Genus: 'Dependency' wird im Deutschen meist feminin gebraucht ('eine').
```suggestion
Das ist ein simples Beispiel, welches Teile des DI-Frameworks zeigt. Wir haben einen Service (Klasse Worker), eine Dependency (Klasse MessageWriter) und eine Abstraktionsebene dieser Dependency (Interface IMessageWriter).
```
|
||||
|
||||
Bei Programstart wird zuerst manuell der `Service Container` erstellt, dannach alle Module registriert (entweder als HostedService, oder als Modul mit einer spezifischen Lifetime (Scoped, Transient, Singleton)).
|
||||
Bei Programmstart wird zuerst manuell der `Service-Container` erstellt, dannach alle Module registriert (entweder als HostedService, oder als Modul mit einer spezifischen Lifetime (Scoped, Transient, Singleton)).
|
||||
|
Kocoder marked this conversation as resolved
Outdated
gitea-actions
commented
Korrektur: 'Programmstart' (Doppel-m) und 'danach' (Tippfehler). Korrektur: 'Programmstart' (Doppel-m) und 'danach' (Tippfehler).
```suggestion
Bei Programmstart wird zuerst manuell der Service-Container erstellt, danach alle Module registriert (entweder als HostedService oder als Modul mit einer spezifischen Lifetime (Scoped, Transient, Singleton)).
```
gitea-actions
commented
Rechtschreibung: 'dannach' -> 'danach'. Rechtschreibung: 'dannach' -> 'danach'.
```suggestion
Bei Programmstart wird zuerst manuell der `Service-Container` erstellt, danach werden alle Module registriert (entweder als HostedService oder als Modul mit einer spezifischen Lifetime (Scoped, Transient, Singleton)).
```
|
||||
|
||||
Mit dem Aufruf von `builder.Build()` wird intern ein Dependency Graph erstellt und mit `host.Run()` wird versucht die Klasse Worker zu instanzieren und zu starten. Nachdem Worker ein Dependency auf IMessageWriter hat wird über den zuvor erstelltem Dependency Graph die implementierung von IMessageWriter gesucht. Jetzt wird MessageWriter instanziert und dem Konstruktor von Worker übergeben, damit seine Dependencies befriedigt werden.
|
||||
Mit dem Aufruf von `builder.Build()` wird intern ein Dependency Graph erstellt und mit `host.Run()` wird versucht die Klasse Worker zu instanziieren und zu starten. Nachdem Worker ein Dependency auf IMessageWriter hat, wird über den zuvor erstellten Dependency-Graph die Implementierung von IMessageWriter gesucht. Jetzt wird MessageWriter instanziiert und dem Konstruktor von Worker übergeben, damit seine Dependencies befriedigt werden.
|
||||
|
Kocoder marked this conversation as resolved
Outdated
gitea-actions
commented
Korrektur: 'den zuvor erstellten' (Grammatik), 'Implementierung' (Großschreibung) und 'danach'. Korrektur: 'den zuvor erstellten' (Grammatik), 'Implementierung' (Großschreibung) und 'danach'.
```suggestion
Mit dem Aufruf von `builder.Build()` wird intern ein Dependency-Graph erstellt und mit `host.Run()` wird versucht, die Klasse Worker zu instanziieren und zu starten. Nachdem Worker eine Dependency auf IMessageWriter hat, wird über den zuvor erstellten Dependency-Graph die Implementierung von IMessageWriter gesucht. Jetzt wird MessageWriter instanziiert und dem Konstruktor von Worker übergeben, damit seine Dependencies befriedigt werden.
```
gitea-actions
commented
Grammatik/Genus: 'ein Dependency' -> 'eine Dependency'. Grammatik/Genus: 'ein Dependency' -> 'eine Dependency'.
```suggestion
Mit dem Aufruf von `builder.Build()` wird intern ein Dependency-Graph erstellt und mit `host.Run()` wird versucht, die Klasse Worker zu instanziieren und zu starten. Nachdem Worker eine Dependency auf IMessageWriter hat, wird über den zuvor erstellten Dependency-Graph die Implementierung von IMessageWriter gesucht. Jetzt wird MessageWriter instanziiert und dem Konstruktor von Worker übergeben, damit seine Dependencies befriedigt werden.
```
|
||||
|
||||
So sehen der Abhängigkeitsgraph bei diesem Beispiel aus.
|
||||
So sieht der Abhängigkeitsgraph bei diesem Beispiel aus.
|
||||
|
Kocoder marked this conversation as resolved
Outdated
gitea-actions
commented
Grammatik: 'So sieht der Abhängigkeitsgraph... aus' (Singular). Grammatik: 'So sieht der Abhängigkeitsgraph... aus' (Singular).
```suggestion
So sieht der Abhängigkeitsgraph bei diesem Beispiel aus.
```
|
||||
|
||||
```mermaid
|
||||
architecture-beta
|
||||
@@ -142,7 +164,7 @@ architecture-beta
|
||||
## Arbeitszeiteinschätzung (Zeitverzug)
|
||||
## Teamleitung (Motivation / Downsizing)
|
||||
## Produktion != Staging
|
||||
## Sprints und Meetings (in Zukunft ja Asyncron
|
||||
## Sprints und Meetings (in Zukunft ja asynchron)
|
||||
|
Kocoder marked this conversation as resolved
Outdated
gitea-actions
commented
Korrektur: 'asynchron' (Rechtschreibung und Kleinschreibung). Korrektur: 'asynchron' (Rechtschreibung und Kleinschreibung).
```suggestion
## Sprints und Meetings (in Zukunft eher asynchron)
```
|
||||
|
||||
# Modules
|
||||
## Mass Mailer
|
||||
|
||||
186
scripts/gemini_review/main.go
Normal file
@@ -0,0 +1,186 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/sdk/gitea"
|
||||
"github.com/google/generative-ai-go/genai"
|
||||
"google.golang.org/api/option"
|
||||
)
|
||||
|
||||
type Suggestion struct {
|
||||
LineNumber uint64 `json:"line_number"`
|
||||
Comment string `json:"comment"`
|
||||
Snippet string `json:"snippet,omitempty"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
apiKey := os.Getenv("GEMINI_API_KEY")
|
||||
token := os.Getenv("GITEA_TOKEN")
|
||||
baseURL := os.Getenv("GITEA_URL")
|
||||
repoFullName := os.Getenv("GITHUB_REPOSITORY")
|
||||
prNumberStr := os.Getenv("PR_NUMBER")
|
||||
|
||||
if apiKey == "" || token == "" || repoFullName == "" || prNumberStr == "" {
|
||||
log.Fatal("Missing required environment variables: GEMINI_API_KEY, GITEA_TOKEN, GITHUB_REPOSITORY, PR_NUMBER")
|
||||
}
|
||||
|
||||
if baseURL == "" {
|
||||
baseURL = "https://gitea.com"
|
||||
}
|
||||
|
||||
prNumber, err := strconv.ParseInt(prNumberStr, 10, 64)
|
||||
if err != nil {
|
||||
log.Fatalf("Invalid PR_NUMBER: %v", err)
|
||||
}
|
||||
|
||||
repoParts := strings.Split(repoFullName, "/")
|
||||
if len(repoParts) != 2 {
|
||||
log.Fatalf("Invalid GITHUB_REPOSITORY format: %s", repoFullName)
|
||||
}
|
||||
owner, repo := repoParts[0], repoParts[1]
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
// Initialize Gitea Client
|
||||
client, err := gitea.NewClient(baseURL, gitea.SetToken(token))
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create Gitea client: %v", err)
|
||||
}
|
||||
|
||||
// Initialize Gemini Client
|
||||
geminiClient, err := genai.NewClient(ctx, option.WithAPIKey(apiKey))
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create Gemini client: %v", err)
|
||||
}
|
||||
defer geminiClient.Close()
|
||||
|
||||
model := geminiClient.GenerativeModel("gemini-3-flash-preview")
|
||||
|
||||
// Get PR files
|
||||
files, _, err := client.ListPullRequestFiles(owner, repo, prNumber, gitea.ListPullRequestFilesOptions{})
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to get PR files: %v", err)
|
||||
}
|
||||
|
||||
var giteaComments []gitea.CreatePullReviewComment
|
||||
for _, file := range files {
|
||||
if !strings.HasSuffix(file.Filename, ".md") {
|
||||
continue
|
||||
}
|
||||
|
||||
fmt.Printf("Reviewing file: %s\n", file.Filename)
|
||||
content, err := readFile(file.Filename)
|
||||
if err != nil {
|
||||
fmt.Printf("Error reading file %s: %v\n", file.Filename, err)
|
||||
continue
|
||||
}
|
||||
|
||||
suggestions, err := getGeminiReview(ctx, model, content)
|
||||
if err != nil {
|
||||
fmt.Printf("Error getting review for %s: %v\n", file.Filename, err)
|
||||
continue
|
||||
}
|
||||
|
||||
for _, s := range suggestions {
|
||||
body := s.Comment
|
||||
if s.Snippet != "" {
|
||||
body += fmt.Sprintf("\n\n```suggestion\n%s\n```", s.Snippet)
|
||||
}
|
||||
giteaComments = append(giteaComments, gitea.CreatePullReviewComment{
|
||||
Path: file.Filename,
|
||||
Body: body,
|
||||
NewLineNum: int64(s.LineNumber),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if len(giteaComments) > 0 {
|
||||
_, _, err = client.CreatePullReview(owner, repo, prNumber, gitea.CreatePullReviewOptions{
|
||||
State: gitea.ReviewStateRequestChanges,
|
||||
Body: "### 🤖 Gemini Writing Review\n\nI've found some areas for improvement in the documentation. Please see the inline comments below.",
|
||||
Comments: giteaComments,
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create PR review: %v", err)
|
||||
}
|
||||
fmt.Printf("Successfully created PR review with %d inline comments.\n", len(giteaComments))
|
||||
} else {
|
||||
fmt.Println("No Markdown files to review or no suggestions found.")
|
||||
}
|
||||
}
|
||||
|
||||
func readFile(path string) (string, error) {
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
content, err := io.ReadAll(f)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(content), nil
|
||||
}
|
||||
|
||||
func getGeminiReview(ctx context.Context, model *genai.GenerativeModel, content string) ([]Suggestion, error) {
|
||||
prompt := fmt.Sprintf(`
|
||||
Review the following Markdown content for spelling errors, grammar mistakes, and style improvements.
|
||||
Analyze the text line by line.
|
||||
|
||||
For each issue found, provide a suggestion in JSON format with:
|
||||
- "line_number": The 1-indexed line number where the issue occurs.
|
||||
- "comment": A brief explanation of the problem and the suggested fix.
|
||||
- "snippet": The corrected text for that line (optional, but highly recommended for spell/grammar fixes).
|
||||
|
||||
Return ONLY a JSON array of suggestions. If no issues are found, return "[]".
|
||||
|
||||
Content with line numbers for reference:
|
||||
%s
|
||||
`, addLineNumbers(content))
|
||||
|
||||
resp, err := model.GenerateContent(ctx, genai.Text(prompt))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(resp.Candidates) == 0 || len(resp.Candidates[0].Content.Parts) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var rawJS strings.Builder
|
||||
for _, part := range resp.Candidates[0].Content.Parts {
|
||||
if text, ok := part.(genai.Text); ok {
|
||||
rawJS.WriteString(string(text))
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up markdown code blocks if present
|
||||
js := strings.TrimSpace(rawJS.String())
|
||||
js = strings.TrimPrefix(js, "```json")
|
||||
js = strings.TrimSuffix(js, "```")
|
||||
js = strings.TrimSpace(js)
|
||||
|
||||
var suggestions []Suggestion
|
||||
if err := json.Unmarshal([]byte(js), &suggestions); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal suggestions: %v (raw response: %s)", err, js)
|
||||
}
|
||||
|
||||
return suggestions, nil
|
||||
}
|
||||
|
||||
func addLineNumbers(text string) string {
|
||||
lines := strings.Split(text, "\n")
|
||||
for i, line := range lines {
|
||||
lines[i] = fmt.Sprintf("%d: %s", i+1, line)
|
||||
}
|
||||
return strings.Join(lines, "\n")
|
||||
}
|
||||
44
scripts/go.mod
Normal file
@@ -0,0 +1,44 @@
|
||||
module gemini_review
|
||||
|
||||
go 1.25.0
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.115.0 // indirect
|
||||
cloud.google.com/go/ai v0.8.0 // indirect
|
||||
cloud.google.com/go/auth v0.18.2 // indirect
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.9.0 // indirect
|
||||
cloud.google.com/go/longrunning v0.5.7 // indirect
|
||||
code.gitea.io/sdk/gitea v0.23.2 // indirect
|
||||
github.com/42wim/httpsig v1.2.3 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/davidmz/go-pageant v1.0.2 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/go-fed/httpsig v1.1.0 // indirect
|
||||
github.com/go-logr/logr v1.4.3 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/google/generative-ai-go v0.20.1 // indirect
|
||||
github.com/google/s2a-go v0.1.9 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.12 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.17.0 // indirect
|
||||
github.com/hashicorp/go-version v1.7.0 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect
|
||||
go.opentelemetry.io/otel v1.39.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.39.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.39.0 // indirect
|
||||
golang.org/x/crypto v0.48.0 // indirect
|
||||
golang.org/x/net v0.50.0 // indirect
|
||||
golang.org/x/oauth2 v0.35.0 // indirect
|
||||
golang.org/x/sync v0.19.0 // indirect
|
||||
golang.org/x/sys v0.41.0 // indirect
|
||||
golang.org/x/text v0.34.0 // indirect
|
||||
golang.org/x/time v0.14.0 // indirect
|
||||
google.golang.org/api v0.269.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260128011058-8636f8732409 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260217215200-42d3e9bedb6d // indirect
|
||||
google.golang.org/grpc v1.79.1 // indirect
|
||||
google.golang.org/protobuf v1.36.11 // indirect
|
||||
)
|
||||
89
scripts/go.sum
Normal file
@@ -0,0 +1,89 @@
|
||||
cloud.google.com/go v0.115.0 h1:CnFSK6Xo3lDYRoBKEcAtia6VSC837/ZkJuRduSFnr14=
|
||||
cloud.google.com/go v0.115.0/go.mod h1:8jIM5vVgoAEoiVxQ/O4BFTfHqulPZgs/ufEzMcFMdWU=
|
||||
cloud.google.com/go/ai v0.8.0 h1:rXUEz8Wp2OlrM8r1bfmpF2+VKqc1VJpafE3HgzRnD/w=
|
||||
cloud.google.com/go/ai v0.8.0/go.mod h1:t3Dfk4cM61sytiggo2UyGsDVW3RF1qGZaUKDrZFyqkE=
|
||||
cloud.google.com/go/auth v0.18.2 h1:+Nbt5Ev0xEqxlNjd6c+yYUeosQ5TtEUaNcN/3FozlaM=
|
||||
cloud.google.com/go/auth v0.18.2/go.mod h1:xD+oY7gcahcu7G2SG2DsBerfFxgPAJz17zz2joOFF3M=
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc=
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c=
|
||||
cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs=
|
||||
cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10=
|
||||
cloud.google.com/go/longrunning v0.5.7 h1:WLbHekDbjK1fVFD3ibpFFVoyizlLRl73I7YKuAKilhU=
|
||||
cloud.google.com/go/longrunning v0.5.7/go.mod h1:8GClkudohy1Fxm3owmBGid8W0pSgodEMwEAztp38Xng=
|
||||
code.gitea.io/sdk/gitea v0.23.2 h1:iJB1FDmLegwfwjX8gotBDHdPSbk/ZR8V9VmEJaVsJYg=
|
||||
code.gitea.io/sdk/gitea v0.23.2/go.mod h1:yyF5+GhljqvA30sRDreoyHILruNiy4ASufugzYg0VHM=
|
||||
github.com/42wim/httpsig v1.2.3 h1:xb0YyWhkYj57SPtfSttIobJUPJZB9as1nsfo7KWVcEs=
|
||||
github.com/42wim/httpsig v1.2.3/go.mod h1:nZq9OlYKDrUBhptd77IHx4/sZZD+IxTBADvAPI9G/EM=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/davidmz/go-pageant v1.0.2 h1:bPblRCh5jGU+Uptpz6LgMZGD5hJoOt7otgT454WvHn0=
|
||||
github.com/davidmz/go-pageant v1.0.2/go.mod h1:P2EDDnMqIwG5Rrp05dTRITj9z2zpGcD9efWSkTNKLIE=
|
||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/go-fed/httpsig v1.1.0 h1:9M+hb0jkEICD8/cAiNqEB66R87tTINszBRTjwjQzWcI=
|
||||
github.com/go-fed/httpsig v1.1.0/go.mod h1:RCMrTZvN1bJYtofsG4rd5NaO5obxQ5xBkdiS7xsT7bM=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/google/generative-ai-go v0.20.1 h1:6dEIujpgN2V0PgLhr6c/M1ynRdc7ARtiIDPFzj45uNQ=
|
||||
github.com/google/generative-ai-go v0.20.1/go.mod h1:TjOnZJmZKzarWbjUJgy+r3Ee7HGBRVLhOIgupnwR4Bg=
|
||||
github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0=
|
||||
github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.12 h1:Fg+zsqzYEs1ZnvmcztTYxhgCBsx3eEhEwQ1W/lHq/sQ=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.12/go.mod h1:vqVt9yG9480NtzREnTlmGSBmFrA+bzb0yl0TxoBQXOg=
|
||||
github.com/googleapis/gax-go/v2 v2.17.0 h1:RksgfBpxqff0EZkDWYuz9q/uWsTVz+kf43LsZ1J6SMc=
|
||||
github.com/googleapis/gax-go/v2 v2.17.0/go.mod h1:mzaqghpQp4JDh3HvADwrat+6M3MOIDp5YKHhb9PAgDY=
|
||||
github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY=
|
||||
github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 h1:q4XOmH/0opmeuJtPsbFNivyl7bCt7yRBbeEm2sC/XtQ=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0/go.mod h1:snMWehoOh2wsEwnvvwtDyFCxVeDAODenXHtn5vzrKjo=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q=
|
||||
go.opentelemetry.io/otel v1.39.0 h1:8yPrr/S0ND9QEfTfdP9V+SiwT4E0G7Y5MO7p85nis48=
|
||||
go.opentelemetry.io/otel v1.39.0/go.mod h1:kLlFTywNWrFyEdH0oj2xK0bFYZtHRYUdv1NklR/tgc8=
|
||||
go.opentelemetry.io/otel/metric v1.39.0 h1:d1UzonvEZriVfpNKEVmHXbdf909uGTOQjA0HF0Ls5Q0=
|
||||
go.opentelemetry.io/otel/metric v1.39.0/go.mod h1:jrZSWL33sD7bBxg1xjrqyDjnuzTUB0x1nBERXd7Ftcs=
|
||||
go.opentelemetry.io/otel/trace v1.39.0 h1:2d2vfpEDmCJ5zVYz7ijaJdOF59xLomrvj7bjt6/qCJI=
|
||||
go.opentelemetry.io/otel/trace v1.39.0/go.mod h1:88w4/PnZSazkGzz/w84VHpQafiU4EtqqlVdxWy+rNOA=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
||||
golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
|
||||
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60=
|
||||
golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM=
|
||||
golang.org/x/oauth2 v0.35.0 h1:Mv2mzuHuZuY2+bkyWXIHMfhNdJAdwW3FuWeCPYN5GVQ=
|
||||
golang.org/x/oauth2 v0.35.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
||||
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
|
||||
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
|
||||
golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
|
||||
golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
|
||||
golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
google.golang.org/api v0.269.0 h1:qDrTOxKUQ/P0MveH6a7vZ+DNHxJQjtGm/uvdbdGXCQg=
|
||||
google.golang.org/api v0.269.0/go.mod h1:N8Wpcu23Tlccl0zSHEkcAZQKDLdquxK+l9r2LkwAauE=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260128011058-8636f8732409 h1:merA0rdPeUV3YIIfHHcH4qBkiQAc1nfCKSI7lB4cV2M=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260128011058-8636f8732409/go.mod h1:fl8J1IvUjCilwZzQowmw2b7HQB2eAuYBabMXzWurF+I=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260217215200-42d3e9bedb6d h1:t/LOSXPJ9R0B6fnZNyALBRfZBH0Uy0gT+uR+SJ6syqQ=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260217215200-42d3e9bedb6d/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
|
||||
google.golang.org/grpc v1.79.1 h1:zGhSi45ODB9/p3VAawt9a+O/MULLl9dpizzNNpq7flY=
|
||||
google.golang.org/grpc v1.79.1/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ=
|
||||
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||
97
scripts/wordcount/main.go
Normal file
@@ -0,0 +1,97 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/sdk/gitea"
|
||||
)
|
||||
|
||||
func main() {
|
||||
token := os.Getenv("GITEA_TOKEN")
|
||||
baseURL := os.Getenv("GITEA_URL")
|
||||
repoFullName := os.Getenv("GITHUB_REPOSITORY")
|
||||
prNumberStr := os.Getenv("PR_NUMBER")
|
||||
|
||||
if token == "" || repoFullName == "" || prNumberStr == "" {
|
||||
log.Fatal("Missing required environment variables: GITEA_TOKEN, GITHUB_REPOSITORY, PR_NUMBER")
|
||||
}
|
||||
|
||||
if baseURL == "" {
|
||||
baseURL = "https://gitea.com"
|
||||
}
|
||||
|
||||
prNumber, err := strconv.ParseInt(prNumberStr, 10, 64)
|
||||
if err != nil {
|
||||
log.Fatalf("Invalid PR_NUMBER: %v", err)
|
||||
}
|
||||
|
||||
repoParts := strings.Split(repoFullName, "/")
|
||||
if len(repoParts) != 2 {
|
||||
log.Fatalf("Invalid GITHUB_REPOSITORY format: %s", repoFullName)
|
||||
}
|
||||
owner, repo := repoParts[0], repoParts[1]
|
||||
|
||||
client, err := gitea.NewClient(baseURL, gitea.SetToken(token))
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create Gitea client: %v", err)
|
||||
}
|
||||
|
||||
// Get PR files
|
||||
files, _, err := client.ListPullRequestFiles(owner, repo, prNumber, gitea.ListPullRequestFilesOptions{})
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to get PR files: %v", err)
|
||||
}
|
||||
|
||||
var counts []string
|
||||
for _, file := range files {
|
||||
if !strings.HasSuffix(file.Filename, ".md") {
|
||||
continue
|
||||
}
|
||||
|
||||
fmt.Printf("Reviewing file: %s\n", file.Filename)
|
||||
content, err := readFile(file.Filename)
|
||||
if err != nil {
|
||||
fmt.Printf("Error reading file %s: %v\n", file.Filename, err)
|
||||
continue
|
||||
}
|
||||
|
||||
count := countWords(content)
|
||||
counts = append(counts, fmt.Sprintf("#### Word count for `%s`\n\nWord count: %d", file.Filename, count))
|
||||
}
|
||||
|
||||
if len(counts) > 0 {
|
||||
commentBody := "### 🤖 Word Count Report\n\n" + strings.Join(counts, "\n\n---\n\n")
|
||||
_, _, err = client.CreateIssueComment(owner, repo, prNumber, gitea.CreateIssueCommentOption{
|
||||
Body: commentBody,
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to post PR comment: %v", err)
|
||||
}
|
||||
fmt.Println("Successfully posted review comments.")
|
||||
} else {
|
||||
fmt.Println("No Markdown files to review or no suggestions found.")
|
||||
}
|
||||
}
|
||||
|
||||
func readFile(path string) (string, error) {
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
content, err := io.ReadAll(f)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(content), nil
|
||||
}
|
||||
|
||||
func countWords(text string) int {
|
||||
return len(strings.Fields(text))
|
||||
}
|
||||
Schreibweise von ASP.NET korrigieren (Großbuchstaben).