This is a monorepo containing GitHub Actions by Extenda Retail. These actions provides reusable logic for the fundamental parts of our CI/CD pipelines.
The following actions are available
- cloud-run
- commitlint
- conventional-release
- conventional-version
- dataflow-template-build
- docker
- dataflow-deploy
- gcp-secret-manager
- iam
- iam-test-token
- jira-release
- jira-releasenotes
- kubernetes
- maven
- repository-dispatch
- rs-create-installerpkg
- rs-permission-converter
- setup-gcloud
- setup-git
- setup-msbuild
- setup-nuget-sources
- setup-terraform
- slack-message
- sonar-scanner
- status-check
- styra-das-deploy
- styra-das-test
- terraform-plan-comment
- test-pod
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@v1
- uses: extenda/actions/gcp-secret-manager@v0
with:
service-account-key: ${{ secrets.SECRET_AUTH }}
secrets: |
NEXUS_PASSWORD: nexus-password
NEXUS_USERNAME: nexus-username
- uses: actions/cache@v1
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}-maven-
- uses: actions/setup-java@v1
with:
java-version: 11
- name: Run tests
uses: extenda/actions/maven@v0
with:
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@v1
- uses: extenda/actions/gcp-secret-manager@v0
with:
service-account-key: ${{ secrets.SECRET_AUTH }}
secrets: |
NEXUS_PASSWORD: nexus-password
NEXUS_USERNAME: nexus-username
- name: Create release
uses: extenda/actions/conventional-release@v0
id: release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- uses: actions/cache@v1
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}-maven-
- uses: actions/setup-java@v1
with:
java-version: 11
- name: Build release
uses: extenda/actions/maven@v0
with:
args: deploy -DskipTests
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@v1
- 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@v1
- 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@v1
- uses: extenda/actions/gcp-secret-manager@v0
with:
service-account-key: ${{ secrets.SECRET_AUTH }}
secrets: |
SONAR_TOKEN: sonarcloud-token
- 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@v1
- 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 12 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.
$ npm run lint:js
Runs eslint
on all Javascript files everywhere.
$ npm test
Runs Jest everywhere.
$ npm run build
Runs npm run build
on all Javascript projects. This recompiles the package into its dist
directory.
$ npm run build:docker
Same as npm run build
, but builds the project 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.
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.