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
68 changes: 63 additions & 5 deletions .github/workflows/docker-multiarch.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ name: docker-multiarch
on:
push:
tags:
- '[0-9]*.[0-9]*.[0-9]*'
- 'v*.*.*'
- '[0-9]+.[0-9]+.[0-9]+*'
workflow_dispatch:

env:
Expand Down Expand Up @@ -40,7 +40,7 @@ jobs:
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
# Generate ONLY platform-specific tags here.
# We do NOT push 'latest' or the bare version 'v1.2.3' in this job.
# We do NOT push 'latest' or the bare version '1.2.3' in this job.
# Those are reserved for the final merge step to avoid race conditions.
tags: |
type=semver,pattern={{version}},suffix=-linux
Expand All @@ -58,6 +58,54 @@ jobs:
provenance: false
outputs: type=image,rewrite-timestamp=false

build-rhel-linux-multiarch:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
ubi_major: [8, 9]
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up QEMU
uses: docker/setup-qemu-action@v3

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

- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract version from tag
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=semver,pattern={{version}},suffix=-rhel${{ matrix.ubi_major }}-linux
type=ref,event=branch,suffix=-rhel${{ matrix.ubi_major }}-linux

- name: Build and push RHEL ${{ matrix.ubi_major }} Linux image
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile-rhel-runtime
build-args: |
UBI_MAJOR=${{ matrix.ubi_major }}
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
provenance: false
outputs: type=image,rewrite-timestamp=false

# Windows build is separate and less frequent, keeping it here but isolated
build-windows:
if: (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')) || github.event_name == 'workflow_dispatch'
Expand Down Expand Up @@ -91,19 +139,29 @@ jobs:
run: |
echo "IMAGE_NAME_LOWER=${{ env.IMAGE_NAME }}".ToLower() >> $env:GITHUB_ENV

- name: Ensure Docker daemon is running (Windows)
shell: powershell
run: |
$ErrorActionPreference = 'Stop'
if (-not (Get-Service -Name docker -ErrorAction SilentlyContinue)) {
throw 'Docker service was not found on the Windows runner.'
}
Start-Service docker
docker version

# Standardize on -windows suffix for consistent intermediary tags
# Ensure IMAGE_NAME is lowercase primarily for the manual docker build command
# Note: We use the default docker builder here, not buildx, because setup-buildx-action
# fails to start the buildkit container on Windows runners (which run in Windows container mode).
# The default 'docker build' command works fine for Windows images.
# The default 'docker build' command works fine for Windows images once the daemon is running.
- name: Build and push Windows image
run: |
docker build -f Dockerfile-windows -t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_LOWER }}:${{ steps.meta.outputs.version }}-windows .
docker push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_LOWER }}:${{ steps.meta.outputs.version }}-windows

# Manifest creation: This is the ONLY place where user-facing tags (v1.2.3, latest) are pushed.
merge-manifest:
needs: [build-linux-multiarch, build-windows]
needs: [build-linux-multiarch, build-rhel-linux-multiarch, build-windows]
if: success() && ((github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')) || github.event_name == 'workflow_dispatch')
runs-on: ubuntu-latest
permissions:
Expand Down Expand Up @@ -142,7 +200,7 @@ jobs:
# In the build-windows job, we push: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.version }}-windows
WINDOWS_IMAGE="${IMAGE_ROOT}:${VERSION}-windows"

# Tags to generate (v1.8.1 and latest)
# Tags to generate (1.8.1 and latest)
TARGET_TAG="${IMAGE_ROOT}:${VERSION}"
LATEST_TAG="${IMAGE_ROOT}:latest"

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: executable-bundle-ubuntu
name: executable-bundle-linux

on:
release:
Expand All @@ -9,56 +9,48 @@ permissions:
contents: write

jobs:
build-ubuntu-linux:
name: build ubuntu linux binary
build-linux:
name: Build Linux Executable Bundle
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Install dependencies and Build Bundle (Ubuntu)
id: get_bundle_name # Added an ID to this step to capture output
- name: Install dependencies and Build Bundle (Linux)
id: get_bundle_name
run: |
# Ensure repository owner is lowercase for Docker tag
REPO_OWNER=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]')
IMAGE_TAG="ghcr.io/${REPO_OWNER}/config-assessment-tool-ubuntu-linux:latest"
IMAGE_TAG="ghcr.io/${REPO_OWNER}/config-assessment-tool-build:latest"

# build image which builds the bundle for Ubuntu 20.x+
# IMPORTANT: Use the new Dockerfile for Ubuntu
make build-image DOCKERFILE=backend/Dockerfile-ubuntu DOCKER_IMAGE_TAG=${IMAGE_TAG}
echo "finished building docker image with bundle included"
# copy bundle out of built image
# Build on a RHEL 8-compatible base so the bundle works on both
# RHEL 8.x and RHEL 9.x hosts (and Ubuntu 20+).
# Use NO_CACHE=true to avoid buildkit caching issues
make build-image DOCKERFILE=backend/Dockerfile-rhel DOCKER_IMAGE_TAG=${IMAGE_TAG} NO_CACHE=true
echo "finished building docker image with Linux bundle included"

# Copy bundle out of built image
# The `find` command is more robust for dynamically named files
tarball_path=$(docker run --rm ${IMAGE_TAG} find /root/config-assessment-tool/dist/ -name "*.tgz")
echo "copying bundle out of image using $tarball_path"
docker cp $(docker create --name temp_image ${IMAGE_TAG}):$tarball_path ./ && docker rm temp_image
echo "finished copying bundle onto hosted runner at $(pwd)"
echo "files in current directory $(ls -altr)"
# Capture the exact bundle filename
ORIGINAL_BUNDLE_NAME=$(ls -1 *.tgz | head -n 1)

# Inject -executable- into the filename
# Expecting format like config-assessment-tool-ubuntu-linux-1.8.0-beta.1.tgz
# converting to config-assessment-tool-ubuntu-linux-executable-1.8.0-beta.1.tgz
# OR just append -executable before extension if regex is too complex

# Using sed to append -executable before the .tgz extension
NEW_BUNDLE_NAME=$(echo "$ORIGINAL_BUNDLE_NAME" | sed 's/\.tgz$/-executable.tgz/')

# fallback if substitution didn't happen (e.g. name format changed)
if [[ "$NEW_BUNDLE_NAME" == "$ORIGINAL_BUNDLE_NAME" ]]; then
NEW_BUNDLE_NAME="${ORIGINAL_BUNDLE_NAME%.tgz}-executable.tgz"
ORIGINAL_BUNDLE_NAME=$(ls -1 *.tgz | head -n 1)
VERSION="${{ github.ref_name }}"
if [[ -z "$VERSION" ]]; then
VERSION="$(cat VERSION)"
fi

NEW_BUNDLE_NAME="config-assessment-tool-linux-${VERSION}-x86_64-executable.tgz"
mv "$ORIGINAL_BUNDLE_NAME" "$NEW_BUNDLE_NAME"

echo "Renamed $ORIGINAL_BUNDLE_NAME to $NEW_BUNDLE_NAME"

BUNDLE_NAME="$NEW_BUNDLE_NAME"
echo "BUNDLE_NAME=$BUNDLE_NAME" >> $GITHUB_ENV # Set as an environment variable
echo "bundle_name=$BUNDLE_NAME" >> $GITHUB_OUTPUT # Set as step output for clarity

- name: Release the bundle for Ubuntu Linux
- name: Release the bundle for Linux
if: startsWith(github.ref, 'refs/tags/')
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Expand All @@ -69,10 +61,10 @@ jobs:
fi
gh release create ${{ github.ref_name }} ${{ env.BUNDLE_NAME }} --generate-notes --title "${{ github.ref_name }}" $PRERELEASE_FLAG || gh release upload ${{ github.ref_name }} ${{ env.BUNDLE_NAME }} --clobber

- name: Keep workflow artifact within the current workflow namespace (Ubuntu)
- name: Keep workflow artifact within the current workflow namespace (Linux)
uses: actions/upload-artifact@v4
with:
name: ${{ env.BUNDLE_NAME }} # Use the exact bundle name for the artifact
path: ./${{ env.BUNDLE_NAME }} # Specify the full path to the bundle
compression-level: 0 # The .tgz is already compressed, no need to compress again
if-no-files-found: ignore
if-no-files-found: ignore
19 changes: 9 additions & 10 deletions .github/workflows/executable-bundle-macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,16 +45,12 @@ jobs:
echo "PyInstaller created directory: ${BUNDLE_DIR_NAME}"

# Define the output bundle filename
# Consistent naming: config-assessment-tool-macos-<version>-executable.zip
# We check if 'macosx' is present and replace it with 'macos', then append '-executable'

if [[ "$BUNDLE_DIR_NAME" == *"macosx"* ]]; then
BASE_NAME="${BUNDLE_DIR_NAME/macosx/macos}"
else
BASE_NAME="$BUNDLE_DIR_NAME"
# Consistent naming: config-assessment-tool-macos-<version>-arm64-executable.zip
VERSION="${{ github.ref_name }}"
if [[ -z "$VERSION" || ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+([.-].*)?$ ]]; then
VERSION="$(cat ../VERSION)"
fi

BUNDLE_FILENAME="${BASE_NAME}-executable.zip"
BUNDLE_FILENAME="config-assessment-tool-macos-${VERSION}-arm64-executable.zip"

echo "Bundle filename: ${BUNDLE_FILENAME}"

Expand All @@ -64,15 +60,18 @@ jobs:

# Set output variable for subsequent steps
echo "::set-output name=bundle_name::${BUNDLE_FILENAME}"
echo "::set-output name=release_tag::${VERSION}"
echo "Current directory contents after zipping:"
ls -altr

- name: Release the bundle for macOS
uses: softprops/action-gh-release@v2
if: startsWith(github.ref, 'refs/tags/')
if: startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch'
with:
tag_name: ${{ steps.build_bundle.outputs.release_tag }}
files: dist/${{ steps.build_bundle.outputs.bundle_name }}
token: ${{ secrets.GITHUB_TOKEN }}
overwrite_files: true

- name: Keep workflow artifact within the current workflow namespace
uses: actions/upload-artifact@v4
Expand Down
16 changes: 11 additions & 5 deletions .github/workflows/executable-bundle-windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,13 @@ jobs:
$sourcePathFor7z = Join-Path -Path "./dist/appdynamics" -ChildPath $pyinstallerOutputDirName

# Define the desired name for the output zip file
# format: config-assessment-tool-windows-<version>-executable.zip
# We append '-executable' to the end of the base name.
$zipFileName = "${pyinstallerOutputDirName}-executable.zip"
# format: config-assessment-tool-windows-<version>-x86_64-executable.zip
$version = "${{ github.ref_name }}"
if ([string]::IsNullOrWhiteSpace($version) -or ($version -notmatch '^[0-9]+\.[0-9]+\.[0-9]+([.-].*)?$')) {
$version = Get-Content -Path "VERSION" -Raw
$version = $version.Trim()
}
$zipFileName = "config-assessment-tool-windows-${version}-x86_64-executable.zip"
# Define the full path where the zip file should be created (in the ./dist folder)
$zipFilePath = Join-Path -Path "./dist" -ChildPath $zipFileName

Expand All @@ -69,16 +73,18 @@ jobs:
# Set the output variable with the correct zip file name
# This variable will be used by subsequent steps to locate the file
echo "bundle_name=$zipFileName" >> $env:GITHUB_OUTPUT
echo "release_tag=$version" >> $env:GITHUB_OUTPUT

- name: Release the bundle for Windows
uses: softprops/action-gh-release@v2
if: startsWith(github.ref, 'refs/tags/')
if: startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch'
with:
# Reference the output variable correctly using ${{ steps.<step_id>.outputs.<output_name> }}
tag_name: ${{ steps.install_it.outputs.release_tag }}
files: dist/${{ steps.install_it.outputs.bundle_name }}
token: ${{ secrets.GITHUB_TOKEN }}
overwrite_files: true
prerelease: ${{ contains(github.ref_name, '-') }}
prerelease: ${{ contains(steps.install_it.outputs.release_tag, '-') }}

- name: Keep workflow artifact within the current workflow namespace
uses: actions/upload-artifact@v4
Expand Down
87 changes: 87 additions & 0 deletions Dockerfile-rhel-runtime
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
ARG UBI_MAJOR=8

FROM redhat/ubi${UBI_MAJOR}:latest AS python-build

ENV PYTHON_VERSION=3.12.3
ENV LD_LIBRARY_PATH=/usr/local/lib
ENV PATH=/usr/local/bin:${PATH}

RUN dnf install -y \
gcc \
gcc-c++ \
make \
wget \
tar \
gzip \
findutils \
which \
zlib-devel \
bzip2 \
bzip2-devel \
ncurses-devel \
sqlite \
sqlite-devel \
openssl-devel \
libffi-devel \
xz \
xz-devel \
ca-certificates \
&& dnf clean all

WORKDIR /root

RUN wget https://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTHON_VERSION}.tar.xz && \
tar -xf Python-${PYTHON_VERSION}.tar.xz

WORKDIR /root/Python-${PYTHON_VERSION}

RUN ./configure --prefix=/usr/local --with-system-ffi --enable-shared && \
make -j"$(nproc)" && \
make altinstall

WORKDIR /app

COPY Pipfile .
COPY Pipfile.lock .

RUN /usr/local/bin/python3.12 -m pip install --upgrade pip pipenv && \
PIPENV_VENV_IN_PROJECT=1 /usr/local/bin/python3.12 -m pipenv install --deploy

FROM redhat/ubi${UBI_MAJOR}:latest AS runtime

ENV LANG=C.UTF-8
ENV LC_ALL=C.UTF-8
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONFAULTHANDLER=1
ENV PYTHONPATH=/app:/app/backend
ENV LD_LIBRARY_PATH=/usr/local/lib
ENV PATH=/app/.venv/bin:/usr/local/bin:${PATH}

RUN dnf install -y \
bzip2-libs \
libffi \
ncurses-libs \
openssl-libs \
sqlite-libs \
xz-libs \
zlib \
&& dnf clean all

WORKDIR /app

COPY --from=python-build /usr/local /usr/local
COPY --from=python-build /app/.venv /app/.venv

COPY backend /app/backend
COPY frontend /app/frontend
COPY plugins /app/plugins
COPY bin /app/bin
COPY VERSION .
COPY entrypoint.sh /app/entrypoint.sh

RUN chmod +x /app/entrypoint.sh

EXPOSE 8501

ENTRYPOINT ["/app/entrypoint.sh"]
CMD []
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.8.2
1.8.3
Loading
Loading