Skip to content

Commit

Permalink
Able to run grate programmatically (#417)
Browse files Browse the repository at this point in the history
* - applying dotnet format

* - moving current grate to src\grate.console project

* - restructure the current grate base on the proposal

* - rename grate to grate.core and grate.console to grate (prevent the breaking change in publish artifact)

* - adding more test case and remove unuse namespace

* - add DependencyInjectionRegistrationExtensions

* - cleanup code and restructure to the right place for unit test

* - remove the IFactory, using MS DI instead.

* chore(unuse imports)

* - remove the target framework in build.props to load the TFM successfully.

* - fix the grate command.

* - add UT for service collection.

* - adding more UT and change to IDbConnection instead of DbConnection.

* - fix overriding method

* - Remove database type and masterDatabase in IGrateTestContext, using static instead.

* - update the docker build and its example

* - add k8s with init container and multi-tenancy example

* - adding more comment into grate builder

* - fix Ut error related to set table casing

* update grate docs

* - add grate nuget package publishing

* - Add NuGet.md into package

* -chore(code format)

* - update code comment

* - fix github workflow ident for push nuget package

* - add symbols for source link
  • Loading branch information
hoangthanh28 authored Jan 14, 2024
1 parent 43d45e5 commit 225220b
Show file tree
Hide file tree
Showing 225 changed files with 2,964 additions and 856 deletions.
54 changes: 44 additions & 10 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ jobs:
run: dotnet restore
- name: Build
#run: dotnet pack ./grate/grate.csproj -c release -p:PackAsTool=true -p:PackageOutputPath=/tmp/grate/nupkg
run: dotnet pack ./grate/grate.csproj -p:SelfContained=false -p:PackAsTool=true -p:PackageOutputPath=/tmp/grate/nupkg
run: dotnet pack ./src/grate/grate.csproj -p:SelfContained=false -p:PackAsTool=true -p:PackageOutputPath=/tmp/grate/nupkg
env:
VERSION: ${{ needs.set-version-number.outputs.nuGetVersion }}

Expand All @@ -66,6 +66,39 @@ jobs:
- name: Push to Nuget.org
if: ${{ needs.set-version-number.outputs.is-release == 'true' }}
run: dotnet nuget push /tmp/grate/nupkg/*.nupkg --source https://api.nuget.org/v3/index.json --api-key ${{secrets.NUGET_ORG_KEY}} --skip-duplicate

build-nuget-package:
needs: set-version-number
name: Build Nuget Packages

runs-on: ubuntu-latest
strategy:
matrix:
package: [ "grate.mariadb",
"grate.oracle",
"grate.postgresql",
"grate.sqlite",
"grate.sqlserver"
]
steps:
- uses: actions/checkout@v4

- name: Setup .NET 8
uses: actions/setup-dotnet@v4
with:
dotnet-version: 8.0.x

- name: Restore dependencies
run: dotnet restore

- name: Pack Nuget package ${{ matrix.package }}
run: dotnet pack ./src/${{ matrix.package }} -c Release --include-symbols -o /tmp/grate/nupkg /p:Version=${{ env.VERSION }}
env:
VERSION: ${{ needs.set-version-number.outputs.nuGetVersion }}

- name: Push to Nuget.org
if: ${{ needs.set-version-number.outputs.is-release == 'true' }}
run: dotnet nuget push /tmp/grate/nupkg/*.nupkg --source https://api.nuget.org/v3/index.json --api-key ${{secrets.NUGET_ORG_KEY}} --skip-duplicate

build-standalone:
name: Build
Expand All @@ -87,12 +120,12 @@ jobs:
dotnet-version: 8.0.x

- name: Publish self-contained ${{ matrix.arch }}
run: dotnet publish ./grate/grate.csproj -f net8.0 -r ${{ matrix.arch }} -c release --self-contained -p:SelfContained=true -o ./publish/${{ matrix.arch }}/self-contained
run: dotnet publish ./src/grate/grate.csproj -f net8.0 -r ${{ matrix.arch }} -c release --self-contained -p:SelfContained=true -o ./publish/${{ matrix.arch }}/self-contained
env:
VERSION: ${{ needs.set-version-number.outputs.nuGetVersion }}

- name: Publish .NET 6/7/8 dependent ${{ matrix.arch }}
run: dotnet publish ./grate/grate.csproj -r ${{ matrix.arch }} -c release --no-self-contained -o ./publish/${{ matrix.arch }}/dependent
run: dotnet publish ./src/grate/grate.csproj -r ${{ matrix.arch }} -c release --no-self-contained -o ./publish/${{ matrix.arch }}/dependent
env:
VERSION: ${{ needs.set-version-number.outputs.nuGetVersion }}

Expand Down Expand Up @@ -144,7 +177,7 @@ jobs:
name: Build and push docker image
needs:
- set-version-number
- build-standalone
#- build-standalone ## no need, we build directly from source
runs-on: ubuntu-latest
if: ${{ needs.set-version-number.outputs.is-release == 'true' }}
env:
Expand All @@ -154,10 +187,10 @@ jobs:

steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v3
with:
name: grate-linux-musl-x64-self-contained-${{ needs.set-version-number.outputs.nuGetVersion }}
path: installers/docker/
# - uses: actions/download-artifact@v3 # download from another artifact is not a good idea, we need to build directly from source
# with:
# name: grate-linux-musl-x64-self-contained-${{ needs.set-version-number.outputs.nuGetVersion }}
# path: installers/docker/


- name: Log in to the Container registry
Expand All @@ -183,7 +216,8 @@ jobs:
- name: Build and push Docker image
uses: docker/build-push-action@4a13e500e55cf31b7a5d59a38ab2040ab0f42f56
with:
context: ./installers/docker/
file: ./installers/docker/Dockerfile
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
Expand Down Expand Up @@ -212,7 +246,7 @@ jobs:
arch=$(echo ${{ matrix.arch }} | cut -d- -f2 | sed 's/x64/amd64/')
echo "::set-output name=arch::$arch"
- name: Create dpkg
- name: Create dpkg # Linux with powershell script? really?
if: ${{ needs.set-version-number.outputs.is-release == 'true' }}
run: ./installers/deb/Create-Package.ps1 -grateExe ./${{ matrix.arch }}/grate -Version "${{ needs.set-version-number.outputs.nuGetVersion }}" -arch ${{ steps.get-arch.outputs.arch}}
env:
Expand Down
8 changes: 5 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
run: |
dotnet restore -r linux-x64 grate.sln
- name: Build
run: dotnet build -f net8.0 --no-restore --no-self-contained -r linux-x64 grate/grate.csproj -c release
run: dotnet build -f net8.0 --no-restore --no-self-contained -r linux-x64 src/grate/grate.csproj -c release


analyze:
Expand All @@ -47,8 +47,10 @@ jobs:
- name: Setup .NET 8
uses: actions/setup-dotnet@v4
with:
dotnet-version: 8.0.x

dotnet-version: |
6.0.x
7.0.x
8.0.x
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
Expand Down
1 change: 0 additions & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
<NetTargetFrameworks Condition=" '$(NetTargetFrameworks)' == '' ">
net6.0;net7.0;net8.0
</NetTargetFrameworks>
<TargetFramework Condition=" '$(TargetFramework)' == '' ">net8.0</TargetFramework>
</PropertyGroup>

<PropertyGroup>
Expand Down
17 changes: 17 additions & 0 deletions docs/GettingGrate.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,23 @@ The [github site](https://github.com/erikbra/grate/) has both the raw source cod

There's a `{{ site.github.repository_nwo }}` docker image published to [dockerhub](https://hub.docker.com/r/{{ site.github.repository_nwo }}) on every release. See the [examples](https://github.com/erikbra/grate/tree/main/examples) folder for a demo using this to a migration.

Start the sqlserver database
```sh
docker network create grate_network && docker run -e SA_PASSWORD=gs8j4AS7h87jHg -e ACCEPT_EULA=Y --name db --network grate_network -d mcr.microsoft.com/mssql/server:2019-latest
```
Run grate migration
```sh
docker run -v ./examples/docker/db:/db -e APP_CONNSTRING="Server=db;Database=grate_test_db;User Id=sa;Password=gs8j4AS7h87jHg;TrustServerCertificate=True" --network grate_network erikbra/grate
# run with database type, accept: sqlserver, postgresql, mariadb, sqlite, oracle
# docker run -v ./examples/docker/db:/db -e DATABASE_TYPE=sqlserver -e CREATE_DATABASE=true -e ENVIRONMENT=Dev -e TRANSACTION=true -e APP_CONNSTRING="Server=db;Database=grate_test_db;User Id=sa;Password=gs8j4AS7h87jHg;TrustServerCertificate=True" --network grate_network erikbra/grate
```

Cleanup resources
```sh

docker kill db || docker network rm grate_network || docker rm $(docker ps -f status=exited | awk '{print $1}')
```

## Dotnet Tool

grate is available as a [dotnet global tool](https://docs.microsoft.com/en-us/dotnet/core/tools/global-tools). Simply `dotnet tool install -g grate` to get the [package](https://www.nuget.org/packages/grate/).
Expand Down
1 change: 0 additions & 1 deletion examples/docker/build-and-run.ps1
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#!/bin/env pwsh

# App versioning is normally provided by your CI/CD pipelines...
docker-compose build --build-arg APP_VERSION=0.0.1
docker-compose up
1 change: 1 addition & 0 deletions examples/docker/db/runFirstAfterUp/001_greeting.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
INSERT INTO grate_test(name) VALUES ('Hello grate from docker !');
4 changes: 4 additions & 0 deletions examples/docker/db/up/001_create_table.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
CREATE TABLE grate_test (
id int IDENTITY(1,1) NOT NULL PRIMARY KEY,
name nvarchar(255) NOT NULL
)
18 changes: 13 additions & 5 deletions examples/docker/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
version: "3.7"
services:
db-migration:
build: .
image: myapp-dbmigration
#build: .
image: erikbra/grate:latest
environment:
# don't configure passwords here for real. This is just a sample!
- APP_CONNSTRING="Server=db;Database=grate_test;User Id=sa;Password=gs8j4AS7h87jHg"

APP_CONNSTRING: "Server=db;Database=grate_test;User Id=sa;Password=gs8j4AS7h87jHg;TrustServerCertificate=True"
VERSION: "1.0.0.0"
DATABASE_TYPE: "sqlserver" # sqlite, oracle, postgresql, sqlserver, mariadb
volumes:
- ./db:/db
- ./output:/output

depends_on:
- db
db:
image: mcr.microsoft.com/mssql/server:2019-latest
environment:
- SA_PASSWORD=gs8j4AS7h87jHg # again, plain text passwords are bad mmkay!
- ACCEPT_EULA=Y
- MSSQL_PID=Express
- MSSQL_PID=Express
ports:
- "1433:1433"
17 changes: 0 additions & 17 deletions examples/docker/dockerfile

This file was deleted.

1 change: 1 addition & 0 deletions examples/docker/output/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*
3 changes: 1 addition & 2 deletions examples/docker/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@ This directory shows a very simple way of building a docker container to apply y
## Usage

Simply `docker-compose up` to:
- build a local `myapp-dbmigration` image that contains both grate and the migration scripts based on the published `grate` image.
- start a sql database server
- run the `myapp-dbmigration` migration against the server
- run the `grate` migration against the server with script locate in `db` folder and store the backup script in `output`

## Notes

Expand Down
18 changes: 18 additions & 0 deletions examples/k8s/initcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
FROM mcr.microsoft.com/dotnet/sdk:8.0-alpine AS build
WORKDIR .

COPY sample-service/ ./sample-service/
RUN dotnet publish ./sample-service/*.csproj -c release -o ./publish/app

FROM mcr.microsoft.com/dotnet/aspnet:8.0-alpine as runtime
WORKDIR /app

COPY --from=build /publish/app .

# Add globalization support to the OS so .Net can use cultures
RUN apk add icu-libs
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false
ENV ASPNETCORE_URLS=http://[::]:80
ENV ASPNETCORE_ENVIRONMENT=Production

ENTRYPOINT ["dotnet", "sample-service.dll"]
11 changes: 11 additions & 0 deletions examples/k8s/initcontainer/Dockerfile-db
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
FROM erikbra/grate:latest as base
WORKDIR /app
COPY sql/ /db
RUN mkdir /output
ENTRYPOINT ./grate \
--sqlfilesdirectory=/db \
--version=$VERSION \
--connstring="$APP_CONNSTRING" \
--silent \
--databasetype=sqlserver \
--outputPath=/output
42 changes: 42 additions & 0 deletions examples/k8s/initcontainer/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
## Grate with k8s

You can propably run grate on your production environment using k8s init container. Please see the very basic example how to config and deploy to k8s.

## Prerequisite:

Local k8s simulator: you can use [minikube](https://github.com/kubernetes/minikube) (my favorite) or [kind](https://github.com/kubernetes-sigs/kind)

## Usage

Now let's get started with your terminal (any Linux dist, MacOS or WSL2):
- Open your terminal and start minikube

```sh
minikube start
```

- Apply the deployment

```sh
kubectl apply -f deployment.yaml
```
- You can check the status with command
```sh
kubectl get pods -w | grep grate
```
- After the pod started, let's test the data :D
```sh
kubectl port-forward svc/grate-k8s 5000:5000
# sending the http request
curl -sL http://localhost:5000/api/grate | jq
```
- Done. Remember to destroy the cluster
```sh
minikube stop
```
## Notes
- Curious how it works, see the `Dockerfile` and `Dockerfile-db`.
Loading

0 comments on commit 225220b

Please sign in to comment.