Skip to content

Commit d52e80c

Browse files
committed
Add GitHub Actions
Add multiple GitHub Actions workflows. 1. CI tests * Performs linting on Go, Markdown, and YAML files. * Build's Docker image if Go code or Dockerfile have changed. 2. Container image * Builds container images and uploads them to registries when a Git tag is created, or a new release is created.
1 parent 8a9a787 commit d52e80c

File tree

6 files changed

+303
-21
lines changed

6 files changed

+303
-21
lines changed

.dockerignore

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
build.sh
2-
Dockerfile
3-
LICENSE
4-
README.md
51
.DS_Store
62
.git/
3+
.github/
74
.gitignore
85
.vscode/
6+
CHANGELOG.md
7+
Dockerfile
8+
LICENSE
9+
manifests/
10+
README.md

.github/workflows/ci.yaml

+146
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
---
2+
name: Continuous integration tasks
3+
on: # yamllint disable-line rule:truthy
4+
pull_request:
5+
branches:
6+
- master
7+
push:
8+
branches:
9+
- master
10+
workflow_dispatch: # Allow manual triggering of the workflow
11+
12+
jobs:
13+
golang-ci:
14+
name: Lint Go code using golangci-lint
15+
runs-on: ubuntu-latest
16+
17+
permissions:
18+
# Required: allow read access to the content for analysis.
19+
contents: read
20+
# Allow read access to pull request. Use with `only-new-issues` # option
21+
pull-requests: read
22+
# Allow write access to checks to allow the action to annotate code in the
23+
# PR
24+
checks: write
25+
26+
steps:
27+
- name: Checkout code
28+
uses: actions/checkout@v4
29+
30+
- name: Run golangci-lint
31+
uses: golangci/golangci-lint-action@v6
32+
with:
33+
only-new-issues: true
34+
problem-matchers: true
35+
36+
paths-filter:
37+
name: Check if Dockerfile or Go code has changed
38+
runs-on: ubuntu-latest
39+
outputs:
40+
modified: ${{ steps.filter.outputs.docker-or-gocode }}
41+
steps:
42+
- name: Checkout repository
43+
uses: actions/checkout@v4
44+
45+
- name: Check if Dockerfile oer Go code has changed
46+
uses: dorny/paths-filter@v3
47+
id: filter
48+
with:
49+
filters: |
50+
docker-or-gocode:
51+
- Dockerfile'
52+
- '*/**.go'
53+
54+
docker:
55+
name: Build multi-arch container image
56+
if: needs.paths-filter.outputs.modified == 'true'
57+
runs-on: ubuntu-latest
58+
# This job is dependent on the golang-ci job and paths-filter job.
59+
# It will only run if the golang-ci job is successful and if the
60+
# paths-filter job indicates that the Dockerfile or Go code have changed.
61+
needs:
62+
- golang-ci
63+
- paths-filter
64+
steps:
65+
- name: Set up QEMU
66+
uses: docker/setup-qemu-action@v3
67+
with:
68+
platforms: arm64,arm
69+
70+
- name: Set up Docker Buildx
71+
uses: docker/setup-buildx-action@v3
72+
73+
- name: Extract metadata (tags, labels) for Docker
74+
id: meta
75+
uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
76+
with:
77+
images: |
78+
blakec/external-mdns
79+
ghcr.io/${{ github.repository }}
80+
81+
- name: Build image and push to local image cache
82+
uses: docker/build-push-action@v6
83+
with:
84+
context: .
85+
file: ./Dockerfile
86+
platforms: >
87+
linux/amd64,linux/arm64,linux/arm/v7,linux/arm/v6,linux/arm/v5
88+
# Load the image into the local image cache instead of pushing it to
89+
# a registry. This is useful for testing the image locally.
90+
load: true
91+
tags: ${{ steps.meta.outputs.tags }}
92+
labels: ${{ steps.meta.outputs.labels }}
93+
94+
markdownlint:
95+
name: Lint markdown files
96+
runs-on: ubuntu-latest
97+
98+
steps:
99+
- name: Checkout code
100+
uses: actions/checkout@v4
101+
with:
102+
fetch-depth: 0
103+
104+
- uses: tj-actions/changed-files@v45
105+
id: changed-files
106+
with:
107+
files: '**/*.md'
108+
separator: ","
109+
110+
- name: Lint markdown files
111+
# This action will only run if there are changed files
112+
# It will use the output from the previous step to determine if there
113+
# are any changed files
114+
# If there are no changed files, it will not run
115+
# If there are changed files, it will run and lint them
116+
# The output of this step will be the list of changed files
117+
uses: DavidAnson/markdownlint-cli2-action@v19
118+
if: steps.changed-files.outputs.any_changed == 'true'
119+
with:
120+
globs: ${{ steps.changed-files.outputs.all_changed_files }}
121+
separator: ","
122+
123+
yamllint:
124+
name: Lint YAML files
125+
runs-on: ubuntu-latest
126+
127+
steps:
128+
- name: Checkout code
129+
uses: actions/checkout@v4
130+
with:
131+
fetch-depth: 0
132+
133+
- name: Check if YAML files have changed
134+
uses: dorny/paths-filter@v3
135+
id: changes
136+
with:
137+
filters: |
138+
yaml:
139+
- '**/*.yaml'
140+
- '**/*.yml'
141+
142+
- name: Lint YAML files
143+
if: steps.changes.outputs.yaml == 'true'
144+
uses: ibiqlik/action-yamllint@v3
145+
with:
146+
strict: true
+131
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
---
2+
name: Build and push container image to image registries
3+
on: # yamllint disable-line rule:truthy
4+
push:
5+
tags:
6+
- "v*.*.*"
7+
release:
8+
types:
9+
- published
10+
- released
11+
workflow_dispatch: # Allow manual triggering of the workflow
12+
inputs:
13+
push_to_docker_hub:
14+
description: 'Push image to Docker Hub'
15+
required: false
16+
default: false
17+
type: boolean
18+
19+
jobs:
20+
21+
push_to_registries:
22+
name: Push image to container registries
23+
runs-on: ubuntu-latest
24+
env:
25+
# The registries to push the image to
26+
DOCKER_REGISTRY: docker.io
27+
DOCKER_USERNAME: "${{ secrets.DOCKER_USERNAME }}"
28+
GITHUB_REGISTRY: ghcr.io
29+
# The name of the image to push
30+
IMAGE_NAME: external-mdns
31+
32+
permissions:
33+
# Permit generating an artifact attestation for the image
34+
attestations: write
35+
# Permits an action to list the commits
36+
contents: read
37+
# Fetch an OpenID Connect (OIDC) token
38+
id-token: write
39+
# Permit uploading and publishing packages on GitHub Packages.
40+
packages: write
41+
42+
steps:
43+
- name: Check out the repo
44+
uses: actions/checkout@v4
45+
46+
- name: Set up QEMU
47+
uses: docker/setup-qemu-action@v3
48+
with:
49+
platforms: arm64,arm
50+
51+
- name: Set up Docker Buildx
52+
uses: docker/setup-buildx-action@v3
53+
54+
- name: Extract metadata (tags, labels) for Docker
55+
id: meta
56+
uses: docker/metadata-action@906ecf0fc0a80f9110f79d9e6c04b1080f4a2621
57+
env:
58+
# Attach metadata annotations to both the image index and the manifest
59+
DOCKER_METADATA_ANNOTATIONS_LEVELS: index,manifest
60+
with:
61+
# yamllint disable rule:line-length
62+
images: |
63+
name=${{ env.DOCKER_REGISTRY }}/${{ env.DOCKER_USERNAME }}/${{ env.IMAGE_NAME }},enable=${{ github.event_name != 'workflow_dispatch' || (github.event_name == 'workflow_dispatch' && inputs.push_to_docker_hub == true) }}
64+
name=${{ env.GITHUB_REGISTRY }}/${{ github.repository }}
65+
# Disable generating the 'latest' tag on the image.
66+
# It will be conditionally tagged later in the workflow.
67+
flavor: |
68+
latest=false
69+
annotations: |
70+
# The date the image was created
71+
org.opencontainers.image.created={{date 'YYYY-MM-DDTHH:mm:ss.SSS[Z]'}}
72+
org.opencontainers.image.revision={{sha}}
73+
org.opencontainers.image.source=${{ github.event.repository.html_url }}
74+
org.opencontainers.image.url=${{ github.event.repository.html_url }}
75+
org.opencontainers.image.version={{tag}}
76+
tags: |
77+
# '{{version}}' results in a tag of '<major>.<minor>.<patch>'
78+
type=semver,pattern={{version}}
79+
type=semver,pattern={{major}}.{{minor}}
80+
81+
# Results in the image being tagged with same value as the Git tag
82+
# (e.g.,'v<major>.<minor>.<patch>')
83+
type=pep440,pattern={{raw}}
84+
85+
# set 'latest' tag on the image if the following conditions are met:
86+
# 1. The event is a push
87+
# 2. The base branch is the default branch
88+
# 3. The GitHub reference starts with 'refs/tags/v'
89+
# (i.e., the event is a tag release)
90+
type=raw,value=latest,enable=${{ github.event_name == 'push' && github.event.base_ref == format('refs/heads/{0}', github.event.repository.default_branch) && startsWith(github.ref, 'refs/tags/v') }}
91+
92+
# Tag the image with the commit SHA when manually triggered and is not
93+
# a tag release. This is useful for testing and debugging.
94+
type=sha,enable=${{ github.event_name == 'workflow_dispatch' && !startsWith(github.ref, 'ref/tags/v') }}
95+
# yamllint enable rule:line-length
96+
97+
- name: Login to Docker Hub
98+
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
99+
if: github.event_name != 'workflow_dispatch' || inputs.push_to_docker_hub == true # yamllint disable-line rule:line-length
100+
with:
101+
registry: ${{ env.DOCKER_REGISTRY }}
102+
username: ${{ secrets.DOCKER_USERNAME }}
103+
password: ${{ secrets.DOCKER_PASSWORD }}
104+
105+
- name: Login to GitHub Container registry
106+
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
107+
with:
108+
registry: ${{ env.GITHUB_REGISTRY }}
109+
username: ${{ github.actor }}
110+
password: ${{ secrets.GITHUB_TOKEN }}
111+
112+
- name: Build and push container image
113+
id: push
114+
uses: docker/build-push-action@v6
115+
with:
116+
context: .
117+
file: ./Dockerfile
118+
platforms: >
119+
linux/amd64,linux/arm64,linux/arm/v7,linux/arm/v6,linux/arm/v5
120+
push: ${{ github.event_name != 'pull_request' }}
121+
annotations: ${{ steps.meta.outputs.annotations }}
122+
# Use the same annotations as labels on the image
123+
labels: ${{ steps.meta.outputs.annotations }}
124+
tags: ${{ steps.meta.outputs.tags }}
125+
126+
- name: Generate artifact attestation
127+
uses: actions/attest-build-provenance@v2
128+
with:
129+
subject-name: ${{ env.GITHUB_REGISTRY }}/${{ github.repository }}
130+
subject-digest: ${{ steps.push.outputs.digest }}
131+
push-to-registry: true

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
<!-- markdownlint-disable-next-line MD041 -->
12
## 0.5.0 (September 27, 2023)
23

34
IMPROVEMENTS:

README.md

+17-15
Original file line numberDiff line numberDiff line change
@@ -27,21 +27,22 @@ advertised with a short name of `<hostname/service_name>.local`.
2727
### Additional control for Services
2828

2929
Service discovery is automatic, however, there are some scenarios where one may wish
30-
to directly control names used with a more general service i.e. the service might be
31-
in front of an Ingress Controller but the service you wish to use is not defined with
32-
an Ingress resource such as in the case of non http/https service with nginx.
30+
to directly control names used with a more general service i.e. the service might
31+
be in front of an Ingress Controller but the service you wish to use is not defined
32+
with an Ingress resource such as in the case of non http/https service with nginx.
3333

34-
Other scenarios include non Ingress types that publish a variety of services and act as
35-
an ingress but have configurations far more complex than can be expressed by an Ingress
36-
resource e.g. Istio.
34+
Other scenarios include non Ingress types that publish a variety of services and
35+
act as an ingress but have configurations far more complex than can be expressed
36+
by an Ingress resource e.g. Istio.
3737

38-
Additionally, one may wish to control in finer detail which services appear directly on
39-
.local MDNS advertisements without either moving services to the default namespace or
40-
enabling the global without-namespace flag.
38+
Additionally, one may wish to control in finer detail which services appear directly
39+
on .local MDNS advertisements without either moving services to the default namespace
40+
or enabling the global without-namespace flag.
4141

42-
In this case Service annotations are possible as follows - these annotations have no effect
43-
if applied to an Ingress resource.
44-
```
42+
In this case Service annotations are possible as follows - these annotations have
43+
no effect if applied to an Ingress resource.
44+
45+
```yaml
4546
apiVersion: v1
4647
kind: Service
4748
metadata:
@@ -55,13 +56,14 @@ spec:
5556
type: LoadBalancer
5657
...
5758
```
59+
5860
This example publishes the service using the name foo which will result in the names
5961
foo.foospace.local, foo-foospace.local and, because we have specified the additional
6062
annotation foo.local is also published (unnecessary if using the global option).
6163

62-
We urge you to test with the default behaviours for Services and Ingress before using these
63-
annotations as the automatic nature of external-mdns is good enough for most use cases.
64-
64+
We urge you to test with the default behaviours for Services and Ingress before
65+
using these annotations as the automatic nature of external-mdns is good enough
66+
for most use cases.
6567

6668
## Deploying External-mDNS
6769

main.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -252,10 +252,10 @@ func main() {
252252
switch src {
253253
case "ingress":
254254
ingressController := source.NewIngressWatcher(factory, namespace, notifyMdns)
255-
go ingressController.Run(stopper)
255+
go ingressController.Run(stopper) //nolint
256256
case "service":
257257
serviceController := source.NewServicesWatcher(factory, namespace, notifyMdns, publishInternal)
258-
go serviceController.Run(stopper)
258+
go serviceController.Run(stopper) //nolint
259259
}
260260
}
261261

0 commit comments

Comments
 (0)