Skip to content

Commit f314530

Browse files
committed
Refactor proxy Docker workflows for PR builds, releases, and fork compatibility
- add pull_request support for proxy image validation - add workflow_dispatch support for manual Docker runs on main or tags - make image naming fork-friendly via repository owner fallback - centralize image tag and version computation in a metadata step - skip DockerHub login and publishing for PR builds - build the image locally for Anchore/Grype scanning before publish - upload SARIF results only for non-PR runs, and only for workflow_dispatch on main - keep multi-arch image publishing for develop and release tags - skip SonarQube when SONAR_TOKEN is not configured - skip SonarQube for fork PRs because repository secrets are unavailable there - add a release workflow for creating and publishing tagged releases - pin and refresh GitHub Action SHAs This improves the proxy CI/CD setup by making PR validation work in forks, keeping publishing restricted to trusted runs, and adding a cleaner manual and release flow for versioned Docker images.
1 parent 3e38378 commit f314530

File tree

3 files changed

+186
-51
lines changed

3 files changed

+186
-51
lines changed

.github/release.yml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
changelog:
2+
categories:
3+
- title: 🎉 New features
4+
labels:
5+
- Feature
6+
- title: ⭐ Enhancements
7+
labels:
8+
- Enhancement
9+
- title: 🐞 Bug fixes
10+
labels:
11+
- Bug
12+
- title: 📝 Documentation
13+
labels:
14+
- Documentation
15+
- title: Other changes
16+
labels:
17+
- "*"

.github/workflows/proxy.yml

Lines changed: 104 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,99 +1,152 @@
1-
# This is a basic workflow to help you get started with Actions
2-
31
name: Docker Image
42

5-
# Controls when the action will run.
63
on:
74
# When a release is published
85
release:
96
types: [published]
107

11-
# Push excluding tags and workflow changes
8+
# Push excluding tags and Markdown-only changes
129
push:
1310
branches:
14-
- main
11+
- main
1512
tags-ignore:
1613
- '*.*'
1714
paths-ignore:
1815
- '**/*.md'
1916

17+
# Validate pull requests without publishing
18+
pull_request:
19+
branches:
20+
- main
21+
paths-ignore:
22+
- '**/*.md'
23+
24+
# Manual trigger
25+
workflow_dispatch:
26+
2027
permissions:
2128
contents: read
2229
security-events: write
2330

2431
concurrency:
25-
group: ${{ github.workflow }}-${{ github.ref }}
32+
group: ${{ github.workflow }}-${{ github.event.pull_request.head.sha || github.ref }}
2633
cancel-in-progress: true
2734

28-
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
35+
env:
36+
IMAGE_NAME: ${{ vars.DOCKERHUB_NAMESPACE || github.repository_owner }}/proxy
37+
PLATFORM: linux/amd64,linux/arm64
38+
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
39+
2940
jobs:
3041
image_proxy:
31-
32-
env:
33-
PLATFORM: linux/amd64,linux/aarch64
34-
42+
name: Build images
3543
runs-on: ubuntu-latest
3644

3745
steps:
38-
- name: Set tags
39-
id: set-tags
40-
run: |
41-
if [ -z "$TAG" ]; then
42-
echo "TAG=-t openremote/proxy:develop" >> $GITHUB_ENV
43-
echo "dockerImage=openremote/proxy:develop" >> $GITHUB_OUTPUT
44-
else
45-
echo "TAG=-t openremote/proxy:latest -t openremote/proxy:$TAG" >> $GITHUB_ENV
46-
echo "dockerImage=openremote/proxy:$TAG" >> $GITHUB_OUTPUT
47-
fi
48-
env:
49-
TAG: ${{ github.event.release.tag_name }}
46+
- name: Checkout
47+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
5048

51-
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
52-
53-
- name: set up QEMU
54-
uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3
49+
- name: Set up QEMU
50+
uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0
5551
with:
5652
platforms: all
5753

58-
- name: install buildx
59-
id: buildx
60-
uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3
61-
with:
62-
version: latest
63-
install: true
64-
65-
- name: available platforms
66-
run: echo ${{ steps.buildx.outputs.platforms }}
54+
- name: Set up Buildx
55+
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
6756

68-
- name: Login to DockerHub
69-
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3
57+
- name: Log in to Docker Hub
58+
if: github.event_name != 'pull_request'
59+
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
7060
with:
7161
username: ${{ secrets._TEMP_DOCKERHUB_USER }}
7262
password: ${{ secrets._TEMP_DOCKERHUB_PASSWORD }}
7363

74-
- name: build and push images
64+
- name: Compute image metadata
65+
id: meta
66+
shell: bash
7567
run: |
76-
docker build --build-arg GIT_COMMIT=${{ github.sha }} --push --platform $PLATFORM $TAG .
68+
VERSION=""
69+
IS_VERSIONED="false"
70+
PRIMARY_TAG=""
71+
PUSH_TAGS=""
72+
73+
if [[ "${{ github.event_name }}" == "release" ]]; then
74+
VERSION="${{ github.event.release.tag_name }}"
75+
IS_VERSIONED="true"
76+
elif [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
77+
if [[ "${{ github.ref_type }}" == "tag" ]]; then
78+
VERSION="${{ github.ref_name }}"
79+
IS_VERSIONED="true"
80+
elif [[ "${{ github.ref }}" != "refs/heads/main" ]]; then
81+
echo "workflow_dispatch must be run on main or on a tag"
82+
exit 1
83+
fi
84+
fi
7785
78-
- name: Scan manager docker image
79-
uses: anchore/scan-action@3c9a191a0fbab285ca6b8530b5de5a642cba332f # v7.2.2
86+
if [[ "$IS_VERSIONED" == "true" ]]; then
87+
PRIMARY_TAG="${IMAGE_NAME}:${VERSION}"
88+
PUSH_TAGS="${IMAGE_NAME}:${VERSION}
89+
${IMAGE_NAME}:latest"
90+
elif [[ "${{ github.ref }}" == "refs/heads/main" ]]; then
91+
PRIMARY_TAG="${IMAGE_NAME}:develop"
92+
PUSH_TAGS="${IMAGE_NAME}:develop"
93+
else
94+
PRIMARY_TAG="${IMAGE_NAME}:pr-${{ github.event.pull_request.number || github.run_number }}"
95+
PUSH_TAGS="${PRIMARY_TAG}"
96+
fi
97+
98+
{
99+
echo "version=$VERSION"
100+
echo "is_versioned=$IS_VERSIONED"
101+
echo "primary_tag=$PRIMARY_TAG"
102+
echo "push_tags<<EOF"
103+
echo "$PUSH_TAGS"
104+
echo "EOF"
105+
} >> "$GITHUB_OUTPUT"
106+
107+
- name: Build image locally for scanning
108+
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0
109+
with:
110+
context: .
111+
platforms: linux/amd64
112+
load: true
113+
push: false
114+
tags: ${{ steps.meta.outputs.primary_tag }}
115+
build-args: |
116+
GIT_COMMIT=${{ github.sha }}
117+
cache-from: type=gha,scope=proxy-amd64
118+
cache-to: type=gha,mode=max,scope=proxy-amd64
119+
120+
- name: Scan proxy Docker image
121+
uses: anchore/scan-action@e1165082ffb1fe366ebaf02d8526e7c4989ea9d2 # v7.4.0
80122
id: anchore-scan
81123
with:
82-
image: ${{ steps.set-tags.outputs.dockerImage }}
124+
image: ${{ steps.meta.outputs.primary_tag }}
83125
fail-build: false
84126
severity-cutoff: critical
85127

86128
- name: Upload Anchore scan SARIF report
87-
if: ${{ !cancelled() }}
88-
uses: github/codeql-action/upload-sarif@c8e3174949dcd2ceb71718aeaa53fee4dc9052f2 # v4.31.7
129+
if: ${{ !cancelled() && github.event_name != 'pull_request' && (github.event_name != 'workflow_dispatch' || github.ref == 'refs/heads/main') }}
130+
uses: github/codeql-action/upload-sarif@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1
89131
with:
90132
sarif_file: ${{ steps.anchore-scan.outputs.sarif }}
133+
category: grype-proxy
91134

92-
- name: Inspect Anchore scan SARIF report
93-
if: ${{ !cancelled() }}
94-
run: cat ${{ steps.anchore-scan.outputs.sarif }}
95-
135+
- name: Build and push multi-arch images
136+
if: github.event_name != 'pull_request'
137+
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0
138+
with:
139+
context: .
140+
platforms: ${{ env.PLATFORM }}
141+
push: true
142+
tags: ${{ steps.meta.outputs.push_tags }}
143+
build-args: |
144+
GIT_COMMIT=${{ github.sha }}
145+
cache-from: type=gha,scope=proxy-multiarch
146+
cache-to: type=gha,mode=max,scope=proxy-multiarch
147+
148+
# Skip SonarQube when SONAR_TOKEN is not configured, and also skip fork PRs because repository secrets are not exposed there
96149
- name: SonarQube Scan
150+
if: ${{ env.SONAR_TOKEN != '' && (github.event_name != 'pull_request' || !github.event.pull_request.head.repo.fork) }}
97151
uses: SonarSource/sonarqube-scan-action@a31c9398be7ace6bbfaf30c0bd5d415f843d45e9 # v7.0.0
98-
env:
99-
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
152+

.github/workflows/release.yml

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
name: Release
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
VERSION:
7+
description: 'Release version/tag to create (example: 2.9.15.1)'
8+
type: string
9+
required: true
10+
11+
permissions:
12+
actions: write
13+
contents: write
14+
15+
jobs:
16+
release:
17+
name: Release
18+
runs-on: ubuntu-latest
19+
20+
steps:
21+
- name: Checkout
22+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
23+
with:
24+
fetch-depth: 0
25+
26+
- name: Validate version
27+
shell: bash
28+
run: |
29+
if [[ -z "${VERSION}" ]]; then
30+
echo "VERSION is required"
31+
exit 1
32+
fi
33+
34+
if git ls-remote --tags origin "refs/tags/${VERSION}" | grep -q "refs/tags/${VERSION}$"; then
35+
echo "Tag ${VERSION} already exists on origin"
36+
exit 1
37+
fi
38+
env:
39+
VERSION: ${{ github.event.inputs.VERSION }}
40+
41+
- name: Create and push tag
42+
shell: bash
43+
run: |
44+
git tag "${VERSION}"
45+
git push origin "${VERSION}"
46+
env:
47+
VERSION: ${{ github.event.inputs.VERSION }}
48+
49+
- name: Create GitHub release
50+
shell: bash
51+
run: |
52+
gh release create "${VERSION}" \
53+
--generate-notes \
54+
--title "${VERSION}"
55+
env:
56+
GH_TOKEN: ${{ github.token }}
57+
VERSION: ${{ github.event.inputs.VERSION }}
58+
59+
- name: Trigger Docker workflow
60+
shell: bash
61+
run: |
62+
gh workflow run proxy.yml --ref "${VERSION}"
63+
env:
64+
GH_TOKEN: ${{ github.token }}
65+
VERSION: ${{ github.event.inputs.VERSION }}

0 commit comments

Comments
 (0)