Skip to content

Commit

Permalink
Add GitHub actions to deploy infra
Browse files Browse the repository at this point in the history
Added a main.bicep file and migrated the other files to Bicep modules.

Also added GitHub Workflow actions to deploy the infra.
  • Loading branch information
DigiBanks99 committed May 23, 2023
1 parent 7f87631 commit 5e57194
Show file tree
Hide file tree
Showing 26 changed files with 1,146 additions and 564 deletions.
12 changes: 12 additions & 0 deletions .fleet/run.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"configurations": [
{
"type": "dotnet",
"name": "run",
"projectPath": "",
"exePath": "",
"args": [],
},

]
}
2 changes: 1 addition & 1 deletion .github/workflows/end-to-end.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:

strategy:
matrix:
node-version: [16.x]
node-version: [18.x]
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/

steps:
Expand Down
5 changes: 5 additions & 0 deletions src/livestock-tracker.abstractions/Animals/KraalStats.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,9 @@ public sealed class KraalStats
/// <remarks>Ranges from 0 to 1.</remarks>
/// </summary>
public decimal DeathRate { get; init; }

/// <summary>
/// The default instance of <see cref="KraalStats" />.
/// </summary>
public static KraalStats Null { get; } = new(0, 0, 0, 0, 0);
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@ public interface IFeedTypeSearchService
/// </summary>
/// <param name="filter">Provides the filtering logic.</param>
/// <param name="pagingOptions">Provides the parameters for returning the correct subset of data.</param>
/// <param name="cancellationToken">A token that can be used to cancel the fetch task.</param>
/// <returns>The subset of feed types that matches filter according to the pagination information.</returns>
IPagedData<FeedType> Search(IQueryableFilter<FeedType> filter, IPagingOptions pagingOptions);
Task<IPagedData<FeedType>> SearchAsync(IQueryableFilter<FeedType> filter,
IPagingOptions pagingOptions,
CancellationToken cancellationToken);

/// <summary>
/// Returns the detail of a feed type that matches the given unique identifier.
Expand Down
6 changes: 5 additions & 1 deletion src/livestock-tracker.logic/Animals/KraalReportHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ public async ValueTask<KraalStats> HandleAsync(CancellationToken cancellationTok
{
_logger.LogInformation("Fetching kraal stats...");

return await _livestockContext.KraalStats.FirstAsync(cancellationToken).ConfigureAwait(false);
return await _livestockContext.KraalStats
.AsNoTracking()
.FirstOrDefaultAsync(cancellationToken)
.ConfigureAwait(false)
?? KraalStats.Null;
}
}
7 changes: 5 additions & 2 deletions src/livestock-tracker.logic/Animals/Services/AnimalManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,14 @@ public void UnarchiveAnimals(int[] animalIds)
}

/// <inheritdoc />
public Task<Animal?> GetOneAsync(long id, CancellationToken cancellationToken)
public async Task<Animal?> GetOneAsync(long id, CancellationToken cancellationToken)
{
_logger.LogInformation("Retrieving the information of animal with ID {AnimalId}", id);

return _dbContext.Animals.AsNoTracking().FirstOrDefaultAsync(animal => animal.Id == id, cancellationToken);
return await _dbContext.Animals
.AsNoTracking()
.FirstOrDefaultAsync(animal => animal.Id == id, cancellationToken)
.ConfigureAwait(false);
}

/// <inheritdoc />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,18 @@ public FeedTypeSearchService(ILogger<FeedTypeSearchService> logger, LivestockCon
}

/// <inheritdoc />
public IPagedData<FeedType> Search(IQueryableFilter<FeedType> filter, IPagingOptions pagingOptions)
public async Task<IPagedData<FeedType>> SearchAsync(IQueryableFilter<FeedType> filter,
IPagingOptions pagingOptions,
CancellationToken cancellationToken)
{
_logger.LogInformation("Searching for feed types using filter {@Filter}...", filter);

return _dbContext.FeedTypes.AsNoTracking()
return await _dbContext.FeedTypes
.AsNoTracking()
.OrderBy(type => type.Description)
.FilterOnObject(filter)
.Paginate(pagingOptions);
.PaginateAsync(pagingOptions, cancellationToken)
.ConfigureAwait(false);
}

/// <inheritdoc />
Expand Down
12 changes: 12 additions & 0 deletions src/livestock-tracker/.config/dotnet-tools.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"version": 1,
"isRoot": true,
"tools": {
"dotnet-ef": {
"version": "6.0.9",
"commands": [
"dotnet-ef"
]
}
}
}
5 changes: 2 additions & 3 deletions src/livestock-tracker/ClientApp/.vscode/extensions.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
"dbaeumer.vscode-eslint",
"streetsidesoftware.code-spell-checker",
"christian-kohler.path-intellisense",
"mike-co.import-sorter",
"eg2.vscode-npm-script"
"mike-co.import-sorter"
]
}
}
2 changes: 2 additions & 0 deletions src/livestock-tracker/ClientApp/src/app/app.component.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Component } from '@angular/core';
import { AnimalStore } from '@animal/store';
import { AppState } from '@core/store';
import { Store } from '@ngrx/store';
import { FetchUnitsAction } from '@unit/store/unit.actions';
Expand All @@ -11,5 +12,6 @@ import { FetchUnitsAction } from '@unit/store/unit.actions';
export class AppComponent {
constructor(store: Store<AppState>) {
store.dispatch(new FetchUnitsAction());
store.dispatch(AnimalStore.actions.fetchItems());
}
}
3 changes: 2 additions & 1 deletion src/livestock-tracker/ClientApp/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,15 @@ const imports: (unknown[] | ModuleWithProviders<unknown> | Type<unknown>)[] = [
EffectsModule.forRoot([])
];

if (environment.production) {
if (!environment.production) {
imports.push(
StoreDevtoolsModule.instrument({
maxAge: 25,
logOnly: environment.production
})
);
}

@NgModule({
declarations: [AppComponent],
imports,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { RunHelpers } from 'rxjs/internal/testing/TestScheduler';
import { TestScheduler } from 'rxjs/testing';

import { Injectable } from '@angular/core';
import { TestBed, waitForAsync } from '@angular/core/testing';
import { TestBed } from '@angular/core/testing';
import { MatSnackBar, MatSnackBarModule } from '@angular/material/snack-bar';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { KeyEntity, PagedData } from '@core/models';
Expand All @@ -23,6 +23,7 @@ const testActions = crudActionsFactory<TestEntity, number, number>('TEST');
@Injectable()
class TestService implements CrudService<TestEntity, number, number> {
getAll(): Observable<PagedData<TestEntity>> {
console.log('getAll');
throw new Error('Method not implemented.');
}
get(key: number): Observable<TestEntity> {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Observable, of } from 'rxjs';
import { Observable, of, throwError } from 'rxjs';
import { catchError, map, switchMap, tap } from 'rxjs/operators';

import { KeyValue } from '@angular/common';
Expand All @@ -18,8 +18,13 @@ export class CrudEffects<
public getAll$: Observable<Action> = createEffect(() =>
this.actions$.pipe(
ofType(`FETCH_${this.typeName}`),
switchMap((action: Action) => this.handleFetchAction$(action)),
map((data: PagedData<TData>) => this.typeActions.apiFetchItems(data)),
switchMap((action: Action) =>
this.handleFetchAction$(action).pipe(
tap(console.log),
map((data: PagedData<TData>) => this.typeActions.apiFetchItems(data)),
catchError((error) => this.handleError(error, this.typeActions))
)
),
catchError((error) => this.handleError(error, this.typeActions))
)
);
Expand All @@ -28,8 +33,14 @@ export class CrudEffects<
this.actions$.pipe(
ofType(`FETCH_SINGLE_${this.typeName}`),
map((action: PayloadAction<TFetchSinglePayload>) => action.payload),
switchMap((payload: TFetchSinglePayload) => this.service.get(payload)),
map((item: TData) => this.typeActions.apiFetchSingle(item)),
switchMap((payload: TFetchSinglePayload) =>
this.service.get(payload).pipe(
map((item: TData) => this.typeActions.apiFetchSingle(item)),
catchError((error: HttpErrorResponse) =>
this.handleError(error, this.typeActions)
)
)
),
catchError((error) => this.handleError(error, this.typeActions))
)
);
Expand All @@ -38,11 +49,17 @@ export class CrudEffects<
this.actions$.pipe(
ofType(`ADD_${this.typeName}`),
map((action: PayloadAction<TData>) => action.payload),
switchMap((item: TData) => this.service.add(item)),
tap(() =>
this.snackBar.open('Added successfully.', undefined, { duration: 2500 })
switchMap((item: TData) =>
this.service.add(item).pipe(
tap(() =>
this.snackBar.open('Added successfully.', undefined, {
duration: 2500
})
),
map((addedItem: TData) => this.typeActions.apiAddItem(addedItem)),
catchError((error) => this.handleError(error, this.typeActions))
)
),
map((item: TData) => this.typeActions.apiAddItem(item)),
catchError((error) => this.handleError(error, this.typeActions))
)
);
Expand All @@ -52,17 +69,19 @@ export class CrudEffects<
ofType(`UPDATE_${this.typeName}`),
map((action: PayloadAction<KeyValue<TKey, TData>>) => action.payload),
switchMap((payload: KeyValue<TKey, TData>) =>
this.service.update(payload.value, payload.key)
),
tap(() =>
this.snackBar.open('Updated successfully.', undefined, {
duration: 2500
})
),
map((item: TData) =>
this.typeActions.apiUpdateItem(
{ changes: item, id: String(item.id) },
item.id
this.service.update(payload.value, payload.key).pipe(
tap(() =>
this.snackBar.open('Updated successfully.', undefined, {
duration: 2500
})
),
map((item: TData) =>
this.typeActions.apiUpdateItem(
{ changes: item, id: String(item.id) },
item.id
)
),
catchError((error) => this.handleError(error, this.typeActions))
)
),
catchError((error) => this.handleError(error, this.typeActions))
Expand All @@ -73,13 +92,17 @@ export class CrudEffects<
this.actions$.pipe(
ofType(`DELETE_${this.typeName}`),
map((action: PayloadAction<TKey>) => action.payload),
switchMap((id: TKey) => this.service.delete(id)),
tap(() =>
this.snackBar.open('Deleted successfully.', undefined, {
duration: 2500
})
switchMap((id: TKey) =>
this.service.delete(id).pipe(
tap(() =>
this.snackBar.open('Deleted successfully.', undefined, {
duration: 2500
})
),
map((deletedId: TKey) => this.typeActions.apiDeleteItem(deletedId)),
catchError((error) => this.handleError(error, this.typeActions))
)
),
map((id: TKey) => this.typeActions.apiDeleteItem(id)),
catchError((error) => this.handleError(error, this.typeActions))
)
);
Expand Down Expand Up @@ -118,6 +141,16 @@ export class CrudEffects<
}

protected handleFetchAction$ = (
action: Action
): Observable<PagedData<TData>> => this.service.getAll();
action: Action,
retryCount = 0
): Observable<PagedData<TData>> =>
this.service.getAll().pipe(
catchError((err: HttpErrorResponse): Observable<PagedData<TData>> => {
if (retryCount > 3) {
return throwError(() => err);
}

return this.handleFetchAction$(action, retryCount++);
})
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export * from './medical-transaction-state.interface';
export * from './medicine-type-state.interface';
export * from './pagination/pagination-action.interface';
export * from './pagination/pagination-state.interface';
export * from './selectors';
export * from './unit-state.interface';

import * as RouterSelectors from './router.selectors';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,11 +103,14 @@ export class AnimalEffects extends CrudEffects<Animal, number, number> {
),
map(([action, animal]: [PayloadAction<number>, Animal]):
| PayloadAction<number>
| Action =>
animal == null || animal.batchNumber == null
| Action => {
if (animal != null && animal.id === action.payload) {
return actions.apiFetchSingle(animal);
}
return animal == null || animal.batchNumber == null
? actions.fetchSingle(action.payload)
: NoopAction
)
: NoopAction;
})
)
);

Expand Down Expand Up @@ -213,14 +216,24 @@ export class AnimalEffects extends CrudEffects<Animal, number, number> {
}

protected handleFetchAction$ = (
action: Action
action: Action,
retryCount = 0
): Observable<PagedData<Animal>> => {
const fetchAction = <FetchAnimalsAction>action;
return this.animalService.getAll(
fetchAction.pageSize,
fetchAction.pageNumber,
fetchAction.orderOptions,
fetchAction.includeArchived
);
return this.animalService
.getAll(
fetchAction.pageSize,
fetchAction.pageNumber,
fetchAction.orderOptions,
fetchAction.includeArchived
)
.pipe(
catchError((err: HttpErrorResponse): Observable<PagedData<Animal>> => {
if (retryCount > 3) {
return throwError(() => err);
}
return this.handleFetchAction$(action, retryCount++);
})
);
};
}
Loading

0 comments on commit 5e57194

Please sign in to comment.