nwheels-io / NWheels

DIY full-stack+BI+DevOps in no time: tiny DSLs transpiled into maintainable codebases for selected technology stacks
MIT License
20 stars 9 forks source link

Make NWheels consumable through NuGet packages #77

Closed felix-b closed 6 years ago

felix-b commented 7 years ago

Applications will use NWheels through referencing NuGet packages. We need to define the set of packages, responsibility of each package, and dependencies between them.

Staying non-opinionated

The goal is being as less opinionated as possible. We should extract opinionated parts into separate packages, so that application developers can choose if they want to follow each one of them. We need to create a set of packages, of which one can compose a framework to taste.

Release process

  1. Published by build server: packages must be built and published to NuGet repositories by the build server, as part of CI build. It is disallowed to publish packages built on a dev machine.

  2. Versioned by build server: packages will be assigned version number and other metadata by the build server during CI build. Version and other metadata set in the source .csproj files will be ignored, except package description. Package description is different for every package, and is specified with <Description> element in .csproj files.

  3. Single publisher: though we're going to run builds on multiple build servers (AppVeyor, Travis, ...), only one server will be the publisher of NuGet packages. Since AppVeyor provides out-of-the-box handling of NuGet packages, AppVeyor will be the publisher.

  4. Public and CI feeds: packages created by AppVeyor CI build will be automatically published to AppVeyor project feed (the CI feed). Selected versions (usually alpha, beta, and release) will be manually republished from the CI feed to nuget.org. The CI feed URL is:

    https://ci.appveyor.com/nuget/nwheels-fp6k3xvwl8uu

Target frameworks

The packages must target .NET Standard 2.0. They must be consumable both by projects that target .NET Core 2.0, and .by projects that target .NET Framework 4.6.1.

Version numbering

NWheels will follow SemVer 2.0 spec for version numbering of the packages.

For instance:

Build number and assembly versions

Assembly version and package version are not the same thing. In particular, assembly version consists of four integers, and doesn't support pre-release suffix.

Still, we want the assembly version to be correlated with the package version. For this reason, NWheels assemblies will be assigned version X.Y.Z.N during CI build, where X.Y.Z is package version without pre-release suffix, and N is build number.

Build number is a unique counter, which is managed by AppVeyor, and is shared across all branches and versions.

List of packages

Below is proposed initial list of packages. Some of listed packages functionality doesn't exist at the moment. More packages will be added as NWheels implements more functionality.

Core packages: programming models

Package Depends on Responsibility
NWheels.Kernel none DI, feature loaders, execution path, authorization mechanism
NWheels.Microservices NWheels.Kernel microservice host, boot configuration, lifecycle events, deployment programming model
NWheels.Compilation NWheels.Kernel code generation programming model, type factory abstractions, type library mechanism, compilation backend adapter port
NWheels.MetaObjects NWheels.Kernel, NWheels.Compilation object contracts and metadata programming model, base classes for type factories of metadata-based objects
NWheels.Logging NWheels.Kernel, NWheels.Compilation, NWheels.MetaObjects logging programming model and adapter ports, logger object type factory
NWheels.Configuration NWheels.Kernel, NWheels.Compilation, NWheels.MetaObjects configuration programming model and adapter ports, configuration object type factory
NWheels.Transactions NWheels.Kernel, NWheels.Logging Transaction programming model (unit of work, commit, change set, 2-phase commit, transaction resource).
NWheels.Communication NWheels.Kernel, NWheels.Compilation, NWheels.MetaObjects, NWheels.Microservices, NWheels.Logging, NWheels.Configuration communication endpoints programming model and adapter ports, message object type factory
NWheels.RestApi NWheels.Kernel, NWheels.Compilation, NWheels.Logging RESTful API programming model, REST API service component, protocol adapter port
NWheels.DB NWheels.Kernel, NWheels.Compilation, NWheels.Logging, NWheels.Configuration Data persistence (ORM/ODM/...) programming model and adapter ports
NWheels.Ddd NWheels.Kernel, NWheels.Compilation, NWheels.MetaObjects, NWheels.Logging, NWheels.DB Domain-driven design programming model
NWheels.UI NWheels.Kernel, NWheels.Compilation, NWheels.MetaObjects, NWheels.Logging Declarative user interface programming model and adapter ports

Technology stack packages: adapter modules

Package Responsibility
NWheels.Microservices.Adapters.Docker Adapter of deployment builder port to Docker
NWheels.DB.Adapters.Mongo Adapter of data persistence port to MongoDB
NWheels.DB.Adapters.EFCore Adapter of data persistence port to EntityFramework Core (basically, all relational DBs supported by EF Core)
NWheels.Communication.Adapters.AspNetCore Adapter of communication endpoint port to ASP.NET Core with Kestrel
NWheels.Communication.Adapters.SocketIO Adapter of communication endpoint port to socket.io protocol
NWheels.Communication.Adapters.Tcp Adapter of communication endpoint port to a fast proprietary protocol over TCP sockets
NWheels.RestApi.Adapters.AspNetCore Enables handling of REST API requests from ASP.NET Core endpoints.
NWheels.RestApi.Adapters.SocketIO Enables handling of REST API requests from socket.io endpoints.
NWheels.RestApi.Adapters.Tcp Enables handling REST API requests from endpoints provided by NWheels.Communication.Adapters.Tcp.
NWheels.UI.Adapters.Angular UI adapter for web SPA based on Angular framework
NWheels.UI.Adapters.React UI adapter for web SPA based on React framework
NWheels.UI.Adapters.ReactNative UI adapter for native Android and iOS apps based on React Native framework
NWheels.UI.Adapters.ElectronReact UI adapter for desktop applications based on Electron and React framework

Domain building block packages (planned)

Package Responsibility
NWheels.Domains.ApplicationSecurity User account management, authentication mechanisms (passwords, 2-factor, etc), authentication through 3rd parties (e. g. social networks), administration of authorization rules.
NWheels.Domains.Merchant Domain model of a shopping cart for e-commerce and retail; includes sophisticated pricing and upsell logic, integration with common merchant services (e.g. PayPal, Stripe, ...), and interaction with point-of-sale devices.
NWheels.Domains.Crm An extensible and fully capable CRM domain model, comparable to that of Salesforce or MS Dynamics CRM.
felix-b commented 7 years ago

@ILyaIL83, I would appreciate if you can give an input on this issue.

ILyaIL83 commented 7 years ago

"Example: in package 1.2.3-beta.2.543, assemblies will have version 1.2.3.543." Should it be 1.2.3-beta.543? Why do we need "A" in alpha.A.N and "B" in beta.B.N?

ILyaIL83 commented 7 years ago

0.dev/alpha/beta is it branch names(otherwise, how AppVeyour can know this info)?

ILyaIL83 commented 7 years ago

I don't see how NWheels.Kernel can be separated for now from NWheels.Microservices, plenty of kernel stuff is going in MicroserviceHost? So IMHO it shouldn't be splitted.

felix-b commented 7 years ago

@ILyaIL83,

"Example: in package 1.2.3-beta.2.543, assemblies will have version 1.2.3.543." Should it be 1.2.3-beta.543?

Assembly version and package version are not the same thing. Assembly version is represented by System.Version class, so it consists of four integers, and doesn't support pre-release suffix.

For example for version 1.2.3 beta-4 build 987: we cannot write:

[assembly:AssemblyVersion("1.2.3-beta.4.987")]

because System.Version won't be able to parse it. But we can set:

[assembly:AssemblyVersion("1.2.3.987")]

which would be the closest match.

felix-b commented 7 years ago

Why do we need "A" in alpha.A.N and "B" in beta.B.N?

If we have several alphas and betas, like alpha-1, alpha-2, etc we need a place in the version number for these "1" and "2" -- the "A" for alpha or "B" for beta.

"N" is the build number and it is always present, except in package release version. Since package versions follow SemVer 2, and in SemVer 2, release version has no pre-release suffix, we have no place for build number. In assembly version, the build number will be present in release versions, too.

A few examples to clarify:

Version being built Package version Assembly version
1.2.3 in dev, build 473 1.2.3-0.dev.473 1.2.3.473
1.2.3 beta 1, build 549 1.2.3-beta.1.549 1.2.3.549
1.2.3 beta 2, build 678 1.2.3-beta.2.678 1.2.3.678
1.2.3 release, build 679 1.2.3 1.2.3.679
(version number spec) (SemVer 2.0) (System.Version)

Note that both for package and assembly version, value in each subsequent row is greater than value in previous one -- according SemVer 2 and System.Version.

felix-b commented 7 years ago

0.dev/alpha/beta is it branch names(otherwise, how AppVeyour can know this info)?

version number is set in the first lines of appveyor.yml:

version: 0.1.0-0.dev.{build}

branches:
  only:
  - master

image: Visual Studio 2017

. . . . .

when we decide that we reached a pre-release point, we will commit a change to appveyor.yml, like this:

version: 1.0.0-alpha.1.{build}

this also plays well with branches, as every branch can have its own version of appveyor.yml

felix-b commented 7 years ago

I don't see how NWheels.Kernel can be separated for now from NWheels.Microservices, plenty of kernel stuff is going in MicroserviceHost? So IMHO it shouldn't be splitted.

Parts of NWheels functionality can be consumed without microservices. For instance, one can use NWheels.Kernel, NWheels.MetaObjects, NWheels.Compilaiton, NWheels.DB without NWheels.Microservices.

The opposite is not true: NWheels,Microservices (and everything else) depends on NWheels.Kernel.

In general, it makes me think that we must define explicit use cases of what can be used without what. Then we can automatically validate that forbidden dependencies don't creep in.

felix-b commented 6 years ago

Done in PR #81