Skip to content

Commit

Permalink
Update workflows, build multiplatform images
Browse files Browse the repository at this point in the history
  • Loading branch information
ffried committed Apr 25, 2024
1 parent 8f48c5a commit c09aee8
Show file tree
Hide file tree
Showing 4 changed files with 186 additions and 77 deletions.
154 changes: 106 additions & 48 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,82 +6,140 @@ on:
- '[0-9]+.[0-9]+.[0-9]+'
branches:
- main
paths:
- '.github/workflows/deploy.yml'
- 'bin/**'
- 'server/**'
- 'Dockerfile'
- '.dockerignore'

jobs:
determine-deployment-config:
check-files:
runs-on: ubuntu-latest
outputs:
environment: ${{ steps.determine-environment.outputs.environment }}
has-relevant-changes: ${{ steps.changes.outputs.workflow || steps.changes.outputs.docker || steps.changes.outputs.server }}
steps:
- name: Determine environment
id: determine-environment
env:
REF_TYPE: ${{ github.ref_type }}
run: |
if [ "${REF_TYPE}" == 'tag' ]; then
echo 'environment=production' >> "${GITHUB_OUTPUT}"
else
echo 'environment=development' >> "${GITHUB_OUTPUT}"
fi
- uses: dorny/paths-filter@v3
id: changes
with:
filters: |
workflow:
- '.github/workflows/deploy.yml'
docker:
- 'bin/**'
- 'Dockerfile'
- '.dockerignore'
server:
- 'server/**'
run-deployment:
needs: determine-deployment-config
environment: ${{ needs.determine-deployment-config.outputs.environment }}
needs: check-files
if: ${{ needs.check-files.outputs.has-relevant-changes == 'true' }}
environment: ${{ github.ref_type == 'tag' && 'production' || 'development'}}
runs-on: ubuntu-latest
steps:
- uses: docker/[email protected]
id: image-meta
with:
images: ${{ vars.DOCKER_REGISTRY }}/${{ vars.DOCKER_IMAGE }}
flavor: latest=false
tags: |
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=sha,format=short,prefix=rev-,enable=${{ github.ref_type != 'tag' }}
type=raw,value=stable,priority=50,enable=${{ github.ref_type == 'tag' }}
type=raw,value=latest,priority=50,enable=${{ github.ref_type != 'tag' }}
- name: Get image parameters
id: image-parameters
shell: bash
env:
IS_RELEASE: ${{ github.ref_type == 'tag' }}
RELEASE_TAG: ${{ github.ref_name }}
SHA: ${{ github.sha }}
IMAGE_VERSION: ${{ steps.image-meta.outputs.version }}
META_JSON: ${{ steps.image-meta.outputs.json }}
run: |
VERSION_TAG=''
LATEST_TAG=''
if [ "${IS_RELEASE}" == 'true' ]; then
VERSION_TAG="${RELEASE_TAG}"
LATEST_TAG='stable'
if [ "${IS_RELEASE}" = 'true' ]; then
VERSION_TAG="${IMAGE_VERSION}"
else
VERSION_TAG="rev-$(echo "${SHA}" | cut -c1-7)"
LATEST_TAG='latest'
VERSION_TAG="$(echo -n "${META_JSON}" | jq --raw-output '
.tags
| map(split(":")
| .[1:]
| join(":")
| select(startswith("rev-")))
| first')"
fi
echo "latest-tag=${LATEST_TAG}" >> "${GITHUB_OUTPUT}"
echo "version-tag=${VERSION_TAG}" >> "${GITHUB_OUTPUT}"
echo "version-arg=${VERSION_TAG}" >> "${GITHUB_OUTPUT}"
- uses: docker/setup-qemu-action@v3
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
- uses: docker/setup-qemu-action@v3.0.0
- uses: docker/setup-buildx-action@v3.3.0
- uses: docker/login-action@v3.1.0
with:
registry: ${{ vars.DOCKER_REGISTRY }}
registry: ${{ vars.DOCKER_IMAGE }}
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- uses: docker/build-push-action@v5
- uses: docker/build-push-action@v5.3.0
with:
pull: true
push: true
platforms: linux/amd64
platforms: linux/amd64,linux/arm64
build-args: |
VERSION=${{ steps.image-parameters.outputs.version-arg }}
tags: |
${{ vars.DOCKER_REGISTRY }}/${{ vars.DOCKER_IMAGE }}:${{ steps.image-parameters.outputs.version-tag }}
${{ vars.DOCKER_REGISTRY }}/${{ vars.DOCKER_IMAGE }}:${{ steps.image-parameters.outputs.latest-tag }}
tags: ${{ steps.image-meta.outputs.tags }}
labels: ${{ steps.image-meta.outputs.labels }}
annotations: ${{ steps.image-meta.outputs.annotations }}
sbom: true
provenance: mode=min
cache-from: type=gha
cache-to: type=gha,mode=max
- uses: fjogeleit/http-request-action@v1
- name: Generate SBOM name
id: sbom-name
shell: bash
env:
REPO: ${{ github.repository }}
IMAGE_VERSION: ${{ steps.image-meta.outputs.version }}
run: echo "artifact-name=${REPO##*/}-${IMAGE_VERSION}-sbom.spdx" >> "${GITHUB_OUTPUT}"
- uses: anchore/sbom-action@v0
with:
image: ${{ fromJson(steps.image-meta.outputs.json).tags[0] }}
artifact-name: ${{ steps.sbom-name.outputs.artifact-name }}
dependency-snapshot: true
- uses: actions/checkout@v4
with:
path: .sarif-scan-temp
sparse-checkout: Dockerfile
sparse-checkout-cone-mode: false
- name: Pull built image
shell: bash
env:
DOCKER_IMAGE: ${{ fromJson(steps.image-meta.outputs.json).tags[0] }}
run: docker pull "${DOCKER_IMAGE}"
- uses: crazy-max/ghaction-container-scan@v3
# continue-on-error: true
id: image-scan
with:
image: ${{ fromJson(steps.image-meta.outputs.json).tags[0] }}
dockerfile: ./.sarif-scan-temp/Dockerfile
annotations: true
- uses: github/codeql-action/upload-sarif@v3
if: ${{ steps.image-scan.outputs.sarif != '' }}
continue-on-error: true # if advanced security is disabled, this will fail.
with:
sarif_file: ${{ steps.image-scan.outputs.sarif }}
- name: Build Payload
id: build-payload
shell: bash
env:
TAGS: ${{ steps.image-meta.outputs.tags }}
run: |
JSON_PAYLOAD="$(echo -n "${TAGS}" | jq --raw-input --slurp --raw-output --compact-output '
split(" |\n"; null)
| map(split(":") | select(length >= 2))
| reduce .[] as $i (null; .[($i[0])] += [($i[1:] | join(":"))])
| to_entries
| map({"image": .key, "tags": .value})')"
echo "payload=${JSON_PAYLOAD}" >> "${GITHUB_OUTPUT}"
- uses: fjogeleit/[email protected]
with:
method: POST
url: "${{ secrets.DEPLOYER_URL }}/api/v1/deploy"
url: ${{ secrets.DEPLOYER_URL }}/api/v1/deploy
bearerToken: ${{ secrets.DEPLOYER_TOKEN }}
timeout: 0
data: |
{
"image": "${{ vars.DOCKER_IMAGE }}",
"tags": [ "${{ steps.image-parameters.outputs.version-tag }}", "${{ steps.image-parameters.outputs.latest-tag }}" ]
}
timeout: 150000 # 2.5 minutes
retry: 3
retryWait: 3000 # 3 seconds
contentType: application/json
data: ${{ steps.build-payload.outputs.payload }}
34 changes: 26 additions & 8 deletions .github/workflows/validate-dependencies.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,39 @@ name: Validate Dependencies
on:
pull_request:
branches: [ main ]
paths: [ 'server/**/*.csproj' ]

permissions:
pull-requests: read
contents: read

jobs:
check-files:
runs-on: ubuntu-latest
outputs:
has-relevant-changes: ${{ steps.changes.outputs.csprojects }}
permissions:
pull-requests: read
steps:
- uses: dorny/paths-filter@v3
id: changes
with:
filters: |
csprojects:
- '*.csproj'
- '**/*.csproj'
validate-dependencies:
needs: check-files
if: ${{ needs.check-files.outputs.has-relevant-changes == 'true' }}
runs-on: ubuntu-latest
env:
NUGET_PACKAGES: ${{ github.workspace }}/.nuget/packages
steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.0.x'
- uses: actions/cache@v4
with:
path: ${{ github.workspace }}/server/.nuget/packages
key: ${{ runner.os }}-nuget-${{ hashFiles('server/**/packages.lock.json') }}
restore-keys: |
${{ runner.os }}-nuget-
dotnet-version: '8.0'
cache: true
cache-dependency-path: '*/*.csproj'
- working-directory: server
run: dotnet restore
73 changes: 53 additions & 20 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,32 +1,63 @@
FROM mcr.microsoft.com/dotnet/sdk:8.0-jammy as buildnode
FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:8.0-alpine as buildnode

ARG TARGETPLATFORM
ARG VERSION

LABEL description="This image builds the Sensor Server"
LABEL vendor="ser.soft GmbH"
LABEL maintainer="[email protected]"
LABEL version="${VERSION}"

ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false

RUN apt-get update --quiet \
&& apt-get install --quiet --yes --no-install-recommends openssl ca-certificates \
&& rm -rf /var/lib/apt/lists/*

WORKDIR /sensor-server

RUN <<EOC
set -eux
case "${TARGETPLATFORM}" in
'linux/amd64') export RUNTIME_ID='linux-musl-x64' ;;
'linux/arm64') export RUNTIME_ID='linux-musl-arm64' ;;
*)
echo "Unsupported platform: ${TARGETPLATFORM}"
exit 1
;;
esac
echo -n "${RUNTIME_ID}" > /tmp/runtime-id
EOC

COPY server/*.sln .
WORKDIR /sensor-server/SensorServer
COPY server/SensorServer/*.csproj .
WORKDIR /sensor-server
RUN unset VERSION; \
dotnet restore
dotnet restore --runtime "$(cat /tmp/runtime-id)"

COPY server/ ./
RUN unset VERSION; \
dotnet publish --no-restore -c release -o /dist



FROM mcr.microsoft.com/dotnet/aspnet:8.0-jammy
RUN <<EOC
set -eux
RUNTIME_ID="$(cat /tmp/runtime-id)"
if echo "${VERSION}" | grep -Eq '^[0-9]+.[0-9]+.[0-9]+'; then
PROJECT_VERSION="${VERSION}"
else
PROJECT_VERSION="0.0.1-${VERSION}"
fi
rm -f appsettings.Development.json
unset VERSION
dotnet publish --no-restore \
--configuration release \
--runtime "${RUNTIME_ID}" \
--no-self-contained \
--output ./dist \
-p:Version="${PROJECT_VERSION}"
EOC


FROM mcr.microsoft.com/dotnet/aspnet:8.0-alpine

ARG VERSION

Expand All @@ -35,23 +66,25 @@ LABEL vendor="ser.soft GmbH"
LABEL maintainer="[email protected]"
LABEL version="${VERSION}"

RUN export DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true \
&& apt-get -qq update && apt-get -q dist-upgrade -y && apt-get -q install -y curl \
&& rm -rf /var/lib/apt/lists/* \
&& mkdir -p /sensor-server \
&& mkdir -p /sensor-server/data \
&& groupadd --gid 1000 sensor-server \
&& useradd --uid 1000 --gid 1000 -m sensor-server \
&& chown -R sensor-server:sensor-server /sensor-server
ENV TZ=UTC
ENV SERVER_PORT=8080
ENV ASPNETCORE_URLS=http://+:${SERVER_PORT}
ENV ASPNETCORE_ENVIRONMENT=Production
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false

RUN <<EOC
set -eux
apk add --update --no-cache curl icu-libs icu-data-full
mkdir -p /sensor-server/data
addgroup --system --gid 1000 sensor-server
adduser --system --uid 1000 --ingroup sensor-server --home /sensor-server sensor-server
chown -R sensor-server:sensor-server /sensor-server
EOC

WORKDIR /sensor-server

USER sensor-server:sensor-server

ENV SERVER_PORT=8080
ENV ASPNETCORE_URLS=http://0.0.0.0:${SERVER_PORT}
ENV ASPNETCORE_ENVIRONMENT Production

EXPOSE ${SERVER_PORT}

COPY bin/docker-healthcheck.sh /usr/local/bin/docker-healthcheck.sh
Expand All @@ -62,4 +95,4 @@ VOLUME [ "/sensor-server/data" ]
HEALTHCHECK --interval=10s --timeout=3s --start-period=30s \
CMD ["/usr/local/bin/docker-healthcheck.sh"]

ENTRYPOINT ["dotnet", "/sensor-server/SensorServer.dll"]
ENTRYPOINT ["/sensor-server/SensorServer"]
2 changes: 1 addition & 1 deletion bin/docker-healthcheck.sh
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
#!/bin/bash
#!/bin/sh

curl --head --fail --silent --connect-timeout 3 --output /dev/null "http://127.0.0.1:${SERVER_PORT}" || exit 1

0 comments on commit c09aee8

Please sign in to comment.