diff --git a/.github/workflows/build-push.yaml b/.github/workflows/build-push.yaml index da9fcaa..a2f8fcc 100644 --- a/.github/workflows/build-push.yaml +++ b/.github/workflows/build-push.yaml @@ -1,21 +1,26 @@ -name: Build And Push +name: Build and Push on: - workflow_dispatch: + # 1) Trigger on pull request (e.g., to main branch) for a simple build test + pull_request: + branches: + - main + # 2) Trigger on push to main (and optionally only when certain files change), + # plus allow manual runs push: branches: - main paths: - "VERSION" - ".github/workflows/build-push.yaml" + workflow_dispatch: permissions: contents: "read" id-token: "write" security-events: "write" actions: "read" - packages: "write" - + packages: "write" env: IMAGE: codecollection-devtools @@ -24,16 +29,41 @@ env: GHCR_ORG: "runwhen-contrib" jobs: + # ------------------------------------------------------------------------------ + # JOB 1: Build Test for Pull Requests + # ------------------------------------------------------------------------------ + build-test: + # Only run this job if the event is a Pull Request + if: ${{ github.event_name == 'pull_request' }} + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Build Test + run: | + echo "Running a quick Docker build test..." + docker build -f Dockerfile . + echo "Build test completed." + + # ------------------------------------------------------------------------------ + # JOB 2: Build and Push on Push to Main (or manual trigger) + # ------------------------------------------------------------------------------ build-and-push: + # Only run this job if the event is a 'push' (incl. workflow_dispatch). + # That way PRs won't push images. + if: ${{ github.event_name == 'push' || github.event_name == 'workflow_dispatch' }} runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v2 + - id: 'auth-runwhen' name: 'Authenticate to Google Cloud' uses: 'google-github-actions/auth@v0.4.0' with: workload_identity_provider: ${{ secrets.RUNWHEN_NONPROD_SHARED_WI_PROVIDER }} service_account: ${{ secrets.RUNWHEN_NONPROD_SHARED_WI_SA }} + - name: Set tag and version run: |- if [[ -s VERSION ]]; then @@ -44,45 +74,46 @@ jobs: echo "VERSION file is missing or empty" >&2 exit 1 fi + # Create a 'TAG' environment variable from the branch name + short SHA echo "TAG=$(echo $GITHUB_REF_NAME | sed 's/[^a-zA-Z0-9]/-/g')-${GITHUB_SHA::8}" >> $GITHUB_ENV - name: Configure docker for GCP run: gcloud --quiet auth configure-docker us-docker.pkg.dev - name: Login to GHCR - run: |- - echo "${{ secrets.GITHUB_TOKEN }}" | docker login --username ${{ github.actor }} --password-stdin ghcr.io + run: | + echo "${{ secrets.GITHUB_TOKEN }}" | \ + docker login --username ${{ github.actor }} --password-stdin ghcr.io - - name: Build + - name: Build & Push run: |- docker buildx create --use --name=mybuilder docker buildx inspect --bootstrap docker buildx build \ --push \ --platform linux/amd64 \ - --tag "${{ env.SHARED_ARTIFACT_REPOSITORY_PATH }}/$IMAGE:$VERSION" \ - --tag "${{env.SHARED_ARTIFACT_REPOSITORY_PATH }}/$IMAGE:latest" \ - --tag ghcr.io/$GHCR_ORG/$IMAGE:$VERSION \ - --tag ghcr.io/$GHCR_ORG/$IMAGE:latest \ - --build-arg GITHUB_SHA="$GITHUB_SHA" \ - --build-arg GITHUB_REF="$GITHUB_REF" \ - -f Dockerfile . + --tag "${{ env.SHARED_ARTIFACT_REPOSITORY_PATH }}/${{ env.IMAGE }}:${{ env.VERSION }}" \ + --tag "${{ env.SHARED_ARTIFACT_REPOSITORY_PATH }}/${{ env.IMAGE }}:latest" \ + --tag "ghcr.io/${{ env.GHCR_ORG }}/${{ env.IMAGE }}:${{ env.VERSION }}" \ + --tag "ghcr.io/${{ env.GHCR_ORG }}/${{ env.IMAGE }}:latest" \ + --build-arg GITHUB_SHA="${GITHUB_SHA}" \ + --build-arg GITHUB_REF="${GITHUB_REF}" \ + -f Dockerfile . - name: Notify Slack of Container Build id: slack-publish-nonprod-shared-artifact-repo uses: slackapi/slack-github-action@v1.19.0 with: - channel-id: "#notifications" # Slack channel id or name to post message. https://api.slack.com/methods/chat.postMessage#channels - slack-message: "Just Pushed to ${{env.SHARED_ARTIFACT_REPOSITORY_PATH }}/${{ env.IMAGE }}:${{ env.VERSION }}" + channel-id: "#notifications" + slack-message: "Just Pushed to ${{ env.SHARED_ARTIFACT_REPOSITORY_PATH }}/${{ env.IMAGE }}:${{ env.VERSION }}" env: SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} - - name: Notify Slack of GHCR Push id: slack-deploy-to-ghcr uses: slackapi/slack-github-action@v1.19.0 with: - channel-id: "#codecollections" # Slack channel id or name to post message. https://api.slack.com/methods/chat.postMessage#channels + channel-id: "#codecollections" slack-message: "Just deployed latest version of codecollection-devtools to https://github.com/orgs/runwhen-contrib/packages/container/package/codecollection-devtools" env: - SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} \ No newline at end of file + SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} diff --git a/Dockerfile b/Dockerfile index 7e66ab1..915b6ac 100644 --- a/Dockerfile +++ b/Dockerfile @@ -20,7 +20,7 @@ RUN apt-get update && \ rm -rf /var/lib/apt/lists/* /var/cache/apt # Install Terraform -ENV TERRAFORM_VERSION=1.9.8 +ENV TERRAFORM_VERSION=1.11.2 RUN wget https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip && \ unzip terraform_${TERRAFORM_VERSION}_linux_amd64.zip terraform -d /usr/local/bin/ && \ rm terraform_${TERRAFORM_VERSION}_linux_amd64.zip @@ -33,6 +33,12 @@ RUN mkdir -p $ROBOT_LOG_DIR && \ chown runwhen:0 $ROBOT_LOG_DIR && \ chmod 775 $ROBOT_LOG_DIR +# Set custom TMPDIR +ENV TMPDIR=/tmp/runwhen +RUN mkdir -p $TMPDIR && \ + chown runwhen:0 $TMPDIR && \ + chmod 775 $TMPDIR + # Set up dev scaffolding # COPY --chown=runwhen:0 dev_facade dev_facade COPY --chown=runwhen:0 auth auth diff --git a/ro b/ro index d7225a7..f2e53da 100755 --- a/ro +++ b/ro @@ -1,16 +1,18 @@ #!/bin/bash # ====================================================================================== -# Synopsis: Shorthand for robot run command that outputs logs to a standard location for viewing at localhost:3000 +# Synopsis: Shorthand for robot run command that outputs logs to a standard location +# for viewing at localhost:3000 # ====================================================================================== -function ro () { - ROBOT_FILE_EXECUTING=${!#} +TMPDIR="${TMPDIR:-/tmp/runwhen}" - if [ "$ROBOT_FILE_EXECUTING" = ".." ]; then - echo "Parent directory execution not supported" - exit 1 +function ro () { + # If no arguments given, pretend the user typed '.' + if [ $# -eq 0 ]; then + set -- "." fi + # We'll parse --test arguments first, but we really only need the final target later TASKS=() POSITIONAL=() while [[ $# -gt 0 ]]; do @@ -30,27 +32,90 @@ function ro () { ;; esac done - set -- "${POSITIONAL[@]}" # Restore positional parameters + set -- "${POSITIONAL[@]}" # restore positional parameters - # Default handling for execution targets - if [ "$ROBOT_FILE_EXECUTING" = "." ]; then - ROBOTFILE_DIR_NAME=$PWD - CODEBUNDLE_NAME=$(basename "$ROBOTFILE_DIR_NAME") - OUTPUT_DIR="$ROBOT_LOG_DIR/$CODEBUNDLE_NAME" - TYPE="codebundle" - elif [ -d "$ROBOT_FILE_EXECUTING" ] && ! echo "$ROBOT_FILE_EXECUTING" | grep -q ".robot"; then - ROBOTFILE_DIR_NAME="$ROBOT_FILE_EXECUTING" - CODEBUNDLE_NAME=$(basename "$ROBOTFILE_DIR_NAME") - OUTPUT_DIR="$ROBOT_LOG_DIR/$CODEBUNDLE_NAME" + # The last positional argument is our "execution target" + ROBOT_FILE_EXECUTING=${!#} + + # -------------------------------------------------------------------- + # 1) Expand that target to a full path, then see if it's a file/dir + # -------------------------------------------------------------------- + real_target="$(realpath "$ROBOT_FILE_EXECUTING")" + + if [ -d "$real_target" ]; then + # It's a directory + RW_SLX="$(basename "$real_target")" + RW_RFNS="all" + else + # It's presumably a file (like 'runbook.robot') + dir_of_target="$(dirname "$real_target")" + RW_SLX="$(basename "$dir_of_target")" + RW_RFNS="$(basename "$real_target")" + fi + + export RW_SLX RW_RFNS + echo "[DEBUG] RW_SLX='${RW_SLX}', RW_RFNS='${RW_RFNS}'" + + # -------------------------------------------------------------------- + # 2) Construct a working directory based on RW_SLX / RW_RFNS + # -------------------------------------------------------------------- + runwhen_workdir="${TMPDIR}/${RW_SLX}/${RW_RFNS}" + mkdir -p "${runwhen_workdir}" + echo "RUNWHEN_WORKDIR set to: ${runwhen_workdir}" + + # Create subdirectories for each CLI/tool + azure_config_dir="${runwhen_workdir}/.azure" + mkdir -p "${azure_config_dir}" + + gcloud_config_dir="${runwhen_workdir}/.gcloud" + mkdir -p "${gcloud_config_dir}" + + codebundle_temp_dir="${runwhen_workdir}/cb-temp" + mkdir -p "${codebundle_temp_dir}" + + kube_config_dir="${runwhen_workdir}/.kube" + mkdir -p "${kube_config_dir}" + kubeconfig_path="${kube_config_dir}/config" + + # Export environment variables + export AZURE_CONFIG_DIR="${azure_config_dir}" + echo "AZURE_CONFIG_DIR set to: ${AZURE_CONFIG_DIR}" + + export CLOUDSDK_CONFIG="${gcloud_config_dir}" + echo "CLOUDSDK_CONFIG set to: ${CLOUDSDK_CONFIG}" + + export CODEBUNDLE_TEMP_DIR="${codebundle_temp_dir}" + echo "CODEBUNDLE_TEMP_DIR set to: ${CODEBUNDLE_TEMP_DIR}" + + export KUBECONFIG="${kubeconfig_path}" + echo "KUBECONFIG set to: ${KUBECONFIG}" + + # -------------------------------------------------------------------- + # 3) Figure out Robot output directory (depends on $ROBOT_LOG_DIR, etc.) + # -------------------------------------------------------------------- + # Use your existing logic. For example: + if [ -d "$real_target" ]; then + # All .robot in directory + OUTPUT_DIR="$ROBOT_LOG_DIR/$RW_SLX" TYPE="codebundle" else - ROBOTFILE_DIR_NAME=$(dirname "$ROBOT_FILE_EXECUTING") - CODEBUNDLE_NAME=$(basename "$ROBOTFILE_DIR_NAME") - OUTPUT_DIR="$ROBOT_LOG_DIR/$CODEBUNDLE_NAME" - TYPE=$(basename "$ROBOT_FILE_EXECUTING" .robot) + # Single .robot file + OUTPUT_DIR="$ROBOT_LOG_DIR/$RW_SLX" + TYPE="$(basename "$real_target" .robot)" fi - robot --loglevel trace --outputdir "$OUTPUT_DIR" --log "$TYPE-log.html" --output "$TYPE-output.xml" --report "$TYPE-report.html" "${TASKS[@]}" "${POSITIONAL[@]}" + echo "[DEBUG] Robot logs => $OUTPUT_DIR (TYPE='${TYPE}')" + + # -------------------------------------------------------------------- + # 4) Finally run Robot + # -------------------------------------------------------------------- + robot --loglevel trace \ + --outputdir "$OUTPUT_DIR" \ + --log "${TYPE}-log.html" \ + --output "${TYPE}-output.xml" \ + --report "${TYPE}-report.html" \ + "${TASKS[@]}" \ + "${POSITIONAL[@]}" } ro "$@"