Skip to content

[build] Pre-release workflow improvements#16946

Merged
titusfortner merged 5 commits intotrunkfrom
pr/pre-release-improvements
Jan 19, 2026
Merged

[build] Pre-release workflow improvements#16946
titusfortner merged 5 commits intotrunkfrom
pr/pre-release-improvements

Conversation

@titusfortner
Copy link
Member

@titusfortner titusfortner commented Jan 19, 2026

User description

💥 What does this PR do?

  • Allow running pre-release with just major and minor versions specified
  • Remove ruby installation requirement from pre-release workflow
  • Have pre-release get latest from trunk before updating files
  • Have pre-release workflow automatically request and lock trunk via new get-approval.yml workflow

🔧 Implementation Notes

Creates a new reusable get-approval.yml workflow that can be called by other workflows to request approval before proceeding.

💡 Additional Considerations

Plan to reuse get-approval.yml in other PRs.

🔄 Types of changes

  • New feature (non-breaking change which adds functionality)

PR Type

Enhancement


Description

  • Create reusable get-approval.yml workflow for approval notifications

  • Allow pre-release with major.minor versions (auto-normalize to major.minor.0)

  • Remove Ruby installation requirement from pre-release workflow

  • Fetch latest trunk before updating files and lock trunk during release

  • Integrate approval workflow into pre-release pipeline with trunk restriction


Diagram Walkthrough

flowchart LR
  A["Pre-release triggered"] --> B["Get Approval<br/>Slack notification"]
  B --> C["Selenium Manager<br/>Update Rust"]
  C --> D["Restrict Trunk<br/>Lock branch"]
  D --> E["Update Files<br/>Normalize version<br/>Fetch latest trunk"]
  E --> F["Create Release PR"]
Loading

File Walkthrough

Relevant files
Enhancement
get-approval.yml
New reusable approval notification workflow                           

.github/workflows/get-approval.yml

  • New reusable workflow that sends Slack notifications for approval
    requests
  • Requires approval via GitHub production environment before proceeding
  • Accepts title and message as inputs for flexible notification content
  • Uses rtCamp Slack action to notify selenium-tlc channel
+44/-0   
pre-release.yml
Integrate approval workflow and version normalization       

.github/workflows/pre-release.yml

  • Add get-approval job to request Slack notification and approval before
    release
  • Add restrict-trunk job to lock trunk branch during release preparation
  • Remove Ruby installation step and replace with git fetch to get latest
    trunk
  • Add version normalization step to convert major.minor to major.minor.0
    format
  • Update all version references to use normalized version output
  • Reorder job dependencies to include approval and trunk restriction
    gates
+35/-9   

@selenium-ci selenium-ci added the B-build Includes scripting, bazel and CI integrations label Jan 19, 2026
@qodo-code-review
Copy link
Contributor

qodo-code-review bot commented Jan 19, 2026

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
Unpinned GitHub Actions

Description: Multiple third-party GitHub Actions are referenced by mutable tags (e.g.,
rtCamp/action-slack-notify@v2, peter-evans/create-pull-request@v6,
bazel-contrib/[email protected], and actions/checkout@v4) rather than being pinned to a
full commit SHA, which creates a supply-chain risk where a compromised or retagged action
could exfiltrate secrets like SLACK_WEBHOOK_URL or SELENIUM_CI_TOKEN.
pre-release.yml [22-210]

Referred Code
get-approval:
  name: Get Approval
  uses: ./.github/workflows/get-approval.yml
  with:
    title: Release approval needed
    message: |
      Selenium ${{ github.event.inputs.version }} release preparation started.
      Please approve to lock trunk when ready.
  secrets:
    SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}

update-rust:
  name: Update Rust Version
  runs-on: ubuntu-latest
  if: github.event.repository.fork == false
  steps:
    - name: "Checkout repo"
      uses: actions/checkout@v4
      with:
        persist-credentials: false
        fetch-depth: 0


 ... (clipped 168 lines)
Ticket Compliance
🎫 No ticket provided
  • Create ticket/issue
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
🟢
Generic: Comprehensive Audit Trails

Objective: To create a detailed and reliable record of critical system actions for security analysis
and compliance.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Meaningful Naming and Self-Documenting Code

Objective: Ensure all identifiers clearly express their purpose and intent, making code
self-documenting

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Error Handling

Objective: To prevent the leakage of sensitive system information through error messages while
providing sufficient detail for internal debugging.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Logging Practices

Objective: To ensure logs are useful for debugging and auditing without exposing sensitive
information like PII, PHI, or cardholder data.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

🔴
Generic: Robust Error Handling and Edge Case Management

Objective: Ensure comprehensive error handling that provides meaningful context and graceful
degradation

Status:
Missing input validation: The version normalization only handles major.minor and otherwise proceeds without
rejecting malformed versions, which can cause confusing downstream failures without
actionable context.

Referred Code
- name: Normalize version
  id: version
  run: |
    VERSION="${{ github.event.inputs.version }}"
    if [[ "$VERSION" =~ ^[0-9]+\.[0-9]+$ ]]; then
      VERSION="${VERSION}.0"
    fi
    echo "value=$VERSION" >> "$GITHUB_OUTPUT"
- name: Update browser versions

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Security-First Input Validation and Data Handling

Objective: Ensure all data inputs are validated, sanitized, and handled securely to prevent
vulnerabilities

Status:
Shell injection risk: The workflow passes the unvalidated and unquoted version input into a shell command,
allowing a crafted input to alter shell execution.

Referred Code
- name: Normalize version
  id: version
  run: |
    VERSION="${{ github.event.inputs.version }}"
    if [[ "$VERSION" =~ ^[0-9]+\.[0-9]+$ ]]; then
      VERSION="${VERSION}.0"
    fi
    echo "value=$VERSION" >> "$GITHUB_OUTPUT"
- name: Update browser versions
  id: browsers
  run: |
    ./go update_browsers ${{ github.event.inputs.chrome_channel }}
    if git diff --staged --quiet; then
      echo "updated=false" >> "$GITHUB_OUTPUT"
    else
      git commit -m "update pinned browser versions"
      echo "updated=true" >> "$GITHUB_OUTPUT"
    fi
- name: Update devtools versions
  id: devtools
  run: |


 ... (clipped 41 lines)

Learn more about managing compliance generic rules or creating your own custom rules

  • Update
Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label

@qodo-code-review
Copy link
Contributor

qodo-code-review bot commented Jan 19, 2026

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
Possible issue
Grant deployment permissions

Grant deployments: write permission in the get-approval.yml workflow to allow
the authorize job to interact with the production environment.

.github/workflows/get-approval.yml [3]

-permissions: {}
+permissions:
+  deployments: write
  • Apply / Chat
Suggestion importance[1-10]: 9

__

Why: This suggestion correctly identifies a critical issue where the get-approval workflow would fail because it lacks the necessary deployments: write permission to use protected environments, effectively fixing a bug.

High
Validate version format
Suggestion Impact:The workflow's "Normalize version" step was updated to validate the version input and exit with an error when it is not in major.minor or major.minor.patch format (also stripping whitespace and explicitly using bash).

code diff:

           git config --local user.name "Selenium CI Bot"
       - name: Normalize version
         id: version
+        shell: bash
         run: |
           VERSION="${{ github.event.inputs.version }}"
+          VERSION="${VERSION//[[:space:]]/}"
           if [[ "$VERSION" =~ ^[0-9]+\.[0-9]+$ ]]; then
             VERSION="${VERSION}.0"
+          elif [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
+            echo "::error::Invalid version format: '$VERSION'. Expected major.minor or major.minor.patch"
+            exit 1
           fi
           echo "value=$VERSION" >> "$GITHUB_OUTPUT"

Add input validation to the Normalize version step to ensure the version string
is in X.Y or X.Y.Z format, and fail the job if the format is invalid.

.github/workflows/pre-release.yml [137-144]

 - name: Normalize version
   id: version
   run: |
     VERSION="${{ github.event.inputs.version }}"
+    if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+(\.[0-9]+)?$ ]]; then
+      echo "Error: version '${VERSION}' is not in X.Y or X.Y.Z format." >&2
+      exit 1
+    fi
     if [[ "$VERSION" =~ ^[0-9]+\.[0-9]+$ ]]; then
       VERSION="${VERSION}.0"
     fi
     echo "value=$VERSION" >> "$GITHUB_OUTPUT"

[Suggestion processed]

Suggestion importance[1-10]: 6

__

Why: This is a valuable suggestion for improving the workflow's robustness by adding input validation for the version, which prevents potential failures in later steps if an invalid format is provided.

Low
High-level
Use a dedicated environment for approvals

Replace the generic production environment in the get-approval.yml workflow with
a dedicated manual-approval environment. This clarifies its purpose and avoids
conflicts with actual deployment environments.

Examples:

.github/workflows/get-approval.yml [41]
    environment: production

Solution Walkthrough:

Before:

# .github/workflows/get-approval.yml
jobs:
  ...
  authorize:
    name: Authorize
    needs: notify
    runs-on: ubuntu-latest
    environment: production
    steps:
      - name: Approved
        run: echo "Approved"

After:

# .github/workflows/get-approval.yml
jobs:
  ...
  authorize:
    name: Authorize
    needs: notify
    runs-on: ubuntu-latest
    environment: manual-approval
    steps:
      - name: Approved
        run: echo "Approved"
Suggestion importance[1-10]: 7

__

Why: This is a strong design suggestion that improves clarity and future maintainability by using a dedicated environment for approvals, avoiding potential conflicts with actual production deployment rules.

Medium
Learned
best practice
Sanitize reusable workflow inputs

Sanitize/trim inputs.title and inputs.message and fail when blank so the Slack
action isn't invoked with empty/whitespace-only content.

.github/workflows/get-approval.yml [24-35]

 steps:
+  - name: Sanitize inputs
+    id: sanitize
+    shell: bash
+    run: |
+      TITLE="$(echo "${{ inputs.title }}" | xargs)"
+      MESSAGE="$(echo "${{ inputs.message }}" | xargs)"
+      if [[ -z "$TITLE" || -z "$MESSAGE" ]]; then
+        echo "title/message must be non-empty" >&2
+        exit 1
+      fi
+      echo "title=$TITLE" >> "$GITHUB_OUTPUT"
+      echo "message=$MESSAGE" >> "$GITHUB_OUTPUT"
   - name: Slack Notification
     uses: rtCamp/action-slack-notify@v2
     env:
       SLACK_ICON_EMOJI: ":key:"
       SLACK_COLOR: warning
       SLACK_CHANNEL: selenium-tlc
       SLACK_USERNAME: GitHub Workflows
-      SLACK_TITLE: ${{ inputs.title }}
-      SLACK_MESSAGE: ${{ inputs.message }}
+      SLACK_TITLE: ${{ steps.sanitize.outputs.title }}
+      SLACK_MESSAGE: ${{ steps.sanitize.outputs.message }}
       MSG_MINIMAL: actions url
       SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }}
  • Apply / Chat
Suggestion importance[1-10]: 6

__

Why:
Relevant best practice - Add explicit validation/guards at integration boundaries (e.g., reusable workflow inputs) by trimming and validating inputs before use.

Low
General
Explicitly set shell to bash
Suggestion Impact:The workflow step "Normalize version" was updated to explicitly specify `shell: bash`, aligning with the suggestion. Additional validation/normalization logic was also added, but the key requested change was implemented.

code diff:

           git config --local user.name "Selenium CI Bot"
       - name: Normalize version
         id: version
+        shell: bash
         run: |
           VERSION="${{ github.event.inputs.version }}"
+          VERSION="${VERSION//[[:space:]]/}"
           if [[ "$VERSION" =~ ^[0-9]+\.[0-9]+$ ]]; then
             VERSION="${VERSION}.0"
+          elif [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
+            echo "::error::Invalid version format: '$VERSION'. Expected major.minor or major.minor.patch"
+            exit 1
           fi
           echo "value=$VERSION" >> "$GITHUB_OUTPUT"

To improve portability, explicitly set the shell to bash for the Normalize
version step, as it uses bash-specific syntax.

.github/workflows/pre-release.yml [137-144]

 - name: Normalize version
   id: version
+  shell: bash
   run: |
     VERSION="${{ github.event.inputs.version }}"
     if [[ "$VERSION" =~ ^[0-9]+\.[0-9]+$ ]]; then
       VERSION="${VERSION}.0"
     fi
     echo "value=$VERSION" >> "$GITHUB_OUTPUT"

[Suggestion processed]

Suggestion importance[1-10]: 4

__

Why: The suggestion correctly identifies the use of bash-specific syntax and recommends explicitly setting shell: bash, which is a good practice for improving workflow portability and robustness.

Low
  • Update

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR enhances the pre-release workflow by adding an approval gate, supporting major.minor version inputs, removing Ruby dependencies, and improving branch management. The changes introduce a reusable approval workflow and normalize version inputs to ensure consistency.

Changes:

  • Created new get-approval.yml workflow for Slack notifications and production environment approval
  • Added version normalization to convert major.minor to major.minor.0 format
  • Integrated approval and trunk restriction gates into the release pipeline
  • Replaced Ruby installation with git fetch to get latest trunk state

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
.github/workflows/get-approval.yml New reusable workflow that sends Slack notifications and requires production environment approval before proceeding
.github/workflows/pre-release.yml Integrates approval workflow, adds trunk restriction, normalizes version input, and removes Ruby dependency

@titusfortner titusfortner merged commit 7a674bb into trunk Jan 19, 2026
20 checks passed
@titusfortner titusfortner deleted the pr/pre-release-improvements branch January 19, 2026 18:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

B-build Includes scripting, bazel and CI integrations Review effort 2/5

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants