Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
99c97c7
test: connection to azure devops
tsweckard Jan 6, 2026
258b1ff
test2: connection to azure devops
tsweckard Jan 6, 2026
bef2e62
Merge branch 'us/15789-build-pipeline' into us/17033-azure-gh-pipeline
tsweckard Jan 6, 2026
f7b4b85
Merge branch 'us/15789-build-pipeline' into us/17033-azure-gh-pipeline
tsweckard Jan 6, 2026
103eba8
remove pull request creation from pipeline
tsweckard Jan 6, 2026
ad5667c
test devops jar file rename
tsweckard Jan 6, 2026
4a79091
test2 devops jar file rename
tsweckard Jan 6, 2026
c342697
readd the PR creation step
tsweckard Jan 6, 2026
cd628cf
fix: test
tsweckard Jan 6, 2026
6dc7697
fix: test2 + error handling
tsweckard Jan 6, 2026
202f376
fix: test http/1.1 for devops pr
tsweckard Jan 6, 2026
fee274c
fix: test repo ID
tsweckard Jan 6, 2026
47f5472
fix: bad request changes
tsweckard Jan 7, 2026
4ef2f4c
fix: rename added file and add reviewer to PR
tsweckard Jan 7, 2026
136dfd8
debug: list users for reviewers
tsweckard Jan 7, 2026
6943a69
test: reviewer secret
tsweckard Jan 7, 2026
6f35e74
test: code cleanup, abstract variables, separate large steps
tsweckard Jan 7, 2026
6a1a6e1
fix: annoying bug
tsweckard Jan 7, 2026
86517a3
chore: remove test branch exception
tsweckard Jan 7, 2026
21752ac
test: comment changes
tsweckard Jan 12, 2026
fa63b4f
chore: remove test branch filter
tsweckard Jan 12, 2026
5941899
comment: build pipeline documentation
tsweckard Jan 13, 2026
3bd48fb
comment: verify JAR file exists
tsweckard Jan 19, 2026
5e7e493
comment: add Java to push to azure job
tsweckard Jan 19, 2026
003e60d
Merge remote-tracking branch 'origin/us/17033-azure-gh-pipeline' into…
tsweckard Jan 19, 2026
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
148 changes: 148 additions & 0 deletions .github/BUILD-PIPELINE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
# GraphHopper Build Pipeline Documentation

## Overview

The GraphHopper build pipeline (`build.yml`) is a GitHub Actions workflow that automates building, testing, and deploying the GraphHopper routing engine to Azure DevOps. The pipeline runs on every push to the repository.

## Pipeline Structure

### Job 1: Build and Test
**Trigger:** Every push to any branch

This job builds and tests the GraphHopper project across multiple Java versions to ensure compatibility.

**Steps:**
1. **Checkout code** - Retrieves the repository code
2. **Setup Java** - Configures Java using the Temurin distribution
- Tested versions: Java 25 and Java 26-ea (early access)
- Uses a matrix strategy to test both versions in parallel
3. **Cache Maven artifacts** - Caches `~/.m2/repository` to speed up builds
4. **Cache node** - Caches `web-bundle/node` directory
5. **Cache node_modules** - Caches `web-bundle/node_modules` directory
6. **Build and Test** - Runs `mvn -B clean test`

### Job 2: Push to Azure DevOps
**Trigger:** Only runs on successful build when pushing to the `master` branch

This job packages the GraphHopper JAR file and pushes it to the Azure DevOps repository for deployment.

**Configuration Variables:**
- `AZURE_ORG`: trihydro
- `AZURE_PROJECT`: SDX
- `AZURE_REPO`: graphhopper
- `JAVA_VERSION`: 25

**Steps:**
1. **Checkout code** - Retrieves the repository code
2. **Package JAR** - Runs `mvn -B package -DskipTests` to create the JAR file
3. **Get JAR info** - Extracts JAR filename and creates a timestamp
4. **Clone Azure DevOps Repository** - Clones the Azure repo using PAT authentication
5. **Commit and push JAR** - Creates a new branch, backs up old JAR, commits new JAR
6. **Create Pull Request** - Creates PR in Azure DevOps with designated reviewers

## Required Secrets

The following GitHub repository secrets must be configured for the pipeline to work:

### `AZURE_DEVOPS_PAT`
**Type:** Personal Access Token
**Purpose:** Authenticates GitHub Actions with Azure DevOps
**Permissions Required:**
- Code: Read & Write

**How to Update:**
1. Go to Azure DevOps → User Settings → Personal Access Tokens
2. Create a new token or regenerate existing one with the required permissions
3. Copy the token value
4. Go to GitHub repository → Settings → Secrets and variables → Actions
5. Update or create `AZURE_DEVOPS_PAT` secret with the new token value

### `AZURE_GH_REPO_ID`
**Type:** Repository GUID
**Purpose:** Identifies the Azure DevOps repository for API calls

**How to Find:**
1. Run command: `az repos list --organization "https://dev.azure.com/trihydro" --project "SDX" --query "[?name == 'graphhopper'].id" --output tsv`

### `TEAGHEN_DEVOPS_USER_ID` & `CHAN_DEVOPS_USER_ID`
**Type:** User GUID
**Purpose:** Adds Teaghen and Chan as a PR reviewer automatically

**How to Find/Update:**
1. Make API call to: https://vssps.dev.azure.com/trihydro/_apis/graph/users?api-version=7.1-preview.1
1. Authorization header: Basic `<AZURE_DEVOPS_PAT>`
2. Content-Type header: application/json
2. Update the GitHub secret with the originId value.

## Maintenance Guide

### Updating Java Versions
To test against different Java versions:
1. Edit `.github/workflows/build.yml`
2. Modify the `matrix.java-version` array (currently `[25, 26-ea]`)
3. Update the `JAVA_VERSION` environment variable in the `push-to-azure` job if changing the deployment version

### Updating Azure DevOps Configuration
To change the target Azure DevOps organization, project, or repository:
1. Edit `.github/workflows/build.yml`
2. Update the environment variables in the `push-to-azure` job:
- `AZURE_ORG`
- `AZURE_PROJECT`
- `AZURE_REPO`

### Adding/Removing Reviewers
To modify automatic PR reviewers:
1. Add the new reviewer user ID secrets in GitHub repository settings
2. Edit the `Create Pull Request in Azure DevOps` step in `build.yml`
3. Add/remove reviewer objects in the `reviewers` array of the PR payload

### Monitoring Secrets Expiration
**Recommended Schedule:**
- Azure DevOps PATs typically expire after 90 days depending on configuration
- Set up calendar reminders 2 weeks before known expiration dates

### Troubleshooting Common Issues

**Build fails but tests pass locally:**
- Check Java version compatibility (pipeline uses Java 25/26)
- Clear Maven cache by removing the cache action temporarily

**Azure push fails with an authentication error:**
- `AZURE_DEVOPS_PAT` has likely expired - regenerate it
- Verify the PAT has Code and Pull Request permissions

**Pull Request creation fails:**
- Verify `AZURE_GH_REPO_ID` is correct
- Check that reviewer IDs are valid and users have access to the repository
- Ensure the target branch (master) exists in Azure DevOps repo

## Workflow Diagram

```
┌─────────────────┐
│ Push Event │
└────────┬────────┘
┌─────────────────────────┐
│ Build & Test Job │
│ - Java 25 │
│ - Java 26-ea │
│ - Maven clean test │
└────────┬────────────────┘
[master branch?]
│ Yes
┌─────────────────────────┐
│ Push to Azure Job │
│ 1. Package JAR │
│ 2. Clone Azure repo │
│ 3. Create branch │
│ 4. Commit JAR │
│ 5. Push branch │
│ 6. Create PR │
└─────────────────────────┘
```

134 changes: 126 additions & 8 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
name: Build and Test
on: push

jobs:
build:
runs-on: ubuntu-latest
Expand Down Expand Up @@ -36,14 +37,131 @@ jobs:
${{ runner.os}}-node_modules-
- name: Build ${{ matrix.java-version }}
run: mvn -B clean test

push-to-azure:
runs-on: ubuntu-latest
needs: build
if: github.ref == 'refs/heads/master'
env:
AZURE_ORG: trihydro
AZURE_PROJECT: SDX
AZURE_REPO: graphhopper
JAVA_VERSION: 25
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
java-version: ${{ env.JAVA_VERSION }}
distribution: temurin
cache: maven

- name: Package JAR
if: github.ref == 'refs/heads/master'
run: mvn -B package -DskipTests
- name: Upload JAR Artifact
if: github.ref == 'refs/heads/master'
uses: actions/upload-artifact@v4
with:
name: graphhopper-jar-${{ matrix.java-version }}
path: web/target/*.jar
retention-days: 90

- name: Get JAR info and set date
id: jar-info
run: |
JAR_FILE=$(ls web/target/*.jar | head -n 1)
if [ -z "$JAR_FILE" ] || [ ! -f "$JAR_FILE" ]; then
echo "Error: No JAR file found in web/target/. Maven package step may have failed to produce a JAR." >&2
exit 1
fi
JAR_NAME=$(basename "$JAR_FILE" | sed 's/-SNAPSHOT//')
DATE=$(date +%Y%m%d-%H%M%S)

{
echo "jar_file=$JAR_FILE"
echo "jar_name=$JAR_NAME"
echo "date=$DATE"
} >> "$GITHUB_OUTPUT"

- name: Clone Azure DevOps Repository
env:
AZURE_DEVOPS_PAT: ${{ secrets.AZURE_DEVOPS_PAT }}
run: |
git clone https://$AZURE_DEVOPS_PAT@dev.azure.com/$AZURE_ORG/$AZURE_PROJECT/_git/$AZURE_REPO azure-repo

- name: Commit and push JAR to new branch
working-directory: azure-repo
run: |
# Set variables
JAR_FILE="${{ steps.jar-info.outputs.jar_file }}"
JAR_NAME="${{ steps.jar-info.outputs.jar_name }}"
BUILD_DATE="${{ steps.jar-info.outputs.date }}"
COMMIT_SHA="${{ github.sha }}"

# Configure git
git config user.name "GitHub Actions Bot"
git config user.email "github-actions@users.noreply.github.com"

# Create a new branch
BRANCH_NAME="update-graphhopper-jar-$BUILD_DATE"
git checkout -b $BRANCH_NAME

# Create resources directory if it doesn't exist
mkdir -p resources

# Rename existing JAR file if it exists
if [ -f "resources/$JAR_NAME" ]; then
OLD_NAME="resources/$(basename $JAR_NAME .jar)-old-$BUILD_DATE.jar"
mv "resources/$JAR_NAME" "$OLD_NAME"
fi

# Copy new JAR file
cp ../$JAR_FILE resources/$JAR_NAME

# Commit changes
git add resources/
git commit -m "Update GraphHopper JAR from GitHub build - $BUILD_DATE" \
-m "Built from commit: $COMMIT_SHA" \
-m "Java version: $JAVA_VERSION"

# Push the branch
git push origin $BRANCH_NAME

# Save branch name for PR creation
echo "BRANCH_NAME=$BRANCH_NAME" >> $GITHUB_ENV

- name: Create Pull Request in Azure DevOps
env:
AZURE_DEVOPS_PAT: ${{ secrets.AZURE_DEVOPS_PAT }}
AZURE_GH_REPO_ID: ${{ secrets.AZURE_GH_REPO_ID }}
REVIEWER_ID_TEAGHEN: ${{ secrets.TEAGHEN_DEVOPS_USER_ID }}
REVIEWER_ID_CHAN: ${{ secrets.CHAN_DEVOPS_USER_ID }}
run: |
# Set variables
BUILD_DATE="${{ steps.jar-info.outputs.date }}"
COMMIT_SHA="${{ github.sha }}"
AUTH_HEADER=$(echo -n ":${AZURE_DEVOPS_PAT}" | base64 | tr -d '\n')

PR_PAYLOAD=$(cat <<EOF
{
"sourceRefName": "refs/heads/${{ env.BRANCH_NAME }}",
"targetRefName": "refs/heads/master",
"title": "Update GraphHopper JAR - $BUILD_DATE",
"description": "Automated PR to update GraphHopper JAR file.\n\n**Source:** GitHub repository\n**Commit:** $COMMIT_SHA\n**Java Version:** $JAVA_VERSION\n**Build Date:** $BUILD_DATE\n\nThis JAR was automatically built and uploaded by GitHub Actions.",
"reviewers": [
{
"id": "${REVIEWER_ID_TEAGHEN}"
},
{
"id": "${REVIEWER_ID_CHAN}"
}
]
}
EOF
)

# Make API request
HTTP_CODE=$(curl -sSL -w "%{http_code}" -o /tmp/pr_response.json \
-X POST \
-H "Content-Type: application/json" \
-H "Authorization: Basic $AUTH_HEADER" \
-d "$PR_PAYLOAD" \
"https://dev.azure.com/${AZURE_ORG}/${AZURE_PROJECT}/_apis/git/repositories/${AZURE_GH_REPO_ID}/pullrequests?api-version=7.1")

if [ "$HTTP_CODE" -ne 201 ]; then
echo "Failed to create Pull Request (HTTP $HTTP_CODE)"
cat /tmp/pr_response.json
exit 1
fi