@halospv3/hce.shared-config
Version:
Automate commit message quality, changelogs, and CI/CD releases. Exports a semantic-release shareable configuration deserialized from this package's '.releaserc.yml'. Shared resources for .NET projects are also distributed with this package.
326 lines (257 loc) • 10.7 kB
Markdown
# HCE.Shared
## NOTICE
> Activity is held up by a rewrite for the `next/3.0.0` branch.
>
> A fix for the `2.x` branch may be feasible if all that's wrong is async functions in CJS. The `2.x` release channel will not receive feature updates, but fixes and dependency updates are acceptable.
Infrastructure resources shared with other HaloSPV3 repositories.
It is recommended to "install" this repo via [Node Package Manager](#npm)
## Usage
### 1. Install `/hce.shared-config`
This project is packaged and published via NPM. As such...
```sh
npm install --save-dev /hce.shared-config
```
### 2. Customize Semantic Release
WARNING! Defining a property will _overwrite_ the previous value. Arrays and
objects are _not_ merged. You can...
- Assign to certain top-level variables (e.g. `options.preset`) to avoid
modifying the plugins array. Caveat: only *some* plugins read these properties.
- Write your config in MJS; It is recommended you use
[deepmerge](https://www.npmjs.com/package/deepmerge) to recursively merge
objects and arrays instead of using `extends`. Doing so will allow your IDE to
tell you when a shareable config cannot be found.
#### Base Config
> - Uses the [conventionalcommits preset](https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-changelog-conventionalcommits).
> - Releases `main` branch; Pre-releases `develop`.
> - Adds and configures [`semantic-release-export-data`](https://github.com/felipecrs/semantic-release-export-data) to export `new-release-published` and `new-release-version` to GitHub Actions' outputs.
> - Adds and configures [`-release/changelog`](https://github.com/semantic-release/changelog) to update CHANGELOG.md.
> - Configures [`-release/git`](https://github.com/semantic-release/git) to add README.md and CHANGELOG.md in a release commit if they have changes. Uses GitHub job's token to commit.
> - Configures [`-release/github`](https://github.com/semantic-release/github) to release all files found in `$PWD/publish`.
##### Usage
```js
// releaserc.config.js
import hceSharedConfig from "@halospv3/hce.shared-config"
// modify it however you wish before the export statement!
export default hceSharedConfig;
```
```js
// releaserc.config.js
export default {
extends: ["@halospv3/hce.shared-config"]
}
```
```json
// package.json
{
"release": {
"extends": ["@halospv3/hce.shared-config"]
}
}
```
#### Dotnet Config
> An extension of our base config.
> Exports a function with parameters for 'projects to pack' and 'projects to push (to nuget)'.
> Although `/hce.shared-config/semanticReleaseConfigDotnet` can be used
via `extends` and configured via the `PROJECTS_TO_PUBLISH` and
`PROJECTS_TO_PACK_AND_PUSH` environment variables, it is recommended to call
the function and pass it parameters so errors are caught before they reach
production.
>
> Differences to the base config:
> - Utilizes `-release/exec` for shell commands.
> - Executes `dotnet publish` and `dotnet pack` upon the configured projects during the `prepare` step.
> - (WIP) Executes `dotnet nuget sign` during `prepare` upon the `dotnet pack` outputs if `projectsToPackAndPush` is not set to `false` (default: `[]`).
> - Executes `dotnet nuget push` during the `publish` step.
##### Usage
```js
// releaserc.config.js
import { getConfig } from "@halospv3/hce.shared-config/semanticReleaseConfigDotnet"
/* Caveat: semantic-release will version and release all specified projects under the same Git tags and GitHub releases.
* To version and release them separately, use [https://github.com/pmowrer/semantic-release-monorepo](semantic-release-monorepo).
*/
/* `prepareCmd` will contain command lines to publish
* both Library and Sample to your GitHub release.
* Their `TargetFrameworks` and `RuntimeIdentifiers`
* properties will be evaluated and a command line
* will be added for each unique combination,
* _regardless of compatibility and intended combinations_.
*/
const projectsToPublish = [
"./Library/Library.csproj",
"./Sample/Sample.csproj"
];
/*
* `prepareCmd` will also contain `dotnet pack` and
* `dotnet nuget sign` commands to pack Library to a nupkg.
* `publishCmd` will contain `dotnet nuget push` commands
* to push Library to Nuget.org and GitHub Package Registry.
*/
const projectsToPackAndPush = ["./Library/Library.csproj"];
// runs getConfig and exports its return value
export default getConfig(projectsToPublish, projectsToPackAndPush)
```
###### `extends` key in a javascript config file
Using `extends` is NOT recommended, but I won't stop you.
Your projects' paths must be assigned to environment variables. See [Dotnet Config](#dotnet-config).
```js
// releaserc.config.js (if {"type": "module"} in package.json)
export default {
extends: ["@halospv3/hce.shared-config"]
}
```
```js
// releaserc.config.js (if {"type": "commonjs"} in package.json)
module.exports = {
extends: ["@halospv3/hce.shared-config"]
}
```
###### `release` key in package.json
```json
// package.json
// `npm install --save-dev cross-env`
{
"scripts":{
"release":"cross-env PROJECTS_TO_PUBLISH=\"./Library/Library.csproj;./Sample/Sample.csproj\" semantic-release"
},
"release": {
"extends": ["@halospv3/hce.shared-config/semanticReleaseConfigDotnet"]
}
}
```
---
**Notable Plugin Properties**
- [`-release/commit-analyzer`](https://github.com/semantic-release/commit-analyzer#options)
- preset (set to `conventionalcommits`)
- parserOpts
- releaseRules
- [`-release/release-notes-generator`](https://github.com/semantic-release/release-notes-generator#options)
- preset (set to `conventionalcommits`)
- parserOpts
- writerOpts
- [`-release/changelog`](https://github.com/semantic-release/changelog#options)
- changelogFile (default: `'CHANGELOG.md'`)
- [`-release/git`](https://github.com/semantic-release/git#options)
- assets (default: `['README.md', 'CHANGELOG.md', 'package.json', 'package-lock.json', 'npm-shrinkwrap.json']`)
- `-release/exec`
- prepareCmd
- [`-release/github`](https://github.com/semantic-release/github#options)
- assets
- draftRelease (default: false)
### 3. Set Up CommitLint
```json
// package.json
{
"commitlint": {
"extends": ["@halospv3/hce.shared-config/commitlintConfig"]
}
}
```
or
```ts
/* eslint-disable import/no-default-export */
import commitlintConfig from '@halospv3/hce.shared-config/commitlintConfig';
export default commitlintConfig;
```
Then...
```sh
npx husky
npx husky add .husky/commit-msg 'npx --no -- commitlint --edit ${1}'
```
### 4. (dotnet) Add/Edit Directory.Build.props
```xml
<Project>
<Import Project="$(HCESharedDir)/dotnet/HCE.Shared.targets"/>
<PropertyGroup>
<RepoRoot Condition="'$(RepoRoot)' == ''">$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), '.git/index'))</RepoRoot>
<HCESharedDir Condition="'$(HCESharedDir)' == ''">$(RepoRoot)node_modules/@halospv3/hce.shared-config/</HCESharedDir>
<!--<GitVersion_Path Condition="'$(GitVersion_Path)' == ''">Path/To/Your/GitVersion.yml</GitVersion_Path>-->
</PropertyGroup>
</Project>
```
These may evaluate to the following:
| Property | Evaluated Value|
| ------------ | -------------- |
|`RepoRootDir` | `c:\Repos\HaloSPV3\HCE.Shared\` |
|`HCESharedDir`| `c:\Repos\HaloSPV3\HCE.Shared\node_modules\\hce.shared-config\` |
#### CI/CD-Only Properties
> Note: Already included when importing HCE.Shared.targets
> If you don't import HCE.Shared.targets, you may import HCE.Shared.CI.props or define your own conditional property group.
If you want properties set only in a CI/CD environment (e.g. a GitHub workflow), add the following
conditional property group to the props file:
```xml, diff
<Project>
<PropertyGroup>
...
</PropertyGroup>
<PropertyGroup Condition=" '$(CI)' == 'true' ">
<Configuration>Release</Configuration>
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
<Deterministic>true</Deterministic>
</PropertyGroup>
</Project>
```
> Any properties added to this conditional property group will only be evaluated when `$(CI)` is
> defined either as a property or as an environment variable. This is most useful for properties
> such as `ContinuousIntegrationBuild`.
#### GitVersion
By default, GitVersion will search only the "current directory" for `GitVersion.yml`. GitVersion has
a lesser-known CLI argument, "Path" which allows users to specify the path to `GitVersion.yml`. The
NuGet package `GitVersion.MSBuild` exposes this as the read-write property `$(GitVersion_Path)`.
If you're satisfied by [dotnet/GitVersion.yml](dotnet/GitVersion.yml), you can configure GitVersion
to use this config file. GitVersion does not have 'extend' functionality typical of Node.js
packages.
You can...
...define it yourself
```xml
<Project>
<PropertyGroup>
<GitVersion_Path>$(ProjectRootDir)/node_modules//hce.shared-config/dotnet/GitVersion.yml</GitVersion_Path>
</PropertyGroup>
</Project>
```
...import HCE.Shared.props
```xml
<Project>
<Import Project="$(HCESharedDir)/dotnet/HCE.Shared.props">
</Project>
```
...import HCE.Shared.Targets (which imports HCE.Shared.props)
```xml
<Project>
<Import Project="$(HCESharedDir)/dotnet/HCE.Shared.props">
</Project>
```
## Tips
### Need your VersionInfo before the actual release?
If you want to use this information in other Semantic Release steps, you'll need
`semantic-release-export-data`.
Run the following to preview the version:
```sh
npx semantic-release --dry-run --plugins "@semantic-release/commit-analyzer,semantic-release-export-data"
```
If the first plugin doesn't run into any issues and infers a version bump from unreleased commits,
it will print the next version to the console. The
[second plugin](https://github.com/felipecrs/semantic-release-export-data#readme) will export the
next version and other information as [GitHub Action Step outputs](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#example-using-output-as-url).
### Don't intend to publish a Node package?
Add the following to `package.json`:
```json
{
"private": true,
}
```
## WIP
### Reusable, configurable GitHub workflows
See callable workflows such as [dotnet-ci](./.github/workflows/dotnet-ci.yml)
```yml
jobs:
release:
steps:
- uses: actions/checkout
- name: dotnet build/publish; copy release artifacts to './publish/'
uses: ./node_modules/@halospv3/hce.shared/dotnet/.github/workflows/dotnet-release.yml
with:
projects:
- src/lib/lib.csproj
- src/lib-sample/sample.csproj
```