Skip to content

Latest commit

 

History

History
348 lines (264 loc) · 17.1 KB

Workflows.md

File metadata and controls

348 lines (264 loc) · 17.1 KB

Reusable GitHub Actions workflows

These workflows can be invoked from a step from any other repository's workflow. The utilize our composite actions.

General notes

  • In addition to the below short explanations and samples, check out the inline documentation of the workflow you want to use, especially its parameters. These examples don't necessarily utilize all parameters.
  • Workflows with a cancel-workflow-on-failure parameter will by default cancel all jobs in the workflow run when the given reusable workflow fails (to save computing resources). You can disable this by setting the parameter to "false".
  • To add the workflows to a project create a folder in the root of the repository that will call them, e.g. .github/workflows/build.yml and/or .github/workflows/publish.yml. Things to keep in mind:
    • If you have multiple projects in the repository or if the project you want to build is in a subfolder, then add a solution to the root of the repository that references all projects you want to build.
    • References to projects (<ProjectReference> elements) not in the repository won't work, these need to be changed to package references (<PackageReference> elements). Make the conditional based on $(NuGetBuild). See the Helpful Extensions project file for an example. References to projects in the repository will work and those projects, if configured with the proper metadata, will be published together, with dependencies retained among the packages too.
    • Projects building client-side assets with Gulp Extensions won't work during such builds. Until we fix this, you have to commit the wwwroot folder to the repository and add the same conditional to the Gulp and NPM Import elements too (example).

Build and Test Orchard Core solution workflow

Meant to be used with Orchard Core solutions; this workflow checks out the code, installs dependencies, builds the solution, runs unit and UI tests (with Lombiq UI Testing Toolbox for Orchard Core), and publishes artifacts as well as a test report.

For an example of this, see below and the workflow of Lombiq's Open-Source Orchard Core Extensions.

name: Build and Test

# Runs for PRs opened for any branch, and pushes to the dev branch.
on:
  pull_request:
  push:
    branches:
      - dev

jobs:
  build-and-test:
    name: Build and Test
    uses: Lombiq/GitHub-Actions/.github/workflows/build-and-test-orchard-core.yml@dev
    with:
      timeout-minutes: 60

Build and Test .NET solution workflow

Builds a .NET solution (or project) with static code analysis, and runs tests with a test report like build-and-test-orchard-core. You can use it along the lines of the following:

name: Build and Test

# Runs for PRs opened for any branch, and pushes to the dev branch.
on:
  pull_request:
  push:
    branches:
      - dev

jobs:
  build-and-test:
    name: Build and Test
    uses: Lombiq/GitHub-Actions/.github/workflows/build-and-test-dotnet.yml@dev
    with:
      machine-types: "['ubuntu-22.04', 'windows-2022']"
      timeout-minutes: 10

Spelling workflow

Checks for spelling mistakes in a repository using the Check Spelling GitHub Action, proxied by the spelling action in this repository, which has its own documentation describing the configuration options and contribution guidelines. This documentation is also displayed automatically in every spell checking report of a pull request.

You can use already existing configuration files by setting the spell-check-this parameter to another existing repository. This parameter is needed even if you want to update our dictionary in a custom branch of project consuming this workflow; changing just the workflow's branch from dev to your branch won't take any effect, you can leave it as it is.

Example check-spelling.yml:

name: Spelling

on:
  pull_request:
  push:
    branches:
      - dev

jobs:
  spelling:
    name: Spelling
    uses: Lombiq/GitHub-Actions/.github/workflows/spelling.yml@dev
    with:
      # Add this parameter if you want to use dictionary files from Lombiq's or any other repository outside "cspell". The order of entries matters, so the most specific ones, like your own should come before more generic ones, like "cspell".
      dictionary-source-prefixes: >
        {
          "lombiq": "https://raw.githubusercontent.com/Lombiq/GitHub-Actions/dev/.github/actions/spelling/",
          "cspell": "https://raw.githubusercontent.com/check-spelling/cspell-dicts/v20220816/dictionaries/"
        }
      # Use this parameter to list the external dictionary files to use, but beware that check-spelling only accepts flat lists of words (so, for example patterns.txt can't be referenced like this). The order doesn't matter, but sorting it alphabetically makes it easier to maintain.
      extra-dictionaries: |
        cspell:csharp/csharp.txt
        lombiq:allow.txt
        lombiq:expect.txt
      # This is only needed if you want to use any other dictionaries than the ones in this project.
      spell-check-this: Lombiq/GitHub-Actions@your-custom-branch

NuGet publish workflow

Builds the project with the .NET SDK and publishes it as a NuGet package to the configured NuGet feed. Example publish.yml:

name: Publish to NuGet

on:
  push:
    tags:
      - v*

jobs:
  publish-nuget:
    uses: Lombiq/GitHub-Actions/.github/workflows/publish-nuget.yml@dev
    secrets:
      apikey: ${{ secrets.DEFAULT_NUGET_PUBLISH_API_KEY }}

The publish.yml workflow is triggered on a tag pushed to any branch with the prefix v and should contain a valid version number, e.g. v1.0.1, which will be extracted and used to version the NuGet packages produced.

There is no configuration required for automated Orchard Core extension manifest versioning, all of the Manifest.cs files are looked up, and the existing Version properties are updated automatically inside the Module or Theme definition with the version pushed. Note that the Version property should be present and leave the version number on the default value (0.0.1). This is because we don't actually need to keep manifest version changes in the code.

It takes one non-optional secret parameter, apikey, the organization API key for pushing to NuGet, and two optional parameters, source and verbosity. E.g.:

jobs:
  publish-nuget:
    uses: Lombiq/GitHub-Actions/.github/workflows/publish-nuget.yml@dev
    with:
      source: https://nuget.cloudsmith.io/lombiq/open-source-orchard-core-extensions/v3/index.json
      verbosity: detailed
    secrets:
      apikey: ${{ secrets.CLOUDSMITH_NUGET_PUBLISH_API_KEY }}

When source is not provided, it assumes a default value of pushing to the Lombiq NuGet feed.

Valid values for verbosity are those defined by MSBuild. The default value is minimal.

Submodule validate workflow

Validates pull requests in submodule repositories for various criteria:

  • Adds a Jira-style issue code (e.g. PROJ-123) to the pull request's title, and a link to the Jira issue in the body if it's not there yet.
  • Checks if a pull request exists in the parent repository.

Example validate-pull-request.yml:

name: Validate Pull Request

on:
  pull_request:

jobs:
  validate-pull-request:
    uses: Lombiq/GitHub-Actions/.github/workflows/validate-submodule-pull-request.yml@dev
    with:
      repository: Lombiq/Hastlayer-SDK

If this is for a submodule of Lombiq's Open-Source Orchard Core Extensions, the repo input can be omitted, because the above is its default value. Otherwise, use your parent repository's address in the {owner}/{repo_name} format.

Refer to Github Actions reusable workflows for more information.

Deploy to Azure App Service workflow

This workflow builds and publishes a .NET web project and then deploys the app to Azure App Service. The workflow also supports Ready to Run compilation. Release annotations are added to the corresponding Azure Application Insights resource. Example deploy-to-azure-app-service.yml:

name: Deploy to Azure App Service

on:
  workflow_dispatch:

jobs:
  deploy-to-azure-app-service:
    name: Deploy to Azure App Service
    uses: Lombiq/GitHub-Actions/.github/workflows/deploy-to-azure-app-service.yml@dev
    with:
      timeout-minutes: 60
      app-name: AppName
      resource-group-name: ResourceGroupName
      slot-name: Staging
      url: https://www.myapp.com
      runtime: win-x86
      self-contained: true
      ready-to-run: true
      application-insights-resource-id: "Azure resource ID of the corresponding AI resource"
    secrets:
      AZURE_APP_SERVICE_DEPLOYMENT_SERVICE_PRINCIPAL: ${{ secrets.AZURE_APP_SERVICE_DEPLOYMENT_SERVICE_PRINCIPAL }}
      AZURE_APP_SERVICE_PUBLISH_PROFILE: ${{ secrets.AZURE_APP_SERVICE_PUBLISH_PROFILE }}

If the app uses the Lombiq.Hosting.BuildVersionDisplay module, then the workflow plays along with it: The module will display a link to the run.

Validate Pull Request workflow

Validates pull requests for various criteria:

  • Labels and comments on pull requests with merge conflicts.
  • Adds a Jira-style issue code (e.g. PROJ-123) to the pull request's title, and a link to the Jira issue in the body if it's not there yet.
name: Validate Pull Request
on:
  push:
  pull_request:
    types: [opened, synchronize]

jobs:
  validate-pull-request:
    uses: Lombiq/GitHub-Actions/.github/workflows/validate-pull-request.yml@dev

Jira issue creation for community activities workflow

Creates Jira issues for community activities happening on GitHub, like issues, discussions, and pull requests being opened. Pull requests are only taken into account if they're not already related to a Jira issue (by starting their title with a Jira issue key).

Set up secrets for the JIRA_* parameters as explained here. You may use secret names without the DEFAULT_* prefix, but that's our recommendation for organization-level secrets, so you have defaults but can override them on a per-repository basis.

The secrets with the *_JIRA_ISSUE_DESCRIPTION suffix should contain templates for the Jira issues to be created, using the internal markup format of Jira (not Markdown). Example for one for ISSUE_JIRA_ISSUE_DESCRIPTION:

h1. Summary
See the linked GitHub issue, including all the comments.

h1. Checklist
* Assign yourself to the referenced GitHub issue.
* [Issue completion checklist|https://example.com/checklist]

All three templates are optional and if not provided, defaults will be used.

name: Create Jira issues for community activities

on:
  discussion:
    types: [created]
  issues:
    types: [opened]
  pull_request:
    types: [opened]

jobs:
  create-jira-issues-for-community-activities:
    uses: Lombiq/GitHub-Actions/.github/workflows/create-jira-issues-for-community-activities.yml@dev
    secrets:
      JIRA_BASE_URL: ${{ secrets.DEFAULT_JIRA_BASE_URL }}
      JIRA_USER_EMAIL: ${{ secrets.DEFAULT_JIRA_USER_EMAIL }}
      JIRA_API_TOKEN: ${{ secrets.DEFAULT_JIRA_API_TOKEN }}
      JIRA_PROJECT_KEY: ${{ secrets.DEFAULT_JIRA_PROJECT_KEY }}
      DISCUSSION_JIRA_ISSUE_DESCRIPTION: ${{ secrets.DEFAULT_DISCUSSION_JIRA_ISSUE_DESCRIPTION }}
      ISSUE_JIRA_ISSUE_DESCRIPTION: ${{ secrets.DEFAULT_ISSUE_JIRA_ISSUE_DESCRIPTION }}
      PULL_REQUEST_JIRA_ISSUE_DESCRIPTION: ${{ secrets.DEFAULT_PULL_REQUEST_JIRA_ISSUE_DESCRIPTION }}
    with:
      issue-component: Lombiq.MyProject

Reset Azure Environment workflow

This workflow resets an Azure Environment, by replacing the Orchard Core Media Library and the Database with the ones from a given source slot. Example reset-azure-environment.yml:

name: Reset Azure Environment

on:
  workflow_dispatch:

jobs:
  reset-azure-environment:
    name: Reset Azure Environment
    uses: Lombiq/GitHub-Actions/.github/workflows/reset-azure-environment.yml@dev
    with:
      timeout-minutes: 60
      app-name: AppName
      resource-group-name: ResourceGroupName
      database-connection-string-name: Database__ConnectionString
      master-database-connection-string-name: Database__ConnectionString-master
      storage-connection-string-name: Storage_ConnectionString
    secrets:
      AZURE_APP_SERVICE_RESET_SERVICE_PRINCIPAL: ${{ secrets.AZURE_APP_RESET_ENVIRONMENT_SERVICE_PRINCIPAL }}

Swap Azure Web App Slots workflow

This workflow swaps two Azure Web App Slots associated with an Azure Web App. Release annotations are added to the corresponding Azure Application Insights resource. Example swap-azure-web-app-slots.yml:

name: Swap Azure Web App Slots

on:
  workflow_dispatch:

jobs:
  swap-azure-web-app-slots:
    name: Swap Azure Web App Slots
    uses: Lombiq/GitHub-Actions/.github/workflows/swap-azure-web-app-slots.yml@dev
    with:
      timeout-minutes: 10
      app-name: AppName
      resource-group-name: ResourceGroupName
      application-insights-resource-id: "Azure resource ID of the corresponding AI resource"
    secrets:
      AZURE_APP_SERVICE_SWAP_SERVICE_PRINCIPAL: ${{ secrets.AZURE_APP_SWAP_WEB_APP_SLOTS_SERVICE_PRINCIPAL }}

To restrict who can run the swap workflow, we recommend putting it into its own repository. GitHub environments would be better, because they not only provide a nice display of what's currently deployed where, but allow secrets specific to environments like staging/production, and also can have required reviewers (i.e. not everyone is able to run a swap who has write access to the repository). However, this latter one is only available under the Enterprise plan. (Branch protection rules are not a suitable substitute.)

Post Pull Request Checks Automation

Various automation that should be run after all other checks succeeded for a pull request. Currently does the following:

  • Merges the current pull request if the "merge-and-resolve-jira-issue-if-checks-succeed" or "merge-if-checks-succeed" label is present. With prerequisite jobs you can execute this only if all others jobs have succeeded. Unlike GitHub's auto-merge, this works without branch protection rules.
  • Resolves the Jira issue corresponding to the pull request if the "resolve-jira-issue-if-checks-succeed" or "merge-and-resolve-jira-issue-if-checks-succeed" label is present, or sets the issue to Done if the "done-jira-issue-if-checks-succeed" label is.

See an example of how you can utilize this workflow, together with jobs that do other checks below. For configuring the JIRA_* secrets see the documentation of create-jira-issues-for-community-activities above, and for details on MERGE_TOKEN check out the workflow's inline documentation.

name: Build and Test

on:
  pull_request:
  push:
    branches:
      - dev

jobs:
  build-and-test:
    name: Build and Test
    uses: Lombiq/GitHub-Actions/.github/workflows/build-and-test-orchard-core.yml@dev

  spelling:
    name: Spelling
    uses: Lombiq/GitHub-Actions/.github/workflows/spelling.yml@dev

  post-pull-request-checks-automation:
    name: Post Pull Request Checks Automation
    needs: [build-and-test, spelling]
    if: github.event.pull_request != ''
    uses: Lombiq/GitHub-Actions/.github/workflows/post-pull-request-checks-automation.yml@dev
    secrets:
      JIRA_BASE_URL: ${{ secrets.DEFAULT_JIRA_BASE_URL }}
      JIRA_USER_EMAIL: ${{ secrets.DEFAULT_JIRA_USER_EMAIL }}
      JIRA_API_TOKEN: ${{ secrets.DEFAULT_JIRA_API_TOKEN }}
      MERGE_TOKEN: ${{ secrets.DEFAULT_MERGE_TOKEN }}