Skip to content

Commit

Permalink
Merge pull request #74 from pleonex/feature/small-fixes
Browse files Browse the repository at this point in the history
🐛 Small fixes and improvements
  • Loading branch information
pleonex authored Nov 21, 2023
2 parents 902e0c1 + 1736d88 commit 7362137
Show file tree
Hide file tree
Showing 13 changed files with 211 additions and 106 deletions.
5 changes: 0 additions & 5 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -240,14 +240,9 @@ dotnet_diagnostic.IDE0045.severity = suggestion # Simplify ifs
dotnet_diagnostic.IDE0046.severity = suggestion # Simplify ifs

### StyleCop
dotnet_diagnostic.SA1000.severity = none # false positive, space before parentheses in new()
dotnet_diagnostic.SA1009.severity = none # false positive with ()! for null checking
dotnet_diagnostic.SA1011.severity = none # False positive due to nullables
dotnet_diagnostic.SA1101.severity = none # Do not force to prefix local calls with 'this'
dotnet_diagnostic.SA1204.severity = suggestion # Static methods should be before non-static
dotnet_diagnostic.SA1313.severity = none # Pascal naming broken with records.
dotnet_diagnostic.SA1500.severity = none # Allow inline braces
dotnet_diagnostic.SA1516.severity = none # Multiple blank lines - broken with top-level statements
dotnet_diagnostic.SA1633.severity = none # No XML-format header in source files

### SonarAnalyzer
Expand Down
2 changes: 1 addition & 1 deletion CODE_OF_CONDUCT.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ This Code of Conduct applies both within project spaces and in public spaces whe

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at benito356@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at <pleonex@protonmail.com>. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.

Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.

Expand Down
118 changes: 82 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,31 +1,87 @@
# PleOps Cake recipe: a simple DevOps workflow [![MIT License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat)](https://choosealicense.com/licenses/mit/) ![Build and release](https://github.com/pleonex/PleOps.Cake/workflows/Build%20and%20release/badge.svg?branch=main&event=push)
# PleOps Cake ![logo](./docs/images/logo_48.png)

<!-- markdownlint-disable MD033 -->
<p align="center">
<a href="https://www.nuget.org/packages/Cake.Frosting.PleOps.Recipe">
<img alt="Stable version" src="https://img.shields.io/nuget/v/Cake.Frosting.PleOps.Recipe?label=nuget.org&logo=nuget" />
</a>
&nbsp;
<a href="https://dev.azure.com/benito356/NetDevOpsTest/_packaging?_a=feed&feed=PleOps">
<img alt="GitHub commits since latest release (by SemVer)" src="https://img.shields.io/github/commits-since/pleonex/PleOps.Cake/latest?sort=semver" />
</a>
&nbsp;
<a href="https://github.com/pleonex/PleOps.Cake/workflows/Build%20and%20release">
<img alt="Build and release" src="https://github.com/pleonex/PleOps.Cake/workflows/Build%20and%20release/badge.svg?branch=main&event=push" />
</a>
&nbsp;
<a href="https://choosealicense.com/licenses/mit/">
<img alt="MIT License" src="https://img.shields.io/badge/license-MIT-blue.svg?style=flat" />
</a>
&nbsp;
</p>

Complete DevOps workflow and best-practices for .NET projects based on
[Cake](https://cakebuild.net/).

- ♻️ DevOps best practices for a software project
- 🔧 Build, test and release tasks for .NET projects and documentation sites
- 📚 Documentation explaining the workflow
- 📋 [Template repository](https://github.com/pleonex/template-csharp) ready to
use

## Tech stack

- **Projects**: C# / .NET
- **Documentation**: DocFX, GitHub page
- **CI**: GitHub Actions
- **Release deployment**: NuGet feeds, GitHub

## Get started

Check out the [documentation site](https://www.pleonex.dev/PleOps.Cake/) to
start learning how to use the library.

Full automated build, test, stage and release pipeline for simple .NET projects
based on Cake. Check also the
[template repository](https://github.com/pleonex/template-csharp) to see the
pipeline in action!

Tech stack:

- Projects: C# / .NET
- Documentation: DocFX, GitHub page
- CI: GitHub Actions
- Release publication: NuGet feeds, GitHub

<!-- prettier-ignore -->
| Release | Package |
| ------- | ----------------------------------------------------------------- |
| Stable | [![Nuget](https://img.shields.io/nuget/v/Cake.Frosting.PleOps.Recipe?label=nuget.org&logo=nuget)](https://www.nuget.org/packages/Cake.Frosting.PleOps.Recipe) |
| Preview | [Azure Artifacts](https://dev.azure.com/benito356/NetDevOpsTest/_packaging?_a=feed&feed=PleOps) |

## Requirements
Feel free to ask any question in the
[project discussion](https://github.com/pleonex/PleOps.Cake/discussions).

## Usage

The project ships a NuGet library with [Cake Frosting](https://cakebuild.net/)
tasks:

- `Cake.Frosting.PleOps.Recipe`:
![Package in NuGet](https://img.shields.io/nuget/v/Cake.Frosting.PleOps.Recipe?label=nuget.org&logo=nuget)

To use it, create a new console application with the
[_Cake Frosting_ template](https://cakebuild.net/docs/getting-started/setting-up-a-new-frosting-project),
add a reference to this recipe NuGet and its tasks will be available to use.

```cs
return new CakeHost()
.AddAssembly(typeof(Cake.Frosting.PleOps.Recipe.PleOpsBuildContext).Assembly)
.UseContext<Cake.Frosting.PleOps.Recipe.PleOpsBuildContext>()
.UseLifetime<BuildLifetime>()
.Run(args);

[TaskName("Default")]
[IsDependentOn(typeof(Cake.Frosting.PleOps.Recipe.Common.SetGitVersionTask))]
[IsDependentOn(typeof(Cake.Frosting.PleOps.Recipe.Common.CleanArtifactsTask))]
[IsDependentOn(typeof(Cake.Frosting.PleOps.Recipe.Dotnet.DotnetTasks.BuildProjectTask))]
public sealed class DefaultTask : FrostingTask
{
}
```

- .NET 8.0 SDK
> [!TIP]
> Find a detailed setup guide in the
> [documentation site](https://www.pleonex.dev/PleOps.Cake/docs/getting-started/tutorial.html).
## Preview versions
### Preview releases

To use a preview version, add a `nuget.config` file in the repository root
directory with the following content:
Preview releases are in an
[Azure DevOps NuGet feed](https://dev.azure.com/benito356/NetDevOpsTest/_packaging?_a=feed&feed=PleOps).
Add a `nuget.config` file in the repository root directory with the following
content:

```xml
<?xml version="1.0" encoding="utf-8"?>
Expand All @@ -47,25 +103,15 @@ directory with the following content:
</configuration>
```

## Documentation

Feel free to ask any question in the
[project Discussion site!](https://github.com/pleonex/PleOps.Cake/discussions)

Check the [documentation](https://www.pleonex.dev/PleOps.Cake/) for more
information. For reference, this is the general build and release pipeline.

![release diagram](./docs/articles/workflows/images/release_automation.png)

## Build

The project requires to build .NET 8.0 SDK.

To build, test and generate artifacts run:

```sh
# Build and run tests
dotnet run --project build/orchestrator -- --target=Default
# Build and run tests (with code coverage!)
dotnet run --project build/orchestrator

# (Optional) Create bundles (nuget, zips, docs)
dotnet run --project build/orchestrator -- --target=Bundle
Expand Down
71 changes: 52 additions & 19 deletions docs/index.md
Original file line number Diff line number Diff line change
@@ -1,47 +1,80 @@
# PleOps Cake
# PleOps Cake ![logo](./images/logo_48.png)

<!-- markdownlint-disable MD033 -->
<p align="center">
<a href="https://www.nuget.org/packages/Cake.Frosting.PleOps.Recipe">
<img alt="Stable version" src="https://img.shields.io/nuget/v/Cake.Frosting.PleOps.Recipe?label=nuget.org&logo=nuget" />
</a>
&nbsp;
<a href="https://dev.azure.com/benito356/NetDevOpsTest/_packaging?_a=feed&feed=PleOps">
<img alt="GitHub commits since latest release (by SemVer)" src="https://img.shields.io/github/commits-since/pleonex/PleOps.Cake/latest?sort=semver" />
</a>
&nbsp;
<a href="https://github.com/pleonex/PleOps.Cake/workflows/Build%20and%20release">
<img alt="Build and release" src="https://github.com/pleonex/PleOps.Cake/workflows/Build%20and%20release/badge.svg?branch=main&event=push" />
</a>
&nbsp;
<a href="https://choosealicense.com/licenses/mit/">
<img alt="MIT License" src="https://img.shields.io/badge/license-MIT-blue.svg?style=flat" />
</a>
&nbsp;
</p>

Complete DevOps workflow and best-practices for .NET projects based on
[Cake](https://cakebuild.net/).

- ♻️ DevOps best practices for a software project
- 🔧 Build, test and release tasks for .NET projects and documentation sites
- 📚 Documentation explaining the workflow
- [Template repository](https://github.com/pleonex/template-csharp) ready to use
- 📋 [Template repository](https://github.com/pleonex/template-csharp) ready to
use

## Tech stack

- Projects: C# / .NET
- Documentation: DocFX, GitHub page
- CI: GitHub Actions
- Release deployment: NuGet feeds, GitHub
- **Projects**: C# / .NET
- **Documentation**: DocFX, GitHub page
- **CI**: GitHub Actions
- **Release deployment**: NuGet feeds, GitHub

## Usage

The project ships a NuGet library with [Cake Frosting](https://cakebuild.net/)
tasks: **`Cake.Frosting.PleOps.Recipe`**.
tasks:

- `Cake.Frosting.PleOps.Recipe`:
![Package in NuGet](https://img.shields.io/nuget/v/Cake.Frosting.PleOps.Recipe?label=nuget.org&logo=nuget)

To use it, create a new console application with the
[_Cake Frosting_ template](https://cakebuild.net/docs/getting-started/setting-up-a-new-frosting-project),
add a reference to this recipe NuGet and its tasks will be available to use.

**More information in the
[setup guide](./articles/getting-started/tutorial.md).**
```cs
return new CakeHost()
.AddAssembly(typeof(Cake.Frosting.PleOps.Recipe.PleOpsBuildContext).Assembly)
.UseContext<Cake.Frosting.PleOps.Recipe.PleOpsBuildContext>()
.UseLifetime<BuildLifetime>()
.Run(args);

## Quick demo
[TaskName("Default")]
[IsDependentOn(typeof(Cake.Frosting.PleOps.Recipe.Common.SetGitVersionTask))]
[IsDependentOn(typeof(Cake.Frosting.PleOps.Recipe.Common.CleanArtifactsTask))]
[IsDependentOn(typeof(Cake.Frosting.PleOps.Recipe.Dotnet.DotnetTasks.BuildProjectTask))]
public sealed class DefaultTask : FrostingTask
{
}
```

You can check this workflow from the
[template repository](https://github.com/pleonex/template-csharp). Just clone /
download it and run its build system:
Then just run the project to start the build system:

```bash
# Build and run tests (with code coverage!)
dotnet run --project build/orchestrator

# Create bundles (nuget, zips, docs)
dotnet run --project build/orchestrator -- --target=Bundle
```

Commits will trigger a new continuous integration build with a similar output as
this:
Pushing commits will trigger a new continuous integration build with a similar
output as this:

![ci-output](./articles/getting-started/images/github-actions-summary.png)

> [!TIP]
> Find a detailed setup guide in the
> [documentation site](articles/getting-started/tutorial.md).
9 changes: 0 additions & 9 deletions docs/template/public/main.css
Original file line number Diff line number Diff line change
@@ -1,16 +1,7 @@
/* Changing the site font */
@import url("https://fonts.googleapis.com/css2?family=Nunito:wght@100;400;700&display=swap");
/* @import url('https://fonts.googleapis.com/css2?family=Inconsolata&display=swap'); */
@import url("https://fonts.googleapis.com/css2?family=Fira Code&display=swap");

/*@import url('https://fonts.cdnfonts.com/css/cascadia-code');*/
/* @font-face {
font-family: 'Cascadia Code';
font-style: normal;
font-weight: 100;
src: local('Cascadia Code'), url('https://fonts.cdnfonts.com/s/29131/Cascadia.woff') format('woff');
} */

:root {
--bs-font-sans-serif: "Nunito";
--bs-font-monospace: "Fira Code";
Expand Down
61 changes: 61 additions & 0 deletions src/Cake.Frosting.PleOps.Recipe/CakeArgumentsExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright (c) 2023 Benito Palacios Sánchez
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
namespace Cake.Frosting.PleOps.Recipe;

using Cake.Core;

/// <summary>
/// Extension methods for ICakeArguments class.
/// </summary>
public static class CakeArgumentsExtensions
{
/// <summary>
/// Run the setter if the argument name is present.
/// </summary>
/// <param name="handler">Cake argument handler.</param>
/// <param name="argName">Argument name.</param>
/// <param name="setter">Setter to run.</param>
public static void SetIfPresent(this ICakeArguments handler, string argName, Action<string> setter)
{
if (handler.HasArgument(argName)) {
setter(handler.GetArgument(argName));
}
}

/// <summary>
/// Run the setter if the argument name is present.
/// </summary>
/// <param name="handler">Cake argument handler.</param>
/// <param name="argName">Argument name.</param>
/// <param name="setter">Setter to run.</param>
public static void SetIfPresent(this ICakeArguments handler, string argName, Action<bool> setter)
{
if (handler.HasArgument(argName)) {
string valueText = handler.GetArgument(argName);
if (string.IsNullOrEmpty(valueText)) {
// If it's present but without value, assume is like a set -> true
setter(true);
} else {
bool value = bool.Parse(handler.GetArgument(argName));
setter(value);
}
}
}
}
6 changes: 3 additions & 3 deletions src/Cake.Frosting.PleOps.Recipe/Dotnet/DotNetBuildContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -146,10 +146,10 @@ public void ReadArguments(PleOpsBuildContext context)
_ => throw new NotSupportedException("Unknown Cake verbosity"),
};

context.IfArgIsPresent("dotnet-configuration", x => Configuration = x);
context.IfArgIsPresent("dotnet-platform", x => Platform = x);
context.Arguments.SetIfPresent("dotnet-configuration", x => Configuration = x);
context.Arguments.SetIfPresent("dotnet-platform", x => Platform = x);

context.IfArgIsPresent("dotnet-test-filter", x => TestFilter = x);
context.Arguments.SetIfPresent("dotnet-test-filter", x => TestFilter = x);

PreviewNuGetFeedToken = context.Environment.GetEnvironmentVariable("PREVIEW_NUGET_FEED_TOKEN");
StableNuGetFeedToken = context.Environment.GetEnvironmentVariable("STABLE_NUGET_FEED_TOKEN");
Expand Down
26 changes: 7 additions & 19 deletions src/Cake.Frosting.PleOps.Recipe/PleOpsBuildContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -154,30 +154,18 @@ public PleOpsBuildContext(ICakeContext context)
IIssuesState IIssuesContext.State => IssuesContext.State;
#endif

/// <summary>
/// Run the setter if the argument name is present.
/// </summary>
/// <param name="argName">Argument name.</param>
/// <param name="setter">Setter to run.</param>
public void IfArgIsPresent(string argName, Action<string> setter)
{
if (Arguments.HasArgument(argName)) {
setter(Arguments.GetArgument(argName));
}
}

/// <summary>
/// Initialize the build context with command-line arguments if present.
/// </summary>
public virtual void ReadArguments()
{
IfArgIsPresent("artifacts", x => ArtifactsPath = Path.GetFullPath(x));
IfArgIsPresent("temp", x => TemporaryPath = Path.GetFullPath(x));
IfArgIsPresent("version", x => Version = x);
WarningsAsErrors = WarningsAsErrors || Arguments.HasArgument("warn-as-error");
IsIncrementalBuild = IsIncrementalBuild || Arguments.HasArgument("incremental");
IfArgIsPresent("changelog-next", x => ChangelogNextFile = x);
IfArgIsPresent("changelog", x => ChangelogFile = x);
Arguments.SetIfPresent("artifacts", x => ArtifactsPath = Path.GetFullPath(x));
Arguments.SetIfPresent("temp", x => TemporaryPath = Path.GetFullPath(x));
Arguments.SetIfPresent("version", x => Version = x);
Arguments.SetIfPresent("warn-as-error", x => WarningsAsErrors = x);
Arguments.SetIfPresent("incremental", x => IsIncrementalBuild = x);
Arguments.SetIfPresent("changelog-next", x => ChangelogNextFile = x);
Arguments.SetIfPresent("changelog", x => ChangelogFile = x);

DotNetContext.ReadArguments(this);
DocFxContext.ReadArguments(this);
Expand Down
Loading

0 comments on commit 7362137

Please sign in to comment.