1
0
mirror of https://github.com/immich-app/immich.git synced 2024-12-25 10:43:13 +02:00

Add all server checks to CI - fix lint issues

CI will now run linter, type-checks and tests for the server.

All the lint issues have been fixed.
This commit is contained in:
Jaime Baez 2022-09-08 11:07:27 +02:00
parent 836b174d33
commit 1f4ba73da7
19 changed files with 47 additions and 70 deletions

View File

@ -18,8 +18,8 @@ jobs:
- name: Run Immich Server 2E2 Test - name: Run Immich Server 2E2 Test
run: docker-compose -f ./docker/docker-compose.test.yml --env-file ./docker/.env.test up --abort-on-container-exit --exit-code-from immich-server-test run: docker-compose -f ./docker/docker-compose.test.yml --env-file ./docker/.env.test up --abort-on-container-exit --exit-code-from immich-server-test
unit-tests: server-unit-tests:
name: Run unit test suites name: Run server unit test suites and checks
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
@ -27,4 +27,4 @@ jobs:
uses: actions/checkout@v3 uses: actions/checkout@v3
- name: Run tests - name: Run tests
run: cd server && npm install && npm run test run: cd server && npm ci && npm run check:all

View File

@ -11,7 +11,6 @@ import { GetAlbumsDto } from './dto/get-albums.dto';
import { RemoveAssetsDto } from './dto/remove-assets.dto'; import { RemoveAssetsDto } from './dto/remove-assets.dto';
import { UpdateAlbumDto } from './dto/update-album.dto'; import { UpdateAlbumDto } from './dto/update-album.dto';
import { AlbumCountResponseDto } from './response-dto/album-count-response.dto'; import { AlbumCountResponseDto } from './response-dto/album-count-response.dto';
import { AlbumResponseDto } from './response-dto/album-response.dto';
export interface IAlbumRepository { export interface IAlbumRepository {
create(ownerId: string, createAlbumDto: CreateAlbumDto): Promise<AlbumEntity>; create(ownerId: string, createAlbumDto: CreateAlbumDto): Promise<AlbumEntity>;
@ -165,7 +164,7 @@ export class AlbumRepository implements IAlbumRepository {
} }
async getListByAssetId(userId: string, assetId: string): Promise<AlbumEntity[]> { async getListByAssetId(userId: string, assetId: string): Promise<AlbumEntity[]> {
let query = this.albumRepository.createQueryBuilder('album'); const query = this.albumRepository.createQueryBuilder('album');
const albums = await query const albums = await query
.where('album.ownerId = :ownerId', { ownerId: userId }) .where('album.ownerId = :ownerId', { ownerId: userId })
@ -190,7 +189,7 @@ export class AlbumRepository implements IAlbumRepository {
} }
async get(albumId: string): Promise<AlbumEntity | undefined> { async get(albumId: string): Promise<AlbumEntity | undefined> {
let query = this.albumRepository.createQueryBuilder('album'); const query = this.albumRepository.createQueryBuilder('album');
const album = await query const album = await query
.where('album.id = :albumId', { albumId }) .where('album.id = :albumId', { albumId })

View File

@ -11,7 +11,6 @@ import {
ParseUUIDPipe, ParseUUIDPipe,
Put, Put,
Query, Query,
Header,
} from '@nestjs/common'; } from '@nestjs/common';
import { ParseMeUUIDPipe } from '../validation/parse-me-uuid-pipe'; import { ParseMeUUIDPipe } from '../validation/parse-me-uuid-pipe';
import { AlbumService } from './album.service'; import { AlbumService } from './album.service';

View File

@ -4,7 +4,6 @@ import { AuthUserDto } from '../../decorators/auth-user.decorator';
import { BadRequestException, NotFoundException, ForbiddenException } from '@nestjs/common'; import { BadRequestException, NotFoundException, ForbiddenException } from '@nestjs/common';
import { AlbumEntity } from '@app/database/entities/album.entity'; import { AlbumEntity } from '@app/database/entities/album.entity';
import { AlbumResponseDto } from './response-dto/album-response.dto'; import { AlbumResponseDto } from './response-dto/album-response.dto';
import { AssetAlbumEntity } from '@app/database/entities/asset-album.entity';
describe('Album service', () => { describe('Album service', () => {
let sut: AlbumService; let sut: AlbumService;

View File

@ -1,4 +1,4 @@
import { IsNotEmpty, IsOptional } from 'class-validator'; import { IsOptional } from 'class-validator';
export class UpdateAlbumDto { export class UpdateAlbumDto {
@IsOptional() @IsOptional()

View File

@ -15,7 +15,6 @@ import {
HttpCode, HttpCode,
BadRequestException, BadRequestException,
UploadedFile, UploadedFile,
Header,
} from '@nestjs/common'; } from '@nestjs/common';
import { JwtAuthGuard } from '../../modules/immich-jwt/guards/jwt-auth.guard'; import { JwtAuthGuard } from '../../modules/immich-jwt/guards/jwt-auth.guard';
import { AssetService } from './asset.service'; import { AssetService } from './asset.service';
@ -34,7 +33,7 @@ import { IAssetUploadedJob } from '@app/job/index';
import { assetUploadedQueueName } from '@app/job/constants/queue-name.constant'; import { assetUploadedQueueName } from '@app/job/constants/queue-name.constant';
import { assetUploadedProcessorName } from '@app/job/constants/job-name.constant'; import { assetUploadedProcessorName } from '@app/job/constants/job-name.constant';
import { CheckDuplicateAssetDto } from './dto/check-duplicate-asset.dto'; import { CheckDuplicateAssetDto } from './dto/check-duplicate-asset.dto';
import { ApiBearerAuth, ApiBody, ApiConsumes, ApiResponse, ApiTags } from '@nestjs/swagger'; import { ApiBearerAuth, ApiBody, ApiConsumes, ApiTags } from '@nestjs/swagger';
import { CuratedObjectsResponseDto } from './response-dto/curated-objects-response.dto'; import { CuratedObjectsResponseDto } from './response-dto/curated-objects-response.dto';
import { CuratedLocationsResponseDto } from './response-dto/curated-locations-response.dto'; import { CuratedLocationsResponseDto } from './response-dto/curated-locations-response.dto';
import { AssetResponseDto } from './response-dto/asset-response.dto'; import { AssetResponseDto } from './response-dto/asset-response.dto';

View File

@ -1,9 +1,8 @@
import { AssetRepository, IAssetRepository } from './asset-repository'; import { IAssetRepository } from './asset-repository';
import { AuthUserDto } from '../../decorators/auth-user.decorator'; import { AuthUserDto } from '../../decorators/auth-user.decorator';
import { AssetService } from './asset.service'; import { AssetService } from './asset.service';
import { Repository } from 'typeorm'; import { Repository } from 'typeorm';
import { AssetEntity, AssetType } from '@app/database/entities/asset.entity'; import { AssetEntity } from '@app/database/entities/asset.entity';
import { CreateAssetDto } from './dto/create-asset.dto';
describe('AssetService', () => { describe('AssetService', () => {
let sui: AssetService; let sui: AssetService;
@ -15,39 +14,39 @@ describe('AssetService', () => {
email: 'auth@test.com', email: 'auth@test.com',
}); });
const _getCreateAssetDto = (): CreateAssetDto => { // const _getCreateAssetDto = (): CreateAssetDto => {
const createAssetDto = new CreateAssetDto(); // const createAssetDto = new CreateAssetDto();
createAssetDto.deviceAssetId = 'deviceAssetId'; // createAssetDto.deviceAssetId = 'deviceAssetId';
createAssetDto.deviceId = 'deviceId'; // createAssetDto.deviceId = 'deviceId';
createAssetDto.assetType = AssetType.OTHER; // createAssetDto.assetType = AssetType.OTHER;
createAssetDto.createdAt = '2022-06-19T23:41:36.910Z'; // createAssetDto.createdAt = '2022-06-19T23:41:36.910Z';
createAssetDto.modifiedAt = '2022-06-19T23:41:36.910Z'; // createAssetDto.modifiedAt = '2022-06-19T23:41:36.910Z';
createAssetDto.isFavorite = false; // createAssetDto.isFavorite = false;
createAssetDto.duration = '0:00:00.000000'; // createAssetDto.duration = '0:00:00.000000';
return createAssetDto; // return createAssetDto;
}; // };
const _getAsset = () => { // const _getAsset = () => {
const assetEntity = new AssetEntity(); // const assetEntity = new AssetEntity();
assetEntity.id = 'e8edabfd-7d8a-45d0-9d61-7c7ca60f2c67'; // assetEntity.id = 'e8edabfd-7d8a-45d0-9d61-7c7ca60f2c67';
assetEntity.userId = '3ea54709-e168-42b7-90b0-a0dfe8a7ecbd'; // assetEntity.userId = '3ea54709-e168-42b7-90b0-a0dfe8a7ecbd';
assetEntity.deviceAssetId = '4967046344801'; // assetEntity.deviceAssetId = '4967046344801';
assetEntity.deviceId = '116766fd-2ef2-52dc-a3ef-149988997291'; // assetEntity.deviceId = '116766fd-2ef2-52dc-a3ef-149988997291';
assetEntity.type = AssetType.VIDEO; // assetEntity.type = AssetType.VIDEO;
assetEntity.originalPath = // assetEntity.originalPath =
'upload/3ea54709-e168-42b7-90b0-a0dfe8a7ecbd/original/116766fd-2ef2-52dc-a3ef-149988997291/51c97f95-244f-462d-bdf0-e1dc19913516.jpg'; // 'upload/3ea54709-e168-42b7-90b0-a0dfe8a7ecbd/original/116766fd-2ef2-52dc-a3ef-149988997291/51c97f95-244f-462d-bdf0-e1dc19913516.jpg';
assetEntity.resizePath = ''; // assetEntity.resizePath = '';
assetEntity.createdAt = '2022-06-19T23:41:36.910Z'; // assetEntity.createdAt = '2022-06-19T23:41:36.910Z';
assetEntity.modifiedAt = '2022-06-19T23:41:36.910Z'; // assetEntity.modifiedAt = '2022-06-19T23:41:36.910Z';
assetEntity.isFavorite = false; // assetEntity.isFavorite = false;
assetEntity.mimeType = 'image/jpeg'; // assetEntity.mimeType = 'image/jpeg';
assetEntity.webpPath = ''; // assetEntity.webpPath = '';
assetEntity.encodedVideoPath = ''; // assetEntity.encodedVideoPath = '';
assetEntity.duration = '0:00:00.000000'; // assetEntity.duration = '0:00:00.000000';
return assetEntity; // return assetEntity;
}; // };
beforeAll(() => { beforeAll(() => {
assetRepositoryMock = { assetRepositoryMock = {

View File

@ -1,6 +1,5 @@
import { ApiProperty } from '@nestjs/swagger'; import { ApiProperty } from '@nestjs/swagger';
import { Transform } from 'class-transformer'; import { IsOptional } from 'class-validator';
import { IsBoolean, IsNotEmpty, IsOptional, IsString, IsUUID } from 'class-validator';
export enum GetAssetThumbnailFormatEnum { export enum GetAssetThumbnailFormatEnum {
JPEG = 'JPEG', JPEG = 'JPEG',

View File

@ -1,6 +1,6 @@
import { ApiProperty } from '@nestjs/swagger'; import { ApiProperty } from '@nestjs/swagger';
import { Transform, Type } from 'class-transformer'; import { Transform } from 'class-transformer';
import { IsBoolean, IsBooleanString, IsNotEmpty, IsOptional } from 'class-validator'; import { IsBoolean, IsNotEmpty, IsOptional } from 'class-validator';
export class ServeFileDto { export class ServeFileDto {
@IsNotEmpty() @IsNotEmpty()

View File

@ -1,12 +1,5 @@
import { Body, Controller, Post, Res, UseGuards, ValidationPipe } from '@nestjs/common'; import { Body, Controller, Post, Res, UseGuards, ValidationPipe } from '@nestjs/common';
import { import { ApiBadRequestResponse, ApiBearerAuth, ApiTags } from '@nestjs/swagger';
ApiBadRequestResponse,
ApiBearerAuth,
ApiBody,
ApiCreatedResponse,
ApiResponse,
ApiTags,
} from '@nestjs/swagger';
import { AuthUserDto, GetAuthUser } from '../../decorators/auth-user.decorator'; import { AuthUserDto, GetAuthUser } from '../../decorators/auth-user.decorator';
import { JwtAuthGuard } from '../../modules/immich-jwt/guards/jwt-auth.guard'; import { JwtAuthGuard } from '../../modules/immich-jwt/guards/jwt-auth.guard';
import { AuthService } from './auth.service'; import { AuthService } from './auth.service';

View File

@ -1,5 +1,5 @@
import { UserEntity } from '@app/database/entities/user.entity'; import { UserEntity } from '@app/database/entities/user.entity';
import { ApiProperty, ApiResponseProperty } from '@nestjs/swagger'; import { ApiResponseProperty } from '@nestjs/swagger';
export class LoginResponseDto { export class LoginResponseDto {
@ApiResponseProperty() @ApiResponseProperty()

View File

@ -1,8 +1,6 @@
import { DeviceType } from '@app/database/entities/device-info.entity'; import { DeviceType } from '@app/database/entities/device-info.entity';
import { PartialType } from '@nestjs/mapped-types';
import { ApiProperty } from '@nestjs/swagger'; import { ApiProperty } from '@nestjs/swagger';
import { IsNotEmpty, IsOptional } from 'class-validator'; import { IsNotEmpty, IsOptional } from 'class-validator';
import { CreateDeviceInfoDto } from './create-device-info.dto';
export class UpdateDeviceInfoDto { export class UpdateDeviceInfoDto {
@IsNotEmpty() @IsNotEmpty()

View File

@ -1,13 +1,10 @@
import { Controller, Get, UseGuards } from '@nestjs/common'; import { Controller, Get } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { JwtAuthGuard } from '../../modules/immich-jwt/guards/jwt-auth.guard';
import { ServerInfoService } from './server-info.service'; import { ServerInfoService } from './server-info.service';
import { serverVersion } from '../../constants/server_version.constant'; import { serverVersion } from '../../constants/server_version.constant';
import { ApiTags } from '@nestjs/swagger'; import { ApiTags } from '@nestjs/swagger';
import { ServerPingResponse } from './response-dto/server-ping-response.dto'; import { ServerPingResponse } from './response-dto/server-ping-response.dto';
import { ServerVersionReponseDto } from './response-dto/server-version-response.dto'; import { ServerVersionReponseDto } from './response-dto/server-version-response.dto';
import { ServerInfoResponseDto } from './response-dto/server-info-response.dto'; import { ServerInfoResponseDto } from './response-dto/server-info-response.dto';
import { DataSource } from 'typeorm';
@ApiTags('Server Info') @ApiTags('Server Info')
@Controller('server-info') @Controller('server-info')

View File

@ -12,7 +12,6 @@ import {
UploadedFile, UploadedFile,
Response, Response,
Request, Request,
StreamableFile,
ParseBoolPipe, ParseBoolPipe,
} from '@nestjs/common'; } from '@nestjs/common';
import { UserService } from './user.service'; import { UserService } from './user.service';

View File

@ -15,7 +15,6 @@ import { AppController } from './app.controller';
import { ScheduleModule } from '@nestjs/schedule'; import { ScheduleModule } from '@nestjs/schedule';
import { ScheduleTasksModule } from './modules/schedule-tasks/schedule-tasks.module'; import { ScheduleTasksModule } from './modules/schedule-tasks/schedule-tasks.module';
import { DatabaseModule } from '@app/database'; import { DatabaseModule } from '@app/database';
import { AppLoggerMiddleware } from './middlewares/app-logger.middleware';
@Module({ @Module({
imports: [ imports: [

View File

@ -1,4 +1,3 @@
import { dataSource } from '@app/database/config/database.config';
import { Logger } from '@nestjs/common'; import { Logger } from '@nestjs/common';
import { NestFactory } from '@nestjs/core'; import { NestFactory } from '@nestjs/core';
import { NestExpressApplication } from '@nestjs/platform-express'; import { NestExpressApplication } from '@nestjs/platform-express';

View File

@ -2,7 +2,6 @@ import { InjectQueue } from '@nestjs/bull/dist/decorators';
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { Queue } from 'bull'; import { Queue } from 'bull';
import { randomUUID } from 'node:crypto'; import { randomUUID } from 'node:crypto';
import { AssetEntity } from '@app/database/entities/asset.entity';
import { AssetResponseDto } from '../../api-v1/asset/response-dto/asset-response.dto'; import { AssetResponseDto } from '../../api-v1/asset/response-dto/asset-response.dto';
@Injectable() @Injectable()

View File

@ -18,7 +18,7 @@ export class GenerateChecksumProcessor {
@Process() @Process()
async generateChecksum() { async generateChecksum() {
let hasNext = true; let hasNext = true;
let pageSize = 200; const pageSize = 200;
while (hasNext) { while (hasNext) {
const assets = await this.assetRepository.find({ const assets = await this.assetRepository.find({

View File

@ -21,7 +21,6 @@ import axios from 'axios';
import { Job } from 'bull'; import { Job } from 'bull';
import exifr from 'exifr'; import exifr from 'exifr';
import ffmpeg from 'fluent-ffmpeg'; import ffmpeg from 'fluent-ffmpeg';
import { readFile } from 'fs/promises';
import path from 'path'; import path from 'path';
import sharp from 'sharp'; import sharp from 'sharp';
import { Repository } from 'typeorm/repository/Repository'; import { Repository } from 'typeorm/repository/Repository';
@ -330,7 +329,7 @@ export class MetadataExtractionProcessor {
} }
if (stream.r_frame_rate) { if (stream.r_frame_rate) {
let fpsParts = stream.r_frame_rate.split('/'); const fpsParts = stream.r_frame_rate.split('/');
if (fpsParts.length === 2) { if (fpsParts.length === 2) {
newExif.fps = Math.round(parseInt(fpsParts[0]) / parseInt(fpsParts[1])); newExif.fps = Math.round(parseInt(fpsParts[0]) / parseInt(fpsParts[1]));