Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion .github/workflows/build-docker-images.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,21 @@ jobs:
build-full-app:

runs-on: ubuntu-latest
permissions:
contents: read

steps:
- uses: actions/checkout@v3
- name: Build the full Docker image
run: docker build --file Dockerfile --tag streamlitapp:latest --output type=tar,dest=/dev/null .
run: docker build --file Dockerfile --tag streamlitapp:latest --build-arg GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }} --output type=tar,dest=/dev/null .

build-full-app-arm64:

runs-on: ubuntu-24.04-arm
permissions:
contents: read

steps:
- uses: actions/checkout@v3
- name: Build the ARM64 Docker image
run: docker build --file Dockerfile.arm --tag streamlitapp:latest-arm64 --build-arg GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }} --output type=tar,dest=/dev/null .
163 changes: 163 additions & 0 deletions .github/workflows/publish-docker-images.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
name: Publish Docker Images to GHCR

on:
workflow_run:
workflows: ["Build executable for Windows"]
types: [completed]
workflow_dispatch:
inputs:
tag:
description: 'Release tag to build (e.g., v0.9.15)'
required: true

jobs:

resolve-tag:
# Only run on successful completion of a release-triggered Windows build,
# or on manual dispatch
if: >
github.event_name == 'workflow_dispatch' ||
(github.event.workflow_run.conclusion == 'success' &&
github.event.workflow_run.event == 'release')
runs-on: ubuntu-latest
outputs:
version: ${{ steps.tag.outputs.version }}
sha: ${{ steps.tag.outputs.sha }}
steps:
- name: Resolve release tag
id: tag
env:
GH_TOKEN: ${{ github.token }}
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
TAG="${{ github.event.inputs.tag }}"
SHA=$(gh api repos/${{ github.repository }}/git/ref/tags/${TAG} --jq '.object.sha')
else
# workflow_run: get the tag from the head branch (release events set head_branch to the tag)
TAG="${{ github.event.workflow_run.head_branch }}"
SHA="${{ github.event.workflow_run.head_sha }}"
fi

# Strip leading 'v' for version
VERSION="${TAG#v}"

echo "Resolved tag=${TAG} version=${VERSION} sha=${SHA}"
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
echo "sha=${SHA}" >> "$GITHUB_OUTPUT"

build-amd64:
needs: resolve-tag
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
env:
IMAGE: ghcr.io/openms/flashapp
steps:
- name: Free disk space
run: |
sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc /opt/hostedtoolcache
sudo apt-get clean
df -h

- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ needs.resolve-tag.outputs.sha }}

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and push amd64 image
uses: docker/build-push-action@v6
with:
context: .
file: Dockerfile
push: true
tags: ${{ env.IMAGE }}:${{ needs.resolve-tag.outputs.version }}-amd64
build-args: |
GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }}
Comment on lines +85 to +86
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n 'ARG GITHUB_TOKEN|ENV GH_TOKEN=|gh release download' Dockerfile Dockerfile.arm
sed -n '78,88p' .github/workflows/publish-docker-images.yml
sed -n '120,130p' .github/workflows/publish-docker-images.yml

Repository: OpenMS/FLASHApp

Length of output: 1392


Replace build-args with secrets: to prevent baking the GitHub token into the image.

The GITHUB_TOKEN is currently passed via build-args (lines 85–86 and 127–128), which causes it to be converted into an ENV variable in the Dockerfile (ENV GH_TOKEN=${GITHUB_TOKEN} at line 35 in both Dockerfiles). Docker ENV values persist in the final image and can be exposed through image metadata/inspection.

Use docker/build-push-action@v6's secrets: input with BuildKit secret mounts instead:

Workflow changes
-          build-args: |
-            GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }}
+          secrets: |
+            "gh_token=${{ secrets.GITHUB_TOKEN }}"

Then in both Dockerfiles, replace the ARG GITHUB_TOKEN / ENV GH_TOKEN=${GITHUB_TOKEN} pattern with RUN --mount=type=secret,id=gh_token when invoking gh release download.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
build-args: |
GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }}
secrets: |
"gh_token=${{ secrets.GITHUB_TOKEN }}"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/publish-docker-images.yml around lines 85 - 86, Replace
the build-args usage in the publish workflow with BuildKit secrets: remove the
GITHUB_TOKEN under build-args in the docker/build-push-action@v6 steps and add a
secrets: entry that provides id: gh_token and value: ${{ secrets.GITHUB_TOKEN }}
so the token is mounted as a secret instead of baked into the image; then update
both Dockerfiles to remove ARG GITHUB_TOKEN and ENV GH_TOKEN=${GITHUB_TOKEN} and
change the gh release download invocation to use BuildKit secret mounts (use RUN
--mount=type=secret,id=gh_token ...) where gh release download is called.

cache-from: type=registry,ref=${{ env.IMAGE }}:buildcache-amd64
cache-to: type=registry,ref=${{ env.IMAGE }}:buildcache-amd64,mode=max

build-arm64:
needs: resolve-tag
runs-on: ubuntu-24.04-arm
permissions:
contents: read
packages: write
env:
IMAGE: ghcr.io/openms/flashapp
steps:
- name: Free disk space
run: |
sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc /opt/hostedtoolcache
sudo apt-get clean
df -h

- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ needs.resolve-tag.outputs.sha }}

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and push arm64 image
uses: docker/build-push-action@v6
with:
context: .
file: Dockerfile.arm
push: true
tags: ${{ env.IMAGE }}:${{ needs.resolve-tag.outputs.version }}-arm64
build-args: |
GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }}
cache-from: type=registry,ref=${{ env.IMAGE }}:buildcache-arm64
cache-to: type=registry,ref=${{ env.IMAGE }}:buildcache-arm64,mode=max

create-manifest:
needs: [resolve-tag, build-amd64, build-arm64]
runs-on: ubuntu-latest
permissions:
packages: write
env:
IMAGE: ghcr.io/openms/flashapp
steps:
- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Create and push multi-arch manifests
run: |
VERSION="${{ needs.resolve-tag.outputs.version }}"

# Create versioned manifest
docker manifest create ${{ env.IMAGE }}:${VERSION} \
${{ env.IMAGE }}:${VERSION}-amd64 \
${{ env.IMAGE }}:${VERSION}-arm64

docker manifest push ${{ env.IMAGE }}:${VERSION}

# Create/update latest manifest
docker manifest create ${{ env.IMAGE }}:latest \
${{ env.IMAGE }}:${VERSION}-amd64 \
${{ env.IMAGE }}:${VERSION}-arm64

docker manifest push ${{ env.IMAGE }}:latest
Comment on lines +158 to +163
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Guard latest on manual backfills.

workflow_dispatch accepts any release tag, but this step always repoints ghcr.io/openms/flashapp:latest to whatever version was requested. Rebuilding an older release would silently roll latest backward.

🛠️ One possible guard
 on:
   workflow_dispatch:
     inputs:
       tag:
         description: 'Release tag to build (e.g., v0.9.15)'
         required: true
+      update_latest:
+        description: 'Also move the latest tag'
+        type: boolean
+        default: false
-          # Create/update latest manifest
-          docker manifest create ${{ env.IMAGE }}:latest \
-            ${{ env.IMAGE }}:${VERSION}-amd64 \
-            ${{ env.IMAGE }}:${VERSION}-arm64
-
-          docker manifest push ${{ env.IMAGE }}:latest
+          if [ "${{ github.event_name }}" = "workflow_run" ] || [ "${{ github.event.inputs.update_latest }}" = "true" ]; then
+            docker manifest create ${{ env.IMAGE }}:latest \
+              ${{ env.IMAGE }}:${VERSION}-amd64 \
+              ${{ env.IMAGE }}:${VERSION}-arm64
+            docker manifest push ${{ env.IMAGE }}:latest
+          fi
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/publish-docker-images.yml around lines 158 - 163, The
docker manifest create/push steps currently always repoint IMAGE:latest to
VERSION; add a guard so those steps only run when VERSION is actually the
repository's latest release (or when not a manual workflow_dispatch backfill).
Implement a short preparatory step (e.g., "get_latest") that queries the GitHub
Releases API to output the current latest tag, then add an if condition on the
docker manifest create and docker manifest push steps that checks env.VERSION
equals that get_latest output (or that github.event_name != 'workflow_dispatch'
OR VERSION == steps.get_latest.outputs.tag) so manual backfills of older tags do
not overwrite IMAGE:latest.

26 changes: 14 additions & 12 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ WORKDIR /openms-streamlit-vue-component
RUN npm install
RUN npm run build

FROM ubuntu:22.04 AS setup-build-system
FROM ubuntu:24.04 AS setup-build-system
WORKDIR /

COPY --from=js-build openms-streamlit-vue-component/dist /app/js-component/dist
Expand All @@ -45,14 +45,14 @@ USER root

# Install required Ubuntu packages.
RUN apt-get -y update
RUN apt-get install -y --no-install-recommends --no-install-suggests g++ autoconf automake patch libtool make git gpg wget ca-certificates curl jq libgtk2.0-dev openjdk-8-jdk cron
RUN apt-get install -y --no-install-recommends --no-install-suggests g++ autoconf automake patch libtool make git gpg wget ca-certificates curl jq libgtk2.0-dev openjdk-8-jdk cron cmake
RUN update-ca-certificates
RUN apt-get install -y --no-install-recommends --no-install-suggests libsvm-dev libeigen3-dev coinor-libcbc-dev libglpk-dev libzip-dev zlib1g-dev libxerces-c-dev libbz2-dev libomp-dev libhdf5-dev
RUN apt-get install -y --no-install-recommends --no-install-suggests libboost-date-time1.74-dev \
libboost-iostreams1.74-dev \
libboost-regex1.74-dev \
libboost-math1.74-dev \
libboost-random1.74-dev
RUN apt-get install -y --no-install-recommends --no-install-suggests libboost-date-time-dev \
libboost-iostreams-dev \
libboost-regex-dev \
libboost-math-dev \
libboost-random-dev
RUN apt-get install -y --no-install-recommends --no-install-suggests qt6-base-dev libqt6svg6-dev libqt6opengl6-dev libqt6openglwidgets6 libgl-dev

# Install Github CLI
Expand All @@ -78,8 +78,6 @@ RUN echo "mamba activate streamlit-env" >> ~/.bashrc
SHELL ["/bin/bash", "--rcfile", "~/.bashrc"]
SHELL ["mamba", "run", "-n", "streamlit-env", "/bin/bash", "-c"]

# Install up-to-date cmake via mamba and packages for pyOpenMS build.
RUN mamba install -y cmake
RUN pip install --upgrade pip && python -m pip install -U setuptools nose 'Cython>=3.1' 'autowrap==0.24' pandas 'numpy>=2.0' pytest

# Clone OpenMS branch and the associcated contrib+thirdparties+pyOpenMS-doc submodules.
Expand All @@ -102,12 +100,16 @@ WORKDIR /
RUN mkdir /openms-build
WORKDIR /openms-build

# Configure.
RUN /bin/bash -c "cmake -DCMAKE_BUILD_TYPE='Release' -DCMAKE_PREFIX_PATH='/OpenMS/contrib-build/;/usr/;/usr/local' -DHAS_XSERVER=OFF -DBOOST_USE_STATIC=OFF -DPYOPENMS=ON ../OpenMS -DPY_MEMLEAK_DISABLE=On -DOPENMP=ON"
# Configure (two-pass: first without miniforge so cmake finds system C++ libs,
# then reconfigure with miniforge for pyopenms).
SHELL ["/bin/bash", "-c"]
RUN cmake -DCMAKE_BUILD_TYPE='Release' -DCMAKE_PREFIX_PATH='/OpenMS/contrib-build/;/usr/;/usr/local' -DCMAKE_IGNORE_PREFIX_PATH=/root/miniforge3 -DHAS_XSERVER=OFF -DBOOST_USE_STATIC=OFF -DOPENMP=ON ../OpenMS
SHELL ["mamba", "run", "-n", "streamlit-env", "/bin/bash", "-c"]
RUN cmake -DPYOPENMS=ON -DPY_MEMLEAK_DISABLE=On -DCMAKE_IGNORE_PREFIX_PATH=/root/miniforge3 .

# Build TOPP tools and clean up.
RUN make -j4 TOPP
RUN rm -rf src doc CMakeFiles
RUN rm -rf src doc

# Build pyOpenMS wheels and install via pip.
RUN make -j4 pyopenms
Expand Down
Loading
Loading