diff --git a/.github/workflows/frontend.yml b/.github/workflows/frontend.yml index 2331e2d..32021d3 100644 --- a/.github/workflows/frontend.yml +++ b/.github/workflows/frontend.yml @@ -10,6 +10,16 @@ jobs: - name: Check out the repo uses: actions/checkout@v2 + - name: Use Cache + uses: actions/cache@v2 + with: # caches all npm packages. Updates when frontend/package-lock.json changes + path: ~/.npm # npm cache files are stored in `~/.npm` on Linux/macOS + key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('./frontend/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-build-${{ env.cache-name }}- + ${{ runner.os }}-build- + ${{ runner.os }}- + - name: sets up npm / node.js uses: actions/setup-node@v2 with: @@ -20,7 +30,7 @@ jobs: - name: Install packages working-directory: ./frontend - run: npm install # TODO cache them + run: npm install - name: Build the FrontEnd working-directory: ./frontend diff --git a/api.yaml b/api.yaml deleted file mode 100644 index fa88680..0000000 --- a/api.yaml +++ /dev/null @@ -1,93 +0,0 @@ -# Besuchen sie editor.swagger.io und pasten Sie den inhalt dieser datei rein, um die Dokumentation graphisch zu sehen. -openapi: "3.0.0" -info: - version: 1.0.0 - title: Linter REST api - -paths: - /projects: - get: - summary: list all inner-source projects - operationId: AllProjects - responses: - '200': - description: array of Projects - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/Project' - - post: - summary: force a lint of a repo - operationId: LintProject - requestBody: - description: the url of the repo you want to lint - required: true - content: - text/plain: - schema: - type: string - responses: - '200': - description: just a message saying it started the lint - content: - text/plain: - schema: - type: string - - /project/{id}: - get: - summary: get details for one repo (incl. results) - operationId: GetProject - parameters: - - $ref: '#/components/parameters/id' - responses: - '200': - description: the project detail and lint results - content: - application/json: - schema: - $ref: "#/components/schemas/Project" - '404': - description: Not Found - -components: - parameters: - id: - name: id - in: path - required: true - schema: - type: integer - description: ProjectID - - schemas: - Project: - type: object - properties: - id: - type: integer - url: - type: string - format: uri - name: - type: string - last_lint: - type: string - format: date-time - results: - type: array - items: - $ref: "#/components/schemas/Result" - - Result: - type: object - properties: - id: - type: integer - name: - type: string - result: - type: boolean diff --git a/docker-compose.yml b/docker-compose.yml index e751f84..a956080 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,13 +10,14 @@ services: - POSTGRES_PASSWORD=${DB_PASSWORD} - POSTGRES_DB=${DB_NAME} volumes: - - postgres-data + - postgres-data:/var/lib/postgresql/data expose: - 5432 backend: container_name: "amos-linter-java-server" image: "amoslinter/server:${ENVIRONMENT}" + # build: "./server" environment: - spring.datasource.platform=postgres - spring.datasource.url=jdbc:postgresql://database:5432/${DB_NAME} @@ -33,10 +34,12 @@ services: nginx: container_name: "amos-linter-nginx" image: "amoslinter/frontend:${ENVIRONMENT}" - volumes: # more like: load configurations - - ./nginx.conf:/etc/nginx/conf.d/default.conf - # environment: FIXME - # - port=${PORT} + # build: "./frontend" + volumes: # more like: load nginx configuration + - ./nginx.conf:/etc/nginx/templates/default.conf.template + environment: + - PORT=${PORT} + - HOST=${HOST} depends_on: - backend ports: # only connection to outside world diff --git a/frontend/Dockerfile b/frontend/Dockerfile index e8ce871..5d642bc 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -1,7 +1,3 @@ -# TODO make this an multistage build. -# Step 1: ng build basically -# Step 2: nginx - FROM nginx:stable COPY ./dist/frontend/ /usr/share/nginx/html/ diff --git a/frontend/README.md b/frontend/README.md index 51891a8..6d24019 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -20,6 +20,6 @@ Flag `--prod` setzen für production build. Erst bauen (siehe oben) dann folgendes Ausführen: `docker build -t amoslinter/frontend: .` (tag z.B staging oder release) -## Development server - -Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. +## Local Dev-Server +`ng serve` für einen Lokalen Server zum Testen. +Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. diff --git a/frontend/src/app/app.component.ts b/frontend/src/app/app.component.ts index 52d6019..b10cb6b 100644 --- a/frontend/src/app/app.component.ts +++ b/frontend/src/app/app.component.ts @@ -22,24 +22,25 @@ export class AppComponent implements OnInit { chipsControl = new FormControl(''); chipsValue$ = this.chipsControl.valueChanges; //SearchBarValue = ''; - kategorie = new FormControl(""); + kategorie = new FormControl(''); all_projects: Project[]; options: FormGroup; forwardLinkWorked = true; errorMsgForwardLink = ''; hideRequiredControl = new FormControl(false); floatLabelControl = new FormControl('auto'); - + chipOptions: string[]; gridInfo: GridInfo[] = new Array(); dataArray: GridInfo[] = new Array(); - displayColumns: string[] = - ['project', - 'testsPassed', - 'testsPassedPerActivChip', - 'newTestsPassedSinceLastMonth']; + displayColumns: string[] = [ + 'project', + 'testsPassed', + 'testsPassedPerActivChip', + 'newTestsPassedSinceLastMonth', + ]; columnsToDisplay: string[] = this.displayColumns.slice(); data = new MatTableDataSource(this.dataArray); @@ -169,13 +170,15 @@ export class AppComponent implements OnInit { //für jedes projekt for (var i = 0; i < this.all_projects.length; i++) { //lade ergebnisse der checks aus dem backend + await this.http .get(`${environment.baseURL}/project/${this.all_projects[i].id}/lastMonth`).toPromise() .then((val: any) => { + var checkResults: CheckResults[] = val.lintingResults[val.lintingResults.length - 1].checkResults; - var checkResultsLastMonth : CheckResults[] = - val.lintingResults[0].checkResults; + var checkResultsLastMonth: CheckResults[] = + val.lintingResults[0].checkResults; //Zähler für erfolgreiche Checks var checksPassed = 0; //Zähler für erfolgreiche Checks pro Tag @@ -187,15 +190,18 @@ export class AppComponent implements OnInit { if (checkResults[j].result) { checksPassed = checksPassed + 1; - for(var k = 0; k < this.chipsControl.value.length ; k++){ + for (var k = 0; k < this.chipsControl.value.length; k++) { //console.log('chipControl', this.chipsControl.value[k]); //console.log('tag in backend', checkResults[j].tag); - if(this.chipsControl.value[k].toLowerCase().trim() == checkResults[j].tag.toLowerCase().trim()){ + if ( + this.chipsControl.value[k].toLowerCase().trim() == + checkResults[j].tag.toLowerCase().trim() + ) { checksPassedPerActivChip = checksPassedPerActivChip + 1; } } } - if(checkResultsLastMonth[j].result){ + if (checkResultsLastMonth[j].result) { checksPassedLastMonth = checksPassedLastMonth + 1; } } @@ -205,7 +211,7 @@ export class AppComponent implements OnInit { project: val.name, testsPassed: checksPassed, testsPassedPerActivChip: checksPassedPerActivChip, - newTestsPassedSinceLastMonth: checksPassed - checksPassedLastMonth + newTestsPassedSinceLastMonth: checksPassed - checksPassedLastMonth, }; @@ -214,18 +220,18 @@ export class AppComponent implements OnInit { } //wähle die sortier funktion nach eingabe - switch(this.kategorie.value){ - case "bestandene_tests" : { + switch (this.kategorie.value) { + case 'bestandene_tests': { //this.gridInfo = this.bubbleSort(this.gridInfo, this.compareTestsPassed); this.gridInfo.sort(this.compareTestsPassed); break; } - case "bestandene_tests_letzter_monat": { + case 'bestandene_tests_letzter_monat': { //this.gridInfo = this.bubbleSort(this.gridInfo, this.compareNewTestsPassedSinceLastMonth); this.gridInfo.sort(this.compareNewTestsPassedSinceLastMonth); break; } - case "bestandene_tests_pro_kategorie" : { + case 'bestandene_tests_pro_kategorie': { //this.gridInfo = this.bubbleSort(this.gridInfo, this.compareTestsPassedPerTag); this.gridInfo.sort(this.compareTestsPassedPerActivChip); break; @@ -267,37 +273,35 @@ export class AppComponent implements OnInit { */ compareTestsPassed(a, b) { - if(a.testsPassed < b.testsPassed){ + if (a.testsPassed < b.testsPassed) { return 1; } - if(a.testsPassed > b.testsPassed){ + if (a.testsPassed > b.testsPassed) { return -1; } return 0; } compareNewTestsPassedSinceLastMonth(a, b) { - if(a.newTestsPassedSinceLastMonth < b.newTestsPassedSinceLastMonth){ + if (a.newTestsPassedSinceLastMonth < b.newTestsPassedSinceLastMonth) { return 1; } - if(a.newTestsPassedSinceLastMonth > b.newTestsPassedSinceLastMonth){ + if (a.newTestsPassedSinceLastMonth > b.newTestsPassedSinceLastMonth) { return -1; } return 0; } compareTestsPassedPerActivChip(a, b) { - if(a.testsPassedPerActivChip < b.testsPassedPerActivChip){ + if (a.testsPassedPerActivChip < b.testsPassedPerActivChip) { return 1; } - if(a.testsPassedPerActivChip > b.testsPassedPerActivChip){ + if (a.testsPassedPerActivChip > b.testsPassedPerActivChip) { return -1; } return 0; } - - /* compareTestsPassedPerTag(a, b, setTags) { var result; diff --git a/frontend/src/app/favicon.ico b/frontend/src/app/favicon.ico new file mode 100644 index 0000000..0c5b405 Binary files /dev/null and b/frontend/src/app/favicon.ico differ diff --git a/frontend/src/app/repository-details/repository-details.component.ts b/frontend/src/app/repository-details/repository-details.component.ts index a75358c..09ebde2 100644 --- a/frontend/src/app/repository-details/repository-details.component.ts +++ b/frontend/src/app/repository-details/repository-details.component.ts @@ -1,9 +1,6 @@ import { HttpClient } from '@angular/common/http'; import { Component, OnInit, Inject } from '@angular/core'; -import { - MatDialogRef, - MAT_DIALOG_DATA, -} from '@angular/material/dialog'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; import { Chart } from '../../../node_modules/chart.js'; import * as dayjs from 'dayjs'; import { environment } from 'src/environments/environment'; @@ -22,7 +19,6 @@ export class RepositoryDetailsComponent implements OnInit { // (1 mal onNGinit für die Erstellung der Tiles (geht nicht später), und 1 mal onngAfterView für die Graphen (Canvas ist davor undefined)) // TODO: chartNames nicht dynamisch erstellen - emojiMap = { /*unwichtig:"〰️", warning: "⚠️", @@ -81,11 +77,19 @@ export class RepositoryDetailsComponent implements OnInit { var tags = this.getTagsArray( val.lintingResults[val.lintingResults.length - 1].checkResults ); - this.numberOfTestsPerSeverityInTags = this.groupLintingResultsInTagsAndFillNumTestsPerSeverity(tags, val.lintingResults[val.lintingResults.length - 1].checkResults)[0]; + this.numberOfTestsPerSeverityInTags = + this.groupLintingResultsInTagsAndFillNumTestsPerSeverity( + tags, + val.lintingResults[val.lintingResults.length - 1].checkResults + )[0]; var chartNames = this.getChartNames(tags); //console.log('in after', this.numberOfTestsPerSeverityInTags); for (var i = 0; i < this.tags.length + 1; i++) { - this.renderChart(chartNames[i], i, this.numberOfTestsPerSeverityInTags); + this.renderChart( + chartNames[i], + i, + this.numberOfTestsPerSeverityInTags + ); this.myChart.update(); } }); @@ -152,7 +156,11 @@ export class RepositoryDetailsComponent implements OnInit { //this.fillSeverityArrays(); // muss momentan nicht benützt werden this.tags = this.getTagsArray(this.latestLintingResults); - this.LintingResultsInTags = this.groupLintingResultsInTagsAndFillNumTestsPerSeverity(this.tags, this.latestLintingResults)[1]; + this.LintingResultsInTags = + this.groupLintingResultsInTagsAndFillNumTestsPerSeverity( + this.tags, + this.latestLintingResults + )[1]; //console.log('LintingResultInTags', this.LintingResultsInTags); // Speichere Informationen @@ -165,7 +173,9 @@ export class RepositoryDetailsComponent implements OnInit { this.chartNames = this.getChartNames(this.tags); this.addTilesForCategoryGraphAndTipps(); // sortiere die Checks um die 3 besten Tipps darzustellen - this.latestLintingResults.forEach(val => this.latestLintingResultsSortedPriority.push(Object.assign({}, val))); + this.latestLintingResults.forEach((val) => + this.latestLintingResultsSortedPriority.push(Object.assign({}, val)) + ); this.latestLintingResultsSortedPriority.sort(this.compareCheckResults); }); } @@ -193,14 +203,16 @@ export class RepositoryDetailsComponent implements OnInit { return tags; } - getChartNames(tags){ - if (!tags){ - console.log("Error in getChartNames() in repository-details.components.ts\n this.tags is empty") + getChartNames(tags) { + if (!tags) { + console.log( + 'Error in getChartNames() in repository-details.components.ts\n this.tags is empty' + ); return []; } - var chartNames :String[] = []; - chartNames.push("Alle Tests:") - for(var i = 0; i < tags.length; i++){ + var chartNames: String[] = []; + chartNames.push('Alle Tests:'); + for (var i = 0; i < tags.length; i++) { chartNames.push(tags[i]); } return chartNames; @@ -282,7 +294,12 @@ export class RepositoryDetailsComponent implements OnInit { var t = { color: 'white', cols: 2, rows: 2, text: this.tags[i] }; this.tiles.push(t); } - this.tiles.push({ color: 'white', cols: this.maxColsForTiles, rows: 1, text: "Top 3 Tipps" }); + this.tiles.push({ + color: 'white', + cols: this.maxColsForTiles, + rows: 1, + text: 'Top 3 Tipps', + }); } returnEmojiBasedOnSeverity(input) { @@ -294,18 +311,17 @@ export class RepositoryDetailsComponent implements OnInit { else return this.emojiMap.bug; } - compareCheckResults( a, b ) { - if ( a.priority < b.priority ){ + compareCheckResults(a, b) { + if (a.priority < b.priority) { return -1; } - if ( a.priority > b.priority ){ + if (a.priority > b.priority) { return 1; } return 0; } } - // Um das Projekt zu bekommen export interface DialogData { projectID: number; @@ -333,7 +349,8 @@ export interface Tile { } // Zum Speichern der Daten eines LintingResult -interface LintingResult { // wird gerade nicht benutzt +interface LintingResult { + // wird gerade nicht benutzt projectId: number; id: number; lintTime: string; diff --git a/frontend/src/environments/environment.prod.ts b/frontend/src/environments/environment.prod.ts index fcd9dc6..edd3012 100644 --- a/frontend/src/environments/environment.prod.ts +++ b/frontend/src/environments/environment.prod.ts @@ -1,4 +1,4 @@ export const environment = { production: true, - baseURL: 'http://localhost:6969/api', // TODO make the port configurable. Take the env variable from docker-compose + baseURL: 'http://localhost:6969/api', // TODO make the port configurable. Take the env variable from docker-compose // TODO make host configurable }; diff --git a/nginx.conf b/nginx.conf index fd606fa..aab1d02 100644 --- a/nginx.conf +++ b/nginx.conf @@ -1,11 +1,11 @@ server { listen 80; #ipv4 listen [::]:80; #ipv6 - server_name localhost; - + server_name ${HOST}; + # rewrite url if it doesent access via the actual domain name - if ($http_host !~ "^localhost") { - rewrite ^(.*)$ $scheme://localhost/$1 redirect; + if ($http_host !~ "^${HOST}") { + rewrite ^(.*)$ $scheme://${HOST}/$1 redirect; } # size limits @@ -30,7 +30,7 @@ server { # locations location /api { - proxy_pass http://backend:8080/; + proxy_pass http://backend:8080/; # backend kommt von namen des docker-compose-services } location / { diff --git a/server/src/main/java/amosproj/server/api/ProjectController.java b/server/src/main/java/amosproj/server/api/ProjectController.java index 5d174ea..7caf01b 100644 --- a/server/src/main/java/amosproj/server/api/ProjectController.java +++ b/server/src/main/java/amosproj/server/api/ProjectController.java @@ -83,12 +83,12 @@ String lintProject(@RequestBody String url) { } } - @GetMapping("/lintAll") - public void lint() { + @PostMapping("/crawler") + public void crawl() { crawler.runCrawler(); } - @GetMapping("/crawler/status") + @GetMapping("/crawler") public CrawlerStatusSchema statusCrawler() { return crawler.crawlerStatus(); } diff --git a/server/src/test/java/amosproj/server/linter/LinterTest.java b/server/src/test/java/amosproj/server/linter/LinterTest.java index 169de85..ab9d688 100644 --- a/server/src/test/java/amosproj/server/linter/LinterTest.java +++ b/server/src/test/java/amosproj/server/linter/LinterTest.java @@ -24,8 +24,7 @@ public void testRunLint() throws GitLabApiException { @Test public void testRunCrawler() throws Exception { - // TODO???? - // better not do this yet, takes 20 minutes + // FIXME better not do this yet, takes 20 minutes } } diff --git a/server/src/test/java/amosproj/server/linter/checks/CheckGitlabSettingsTest.java b/server/src/test/java/amosproj/server/linter/checks/CheckGitlabSettingsTest.java index 541e573..becdb62 100644 --- a/server/src/test/java/amosproj/server/linter/checks/CheckGitlabSettingsTest.java +++ b/server/src/test/java/amosproj/server/linter/checks/CheckGitlabSettingsTest.java @@ -199,7 +199,7 @@ public void hasDescription_negative() { } } - @Test + /*@Test public void hasSquashingEnabled_positive(){ try { prepareSettingsCheck("https://gitlab.cs.fau.de/or16iqyd/noReadme"); @@ -217,5 +217,6 @@ public void hasSquashingEnabled_negative(){ } catch (GitLabApiException e) { fail(); } - } + }*/ + }