Skip to content
Open
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
28 changes: 27 additions & 1 deletion .github/actions/firefox-ios-milestone/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,15 @@ inputs:
slack_webhook_url_error_channel:
description: "Slack Webhook Url for mobile alerts io channel"
required: true
jenkins-ssh-host:
description: "SSH host for Jenkins Mac"
required: true
jenkins-ssh-user:
description: "SSH user for Jenkins Mac"
required: true
jenkins-ssh-key:
description: "SSH private key for Jenkins Mac"
required: true

runs:
using: "composite"
Expand All @@ -31,9 +40,19 @@ runs:
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Configure SSH for Jenkins
run: |
echo "Host: [${{ inputs.jenkins-ssh-host }}]"
echo "User: [${{ inputs.jenkins-ssh-user }}]"
if [ -z "${{ inputs.jenkins-ssh-key }}" ]; then echo "Key is empty"; else echo "Key is present"; fi
mkdir -p ~/.ssh
echo "${{ inputs.jenkins-ssh-key }}" > ~/.ssh/jenkins_key
chmod 600 ~/.ssh/jenkins_key
ssh-keyscan -H ${{ inputs.jenkins-ssh-host }} >> ~/.ssh/known_hosts
shell: bash
- name: Clone testops-tools repo
run: |
git clone --branch main https://github.com/mozilla-mobile/testops-tools.git ../testops-tools
git clone --branch mb/jenkins-trigger https://github.com/mozilla-mobile/testops-tools.git ../testops-tools
shell: bash

- name: Install dependencies
Expand All @@ -59,8 +78,15 @@ runs:
RELEASE_NAME: ${{ inputs.release-name }}
RELEASE_TAG: ${{ inputs.release-tag }}
SLACK_MOBILE_ALERTS_IOS_CHANNEL: ${{ inputs.slack_webhook_url_error_channel }}
JENKINS_SSH_HOST: ${{ inputs.jenkins-ssh-host }}
JENKINS_SSH_USER: ${{ inputs.jenkins-ssh-user }}
JENKINS_SSH_KEY_PATH: ~/.ssh/jenkins_key
shell: bash

- name: Delete credentials file
run: rm -f .testrail_credentials.json
shell: bash

- name: Cleanup SSH key
run: rm -f ~/.ssh/jenkins_key
shell: bash
12 changes: 11 additions & 1 deletion .github/workflows/create-milestone.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,15 @@ jobs:
create-milestone:
runs-on: ubuntu-latest
steps:
- name: 🕵️ Debug Secrets Check
run: |
if [ -z "${{ secrets.JENKINS_SSH_HOST }}" ]; then
echo "❌ ERROR: El secreto JENKINS_SSH_HOST está VACÍO o no es accesible."
else
echo "✅ El secreto JENKINS_SSH_HOST existe y tiene contenido."
fi
- name: Use reusable milestone action
uses: mozilla-mobile/testops-tools/.github/actions/firefox-ios-milestone@main
uses: mozilla-mobile/testops-tools/.github/actions/firefox-ios-milestone@mb/jenkins-trigger
with:
release-name: ${{ github.event.inputs.release-name }}
release-tag: ${{ github.event.inputs.release-tag }}
Expand All @@ -24,3 +31,6 @@ jobs:
testrail-api-key: ${{ secrets.TESTRAIL_PASSWORD }}
slack_webhook_url: ${{ secrets.WEBHOOK_SLACK_MOBILE_TESTENG_CHANNEL }}
slack_webhook_url_error_channel: ${{ secrets.WEBHOOK_SLACK_MOBILE_ALERTS_IOS_CHANNEL }}
jenkins-ssh-host: ${{ secrets.JENKINS_SSH_HOST }}
jenkins-ssh-user: ${{ secrets.JENKINS_SSH_USER }}
jenkins-ssh-key: ${{ secrets.JENKINS_SSH_KEY }}
138 changes: 138 additions & 0 deletions testrail/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
# Create milestone - Quick Guide

The automation connects GitHub Actions → Bitrise →TestRail → Slack.
Checks Bitrise for new successful iOS release tags.

Detects whether:
- A new mayor version was released (e.g., 145.0), or
- A new RC build was generated (e.g., 145.3 RC4).
- Automatically triggers milestone creation in TestRail.
- Creates test runs for smoke tests.
- Sends release notifications to Slack.


![Architecture Diagram](img/Milestone_Architecture.png)

Link to the documentation: https://docs.google.com/document/d/1LNhfbO7MYoY-nBRM0Dz22PO91SJjNLYyr1fhCuXNZe0/edit?tab=t.0


# Jenkins Remote Job Trigger - Quick Guide
Copy link
Collaborator

Choose a reason for hiding this comment

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

I would call this file README.md to be consistent with the rest of our repos.

Then, since it is inside Testrail folder and there are several actions we do here.. I would have two sections in this doc:

  1. Create Milestones: at some point it would be good to add some info in the README about this
  2. Launch tests: all this that you have documented

That way we have the README with the info needed for this Testrail section...
Does this make sense? Let me know your thoughts


## Prerequisites

- Mac with Jenkins installed locally
- SSH access to the Mac
- Java installed on the Mac

### Check/Install Java
```bash
# Check if Java is installed
java -version

# If not, install with Homebrew
brew install openjdk@17
```

## 1. Download Jenkins CLI
```bash
# Connect to the Mac via SSH
ssh user@mac-ip

# Download jenkins-cli.jar
cd ~
wget http://localhost:8080/jnlpJars/jenkins-cli.jar

# Or with curl
curl -O http://localhost:8080/jnlpJars/jenkins-cli.jar
```

## 2. Generate an API Token in Jenkins if you don't have one

# We alredy have one api token in one password

1. Open Jenkins: `http://localhost:8080`
2. Click on your **user** (top right)
3. Click **"Configure"**
4. In the **"API Token"** section → Click **"Add new Token"**
5. Name: "CLI-Access"
6. Click **"Generate"**
7. **Copy the token** (it is only shown once)

## 4. Create the Script
```bash
# Create the script on the Mac
nano ~/jenkins-trigger.sh
```

**Script contents:**
Copy the jenkins-trigger.sh file contained in this repo

**Give it execute permissions:**
```bash
chmod +x ~/jenkins-trigger.sh
```

## 5. Using the Script

### From the Mac (local)
```bash
# Job without parameters
~/jenkins-trigger.sh MyJob

# Job with one parameter
~/jenkins-trigger.sh MyJob BRANCH=main

# Job with several parameters
~/jenkins-trigger.sh MyJob BRANCH=develop PHONE=iPhone VERSION=18.6
```

### From a remote machine (via SSH)
```bash
# Job without parameters
ssh user@mac-ip "~/jenkins-trigger.sh MyJob"

# Job with parameters
ssh user@mac-ip "~/jenkins-trigger.sh MyJob BRANCH=main PHONE=iPhone"

# Multiple parameters
ssh user@mac-ip "~/jenkins-trigger.sh MyJob BRANCH=hotfix ENV=staging VERSION=2.0.1"
```

## 6. View Logs
```bash
# View the entire log
cat ~/jenkins-trigger.log

# View the last 10 executions
tail -10 ~/jenkins-trigger.log

# View only successful ones
grep "SUCCESS" ~/jenkins-trigger.log

# View only failed ones
grep "FAILED" ~/jenkins-trigger.log

# View today's executions
grep "$(date '+%Y-%m-%d')" ~/jenkins-trigger.log

# Search for a specific job
grep "MyJob" ~/jenkins-trigger.log

# View logs remotely
ssh user@mac-ip "tail -20 ~/jenkins-trigger.log"
```

## 7. Useful Jenkins CLI Commands
```bash
# List jobs
java -jar jenkins-cli.jar -s http://localhost:8080/ -http -auth "user:token" list-jobs

# View user information
java -jar jenkins-cli.jar -s http://localhost:8080/ -http -auth "user:token" who-am-i

# Trigger a job manually (without the script)
java -jar jenkins-cli.jar -s http://localhost:8080/ -http -auth "user:token" build "MyJob" -p PARAM1=value1

# View console output of a build
java -jar jenkins-cli.jar -s http://localhost:8080/ -http -auth "user:token" console "MyJob" -n lastBuild
```
Binary file added testrail/img/Milestone_Architecture.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
50 changes: 50 additions & 0 deletions testrail/jenkins-trigger.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#!/bin/bash

# Configuration
JENKINS_CLI="$HOME/jenkins-cli.jar"
JENKINS_URL="http://localhost:8080/"
JENKINS_USER="jenkins-username"
JENKINS_TOKEN="jenkins-token"
LOG_FILE="$HOME/jenkins-trigger.log"

# Logging function
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}

# Validation
if [ $# -lt 1 ]; then
echo "Uso: $0 <job_name> [PARAM1=value1] [PARAM2=value2]"
exit 1
fi

JOB_NAME=$1
shift

# Parameters
PARAMS=()
PARAMS_LOG=""
for arg in "$@"; do
PARAMS+=(-p "$arg")
PARAMS_LOG="$PARAMS_LOG $arg"
done

# Start Log
if [ -z "$PARAMS_LOG" ]; then
PARAMS_LOG="none"
fi

log "START | Job: $JOB_NAME | Params: $PARAMS_LOG"

# Execute
java -jar "$JENKINS_CLI" -s "$JENKINS_URL" -http -auth "$JENKINS_USER:$JENKINS_TOKEN" build "$JOB_NAME" $PARAMS

# Verify the result
if [ $? -eq 0 ]; then
log "SUCCESS | Job: $JOB_NAME | Job executed successfully"
echo "✓ Job $JOB_NAME started"
else
log "FAILED | Job: $JOB_NAME | Error running the job"
echo "✗ Error running the job $JOB_NAME"
exit 1
fi
16 changes: 12 additions & 4 deletions testrail/testrail_main_ios.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
build_milestone_name,
get_release_type,
get_release_version_ios,
load_testrail_credentials
load_testrail_credentials,
trigger_jenkins_jobs
)

from slack_notifier import (
Expand All @@ -39,6 +40,9 @@

SLACK_MOBILE_TESTENG_RELEASE_CHANNEL = os.environ.get("SLACK_MOBILE_TESTENG_RELEASE_CHANNEL")
SLACK_MOBILE_ALERTS_IOS_CHANNEL = os.environ.get("SLACK_MOBILE_ALERTS_IOS_CHANNEL")
JENKINS_SSH_HOST = os.environ.get("JENKINS_SSH_HOST")
JENKINS_SSH_USER = os.environ.get("JENKINS_SSH_USER")
JENKINS_SSH_KEY_PATH = os.environ.get("JENKINS_SSH_KEY_PATH")

if not SLACK_MOBILE_TESTENG_RELEASE_CHANNEL:
raise ValueError("SLACK_MOBILE_TESTENG_RELEASE_CHANNEL not defined in the environment variable.")
Expand Down Expand Up @@ -86,7 +90,7 @@ def main():
# Release information
release_version = get_release_version_ios(release_tag)
release_type = get_release_type(release_version)

"""
# Build milestone information
milestone_name = build_milestone_name(
testrail_product_type, release_type, release_version
Expand Down Expand Up @@ -154,8 +158,12 @@ def main():
"TESTRAIL_PRODUCT_TYPE": testrail_product_type,
}
send_success_notification_ios(success_values, SLACK_MOBILE_TESTENG_RELEASE_CHANNEL)
except Exception as error_message:
send_error_notification_ios(str(error_message), SLACK_MOBILE_ALERTS_IOS_CHANNEL)
"""
print("\n--- Jenkins Job Triggers ---")
trigger_jenkins_jobs(release_version, shipping_product, JENKINS_SSH_USER, JENKINS_SSH_HOST, JENKINS_SSH_KEY_PATH)

# except Exception as error_message:
# send_error_notification_ios(str(error_message), SLACK_MOBILE_ALERTS_IOS_CHANNEL)

if __name__ == "__main__":
main()
Loading
Loading