diff --git a/.github/actions/docker-build/action.yaml b/.github/actions/docker-build/action.yaml index e798de413e..e16511cf78 100644 --- a/.github/actions/docker-build/action.yaml +++ b/.github/actions/docker-build/action.yaml @@ -52,11 +52,25 @@ inputs: description: Path to the Dockerfile to use required: false default: 'docker/Dockerfile' + sealightsDockerfilePath: + description: Path to the Sealights Dockerfile to use + required: false + default: 'docker/Dockerfile.sealights' + buildSealights: + description: Whether to build the Sealights-enabled image + required: false + default: 'false' + sealightsToken: + description: Sealights token for instrumentation + required: false outputs: digest: description: The digest of the built Docker image value: ${{ steps.build.outputs.digest }} + sealights-digest: + description: The digest of the built Sealights Docker image + value: ${{ steps.build-sealights.outputs.digest }} runs: using: composite @@ -100,6 +114,19 @@ runs: labels: | ${{ inputs.imageLabels }} + - name: Extract metadata (tags, labels) for Sealights Docker image + if: ${{ inputs.buildSealights == 'true' }} + id: meta-sealights + uses: docker/metadata-action@v5 + with: + images: ${{ inputs.registry }}/${{ inputs.imageName }} + tags: | + ${{ inputs.imageTags }} + labels: | + ${{ inputs.imageLabels }} + flavor: | + suffix=-sealights + # Hermetic Build Steps - name: Set up hermetic build variables if: ${{ inputs.enableHermeticBuild == 'true' }} @@ -202,6 +229,21 @@ runs: labels: ${{ steps.meta.outputs.labels }} annotations: ${{ steps.meta.outputs.annotations }} platforms: ${{ inputs.platform }} + + - name: Build and push Sealights Docker image (Standard) + if: ${{ inputs.enableHermeticBuild != 'true' && inputs.buildSealights == 'true' }} + uses: docker/build-push-action@v6 + id: build-sealights + with: + context: . + file: ${{ inputs.sealightsDockerfilePath }} + push: ${{ inputs.push }} + provenance: false + tags: ${{ steps.meta-sealights.outputs.tags }} + labels: ${{ steps.meta-sealights.outputs.labels }} + platforms: ${{ inputs.platform }} + build-args: | + SLTOKEN=${{ inputs.sealightsToken }} - name: "Build Docker Image (Hermetic)" id: hermetic-build diff --git a/.ibm/pipelines/utils.sh b/.ibm/pipelines/utils.sh index 27309ef1d1..eb7d725299 100755 --- a/.ibm/pipelines/utils.sh +++ b/.ibm/pipelines/utils.sh @@ -396,7 +396,7 @@ apply_yaml_files() { fi # Create secret for sealight job to pull image from private quay repository. - if [[ "$JOB_NAME" == *"sealight"* ]]; then kubectl create secret docker-registry quay-secret --docker-server=quay.io --docker-username=$RHDH_SEALIGHTS_BOT_USER --docker-password=$RHDH_SEALIGHTS_BOT_TOKEN --namespace="${project}"; fi + if [[ "$JOB_NAME" == *"sealight"* || "$JOB_NAME" == *pull-*-e2e-tests* ]]; then kubectl create secret docker-registry quay-secret --docker-server=quay.io --docker-username=$RHDH_SEALIGHTS_BOT_USER --docker-password=$RHDH_SEALIGHTS_BOT_TOKEN --namespace="${project}"; fi } deploy_test_backstage_customization_provider() { @@ -481,7 +481,7 @@ run_tests() { echo "Yarn install completed successfully." fi - if [[ "$JOB_NAME" == *"sealight"* ]]; then node node_modules/sealights-playwright-plugin/importReplaceUtility.js playwright; fi + if [[ "$JOB_NAME" == *"sealight"* || "$JOB_NAME" == *pull-*-e2e-tests* ]]; then node node_modules/sealights-playwright-plugin/importReplaceUtility.js playwright; fi yarn playwright install chromium @@ -721,7 +721,7 @@ get_image_helm_set_params() { params+="--set upstream.backstage.image.tag=${TAG_NAME} " # Add pull secrets if sealight job - params+=$(if [[ "$JOB_NAME" == *"sealight"* ]]; then echo "--set upstream.backstage.image.pullSecrets[0]='quay-secret'"; fi) + params+=$(if [[ "$JOB_NAME" == *"sealight"* || "$JOB_NAME" == *pull-*-e2e-tests* ]]; then echo "--set upstream.backstage.image.pullSecrets[0]='quay-secret'"; fi) echo "${params}" } @@ -857,7 +857,13 @@ initiate_runtime_deployment() { oc apply -f "$DIR/resources/postgres-db/postgres-cred.yaml" -n "${namespace}" oc apply -f "$DIR/resources/postgres-db/dynamic-plugins-root-PVC.yaml" -n "${namespace}" # Create secret for sealight job to pull image from private quay repository. - if [[ "$JOB_NAME" == *"sealight"* ]]; then kubectl create secret docker-registry quay-secret --docker-server=quay.io --docker-username=$RHDH_SEALIGHTS_BOT_USER --docker-password=$RHDH_SEALIGHTS_BOT_TOKEN --namespace="${namespace}"; fi + if [[ "$JOB_NAME" == *"sealight"* || "$JOB_NAME" == *pull-*-e2e-tests* ]]; then + kubectl create secret docker-registry quay-secret \ + --docker-server=quay.io \ + --docker-username="$RHDH_SEALIGHTS_BOT_USER" \ + --docker-password="$RHDH_SEALIGHTS_BOT_TOKEN" \ + --namespace="$namespace" + fi # shellcheck disable=SC2046 helm upgrade -i "${release_name}" -n "${namespace}" \ diff --git a/docker/Dockerfile.sealights b/docker/Dockerfile.sealights new file mode 100644 index 0000000000..e4de0b031f --- /dev/null +++ b/docker/Dockerfile.sealights @@ -0,0 +1,84 @@ +FROM quay.io/rhdh-community/rhdh:pr-3413 AS sealights +# FROM redhat-developer/rhdh:local AS sealights + +ARG SL_TOKEN +ARG GH_PR_NUMBER +ARG GH_PR_COMMIT +ARG GH_PR_TARGET_BRANCH + + +ENV SL_tokenFile=/opt/app-root/src/sltoken.txt NODE_DEBUG=sl FRONTEND_BUILD_DIR=dist SL_FRONTEND_BUILD_DIR=sl_dist SL_TOKEN=${SL_TOKEN} SL_LOG_LEVEL=debug NODE_DEBUG=sl \ + GH_PR_NUMBER=${GH_PR_NUMBER} GH_PR_COMMIT=${GH_PR_COMMIT} GH_PR_TARGET_BRANCH=${GH_PR_TARGET_BRANCH} + +# RUN echo ${SL_TOKEN} > $SL_tokenFile + +RUN npm install -g slnodejs && npm cache clean --force + +USER root +# RUN chmod +r ${SL_tokenFile} +# RUN chown 1001 ${SL_tokenFile} +USER 1001 + +# Generate build session ID dynamically +# RUN npx slnodejs config --token ${SL_TOKEN} --appname "rhdh" --branch "subhash-local-test6" --build $(date +"%y%m%d_%H%M%S") +RUN npx slnodejs prConfig --token ${SL_TOKEN} --appname "rhdh" --pullRequestNumber ${GH_PR_NUMBER} --targetBranch ${GH_PR_TARGET_BRANCH} --latestCommit ${GH_PR_COMMIT} --repositoryUrl "https://github.com/redhat-developer/rhdh" + +ENV SL_BUILD_SESSION_ID_FILE=/opt/app-root/src/buildSessionId + + +# Update source map relative paths to absolute paths before scanning (plugins only). +RUN cd $CONTAINER_SOURCE && \ + for map_file in $(find plugins -path "*/dist/*.map" -type f); do \ + if grep -q '"sources"' "$map_file"; then \ + plugin_base=${map_file%/dist/*}; \ + sed -i -E "s|\"(\\.\\.?/)+([^\"]*)\"|\"$CONTAINER_SOURCE/$plugin_base/\\2\"|g" "$map_file"; \ + fi; \ + done + +# Declare the plugin list as an ENV variable +ENV PLUGIN_LIST="dynamic-plugins-info-backend licensed-users-info-backend scalprum-backend" + +# Define common scan parameters +ENV SL_SCAN_BASE="slnodejs scan --token ${SL_TOKEN} --buildsessionidFile $SL_BUILD_SESSION_ID_FILE --excludedpaths webpack --scm none --projectroot $CONTAINER_SOURCE" + +# Scan modules with browser instrumentation (frontend and app-next) +RUN $SL_SCAN_BASE --workspacepath "$CONTAINER_SOURCE/packages/app/${FRONTEND_BUILD_DIR}" --uniqueModuleId frontend +RUN $SL_SCAN_BASE --workspacepath "$CONTAINER_SOURCE/packages/app-next/dist" --uniqueModuleId app-next + +# Scan backend module +RUN $SL_SCAN_BASE --workspacepath "$CONTAINER_SOURCE/packages/backend" --uniqueModuleId backend + +# Scan plugins using array iteration +RUN for plugin in $PLUGIN_LIST; do \ + $SL_SCAN_BASE --workspacepath "$CONTAINER_SOURCE/plugins/$plugin/dist" --uniqueModuleId $plugin; \ + done + +RUN slnodejs buildend --buildsessionidFile $SL_BUILD_SESSION_ID_FILE --token ${SL_TOKEN} --ok + +# Define common instrument parameters +ENV SL_INSTRUMENT_BASE="slnodejs instrument --token ${SL_TOKEN} --buildsessionidFile $SL_BUILD_SESSION_ID_FILE --projectroot $CONTAINER_SOURCE" + +# Instrument frontend +RUN $SL_INSTRUMENT_BASE \ + --workspacepath "$CONTAINER_SOURCE/packages/app/${FRONTEND_BUILD_DIR}" \ + --outputpath "$CONTAINER_SOURCE/packages/app/${SL_FRONTEND_BUILD_DIR}" && \ + rm -rf "$CONTAINER_SOURCE/packages/app/${FRONTEND_BUILD_DIR}" && \ + mv "$CONTAINER_SOURCE/packages/app/${SL_FRONTEND_BUILD_DIR}" "$CONTAINER_SOURCE/packages/app/${FRONTEND_BUILD_DIR}" + +# Instrument app-next +RUN $SL_INSTRUMENT_BASE \ + --workspacepath "$CONTAINER_SOURCE/packages/app-next/dist" \ + --outputpath "$CONTAINER_SOURCE/packages/app-next/sl_dist" && \ + rm -rf "$CONTAINER_SOURCE/packages/app-next/dist" && \ + mv "$CONTAINER_SOURCE/packages/app-next/sl_dist" "$CONTAINER_SOURCE/packages/app-next/dist" + + +# RUN echo ${SL_buildSessionId} > buildSessionId + +ENV NODE_OPTIONS="${NODE_OPTIONS} --require /opt/app-root/src/.npm-global/lib/node_modules/slnodejs/lib/preload.js" \ + SL_workspacepath="." \ + SL_useinitialcolor="true" \ + SL_buildSessionIdFile=$SL_BUILD_SESSION_ID_FILE \ + SL_disableCoverageSummaryLogs="true" \ + NODE_DEBUG="" +