This is a monorepo containing GitHub Actions by Extenda Retail. These actions provide reusable logic for the fundamental parts of our CI/CD pipelines.
The following actions are available
- cloud-deploy
cloud-run- commitlint
- component-tests
- conventional-release
- conventional-version
- dataflow-template-build
docker- dataflow-deploy
- customer-config
- gcp-secret-manager
- iam
- iam-test-token
- identity-token
- jira-release
- jira-releasenotes
kubernetes- maven
- nexus-auth-npm
- opa-policy-test
- pact-broker
- pact-can-i-deploy
- pact-publish
- pact-tag-version
- repository-dispatch
rs-create-installerpkgrs-permission-converter- setup-gcloud
- setup-git
- setup-msbuild
- setup-nuget-sources
- setup-terraform
slack-message- slack-notify
- sonar-scanner
- status-check
styra-das-deploystyra-das-test- terraform-plan-comment
test-podtxengine-deploy
The following workflows demonstrates the high-level usage of many of our actions.
This workflow demonstrates how a Maven project can be built using two jobs.
- Every commit triggers the
test
job- Run unit tests
- Scan with Sonar
- Every successful commit on
master
triggers the release job- Bump the version and create a release
- Deploy to Nexus without running tests
name: Commit
on: push
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: actions/setup-java@v3
with:
distribution: temurin
java-version: 17
cache: maven
- name: Run tests
uses: extenda/actions/maven@v0
with:
service-account-key: ${{ secrets.SECRET_AUTH }}
args: verify
- name: Scan with SonarCloud
uses: extenda/actions/sonar-scanner@v0
with:
sonar-host: https://sonarcloud.io
service-account-key: ${{ secrets.SECRET_AUTH }}
release:
runs-on: ubuntu-latest
needs: test
if: github.ref == 'refs/heads/master'
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Create release
uses: extenda/actions/conventional-release@v0
id: release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- uses: actions/setup-java@v3
with:
distribution: temurin
java-version: 17
cache: maven
- name: Build release
uses: extenda/actions/maven@v0
with:
args: deploy -DskipTests
service-account-key: ${{ secrets.SECRET_AUTH }}
version: ${{ steps.release.outputs.version }}
This workflow demonstrates how a .NET Core project can be built using two jobs.
- Every commit triggers the
test
job- Build the project
- Run unit tests
- Scan with Sonar
- Every successful commit on
master
triggers the release job- Bump the version and create a release
- Deploy the NuGet package to Nexus
- Build a Docker image and push it to Amazon ECR
name: Commit
on: push
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: extenda/actions/gcp-secret-manager@v0
with:
service-account-key: ${{ secrets.SECRET_AUTH }}
secrets: |
NEXUS_PASSWORD: nexus-password
NEXUS_USERNAME: nexus-username
NUGET_API_KEY: nuget-api-key
- uses: extenda/actions/conventional-version@v0
id: semver
with:
version-suffix: -${{ github.sha }}
- name: Setup .NET Core 2.1
uses: actions/setup-dotnet@v1
with:
dotnet-version: 2.1.607
- name: Setup NuGet
uses: NuGet/[email protected]
with:
nuget-version: latest
- name: Setup NuGet sources
uses: extenda/actions/setup-nuget-sources@v0
with:
config-file: NuGet.Config
sources: |
[{
"name": "nuget.org",
"source": "https://api.nuget.org/v3/index.json"
},
{
"name": "Extenda",
"source": "https://repo.extendaretail.com/repository/nuget-group/",
"username": "${{ env.NEXUS_USERNAME }}",
"password": "${{ env.NEXUS_PASSWORD }}",
"apikey": "${{ env.NUGET_API_KEY }}"
}]
- name: Begin Sonar Scanner
uses: extenda/actions/sonar-scanner@v0
with:
sonar-host: https://sonar.extenda.io
sonar-scanner: dotnet
main-branch: develop
service-account-key: ${{ secrets.SECRET_AUTH }}
- name: Build
run: |
dotnet build --configuration Release \
/p:Version=${{ steps.semver.outputs.version }}
- name: Run tests
run: |
dotnet test --results-directory "./testresults" -l trx -c Release \
/p:CollectCoverage=true \
/p:CoverletOutputFormat=opencover \
--verbosity minimal
- name: Analyze with Sonar
uses: extenda/actions/sonar-scanner@v0
with:
sonar-host: https://sonar.extenda.io
sonar-scanner: dotnet
main-branch: develop
service-account-key: ${{ secrets.SECRET_AUTH }}
release:
runs-on: ubuntu-latest
needs: test
if: github.ref == 'refs/heads/master'
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: extenda/actions/gcp-secret-manager@v0
with:
service-account-key: ${{ secrets.SECRET_AUTH }}
secrets: |
NEXUS_PASSWORD: nexus-password
NEXUS_USERNAME: nexus-username
NUGET_API_KEY: nuget-api-key
AWS_ACCESS_KEY_ID: aws-access-key-id
AWS_SECRET_ACCESS_KEY: aws-secret-access-key
- uses: extenda/actions/conventional-version@v0
id: semver
with:
version-suffix: -${{ github.sha }}
- name: Create a release
uses: extenda/actions/conventional-release@v0
id: release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Setup .NET Core 2.1
uses: actions/setup-dotnet@v1
with:
dotnet-version: 2.1.607
- name: Setup NuGet
uses: NuGet/[email protected]
with:
nuget-version: latest
- name: Setup NuGet sources
uses: extenda/actions/setup-nuget-sources@v0
with:
config-file: NuGet.Config
sources: |
[{
"name": "nuget.org",
"source": "https://api.nuget.org/v3/index.json"
},
{
"name": "Extenda",
"source": "https://repo.extendaretail.com/repository/nuget-group/",
"username": "${{ env.NEXUS_USERNAME }}",
"password": "${{ env.NEXUS_PASSWORD }}",
"apikey": "${{ env.NUGET_API_KEY }}"
}]
- name: Build
run: dotnet build --configuration Release /p:Version=${{ steps.release.outputs.version }}
- name: Publish
run: |
dotnet publish MyExample.csproj \
--configuration Release \
/p:Version=${{ steps.semver.outputs.version }}
- name: Docker build and push
uses: extenda/actions/docker@v0
with:
image: extenda/my-example
tag: latest,${{ steps.release.outputs.version }}
This workflow demonstrates how a Node project can be built using two jobs.
- Every commit triggers the
test
job- Run
eslint
- Run unit tests
- Build the project
- Scan with Sonar
- Run
- Every successful commit on
master
triggers the release job- Bump the version and create a release
- Build the released version
- Build a Docker image and push it to GCR
name: Commit
on: push
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: NPM install
run: npm ci
- name: Lint javascript
run: |
npm run lint:js -- \
--format junit \
--output-file test-results/eslint/TEST-eslint.xml
- name: Unit tests
run: npm test -- --ci --coverage
- name: Build
run: npm run build
- name: SonarCloud Scan
uses: extenda/actions/sonar-scanner@v0
with:
sonar-host: https://sonarcloud.io
service-account-key: ${{ secrets.SECRET_AUTH }}
release:
if: github.ref == 'refs/heads/master'
runs-on: ubuntu-latest
needs: test
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Create release
uses: extenda/actions/conventional-release@v0
id: release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: NPM install
run: npm ci
- name: Build
run: |
npm version ${{ steps.release.outputs.version }} --no-git-tag-version
npm run build
- uses: extenda/actions/setup-gcloud@v0
id: gcloud
with:
service-account-key: ${{ secrets.GCLOUD_AUTH }}
- name: Publish Docker image
run: |
gcloud auth configure-docker
IMAGE=gcr.io/${{ steps.gcloud.outputs.project-id }}/my-example:v${{ steps.release.outputs.version }}
docker build -t $IMAGE .
docker push $IMAGE
The repository is a monorepo consisting of multiple packages. There are some dependencies between packages. Primarily
- All actions depend on common functions from
utils
- Cross-cutting actions like
sonar-scanner
depends on other actions
Javascript actions are compiled into a single javascript files using @zeit/ncc
to avoid committing node_modules
into source control. This is required because GitHub Actions does not run npm install
before running actions.
Development tools needed are:
- Latest Node 20 LTS release
- Docker
- Pre-commit
Developers should use pre-commit on this repository to validate file formatting and commit messages on every commit. After pre-commit has been installed on your system, activate on the repository.
$ pre-commit install -t pre-commit -t commit-msg
Use the NPM scripts in the root package.json
to install and build the complete project.
$ npm install --no-bin-links
Runs npm install
on all Javascript packages. Prefer npm ci
on first install or to reinstall local dependencies.
$ npm run lint:js
Runs eslint
on all Javascript files everywhere.
$ npm test
Runs Jest everywhere.
If tests fails due to short-sha being unexpected length, consider configuring the default on your repository
$ git config core.abbrev 7
$ npm run build:docker
Runs npm run build
on all modules. This recompiles the package into its dist
directory. The project
builds in a Docker container to ensure strictly identical output across platforms.
- Remember to always run
npm run build
before committing changes to packages. Failing to do so will not pass CI/CD checks - If you've run
npm run build
and your build still fails, trynpm ci && npm run build
- While developing, run
npm test -- -o
to only run tests on changed files - Do not add dependencies to the root package unless you are making global changes, for example to the build process
A GitHub Actions pipeline will run tests on every commit.
Every successful commit to master
will automatically:
- Be tagged to a semantic release version
- Update the
v{MAJOR}
branch to point to the new release
The repository is versioned using a single semantic version. This means that all packages are always released and map to the same version.
To follow GitHub Actions version conventions
actions will always be accessible from a v{MAJOR}
branch that points to the last release for that major version.
For example v1
will point to v1.1.2
after it has been released.
g The project is versioned with Conventional Commits conventions.
- Make sure your commits to
master
always follow conventional commits - Always use squash and merge when merging to
master
This repository is released under the MIT license.