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
3 changes: 2 additions & 1 deletion .github/workflows/main-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ on:
branches:
- main
- "release/v*"
- nightly-dependency-updates

permissions:
id-token: write
Expand Down Expand Up @@ -184,7 +185,7 @@ jobs:
name: "Publish Main Build Status"
needs: [ build, application-signals-e2e-test ]
runs-on: ubuntu-latest
if: always()
if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/')
steps:
- name: Configure AWS Credentials for emitting metrics
uses: aws-actions/configure-aws-credentials@a03048d87541d1d9fcf2ecf528a4a65ba9bd7838 #v5.0.0
Expand Down
70 changes: 70 additions & 0 deletions .github/workflows/nightly-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
name: Nightly Upstream Snapshot Build

on:
schedule:
- cron: "21 3 * * *"
workflow_dispatch:

env:
BRANCH_NAME: nightly-dependency-updates

jobs:
update-and-create-pr:
runs-on: ubuntu-latest
outputs:
has_changes: ${{ steps.check_changes.outputs.has_changes }}

steps:
- name: Checkout repository
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}

- name: Check if nightly branch already exists
run: |
if git ls-remote --exit-code --heads origin "$BRANCH_NAME"; then
echo "Branch $BRANCH_NAME already exists. Skipping run to avoid conflicts."
echo "Please merge or close the existing PR before the next nightly run."
exit 1
fi

- name: Configure git and create branch
run: |
git config --local user.email "[email protected]"
git config --local user.name "GitHub Action"
git checkout -b "$BRANCH_NAME"

- name: Set up Python
uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c #v6.0.0
with:
python-version: '3.11'

- name: Install Python dependencies
run: pip install requests

- name: Update dependencies
run: python3 scripts/update_dependencies.py

- name: Check for changes and create PR
id: check_changes
run: |
if git diff --quiet; then
echo "No dependency updates needed"
echo "has_changes=false" >> $GITHUB_OUTPUT
else
echo "Dependencies were updated"
echo "has_changes=true" >> $GITHUB_OUTPUT

git add src/AWS.Distro.OpenTelemetry.AutoInstrumentation/AWS.Distro.OpenTelemetry.AutoInstrumentation.csproj build/Build.cs
git commit -m "chore: update OpenTelemetry dependencies to latest versions"
git push origin "$BRANCH_NAME"

gh pr create \
--title "Nightly dependency update: OpenTelemetry packages to latest versions" \
--body "Automated update of OpenTelemetry dependencies to their latest available versions." \
--base main \
--head "$BRANCH_NAME"
fi
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Comment on lines +13 to +70

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}
136 changes: 136 additions & 0 deletions scripts/update_dependencies.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
#!/usr/bin/env python3

import requests
import re
import sys
import xml.etree.ElementTree as ET

def get_latest_version(package_name):
"""Get the latest version of a NuGet package."""
try:
response = requests.get(
f'https://api.nuget.org/v3-flatcontainer/{package_name.lower()}/index.json',
timeout=30
)
response.raise_for_status()

data = response.json()
versions = data.get('versions', [])

if not versions:
print(f"Warning: No versions found for {package_name}")
return None

# Get the latest stable version (avoid pre-release versions for now)
stable_versions = [v for v in versions if not any(pre in v.lower() for pre in ['alpha', 'beta', 'rc', 'preview'])]

if stable_versions:
return stable_versions[-1] # Last version is typically the latest
else:
# If no stable versions, use the latest version
return versions[-1]

except requests.RequestException as request_error:
print(f"Warning: Could not get latest version for {package_name}: {request_error}")
return None

def get_latest_dotnet_instrumentation_version():
"""Get the latest version of opentelemetry-dotnet-instrumentation from GitHub releases."""
try:
response = requests.get(
'https://api.github.com/repos/open-telemetry/opentelemetry-dotnet-instrumentation/releases/latest',
timeout=30
)
response.raise_for_status()

release_data = response.json()
tag_name = release_data['tag_name']

return tag_name

except requests.RequestException as request_error:
print(f"Warning: Could not get latest dotnet-instrumentation version: {request_error}")
return None

def update_csproj_file(file_path):
"""Update OpenTelemetry package versions in a .csproj file."""
try:
# Parse the XML file
tree = ET.parse(file_path)
root = tree.getroot()

updated = False

# Find all PackageReference elements
for package_ref in root.findall('.//PackageReference'):
include = package_ref.get('Include', '')

# Only update OpenTelemetry packages
if include.startswith('OpenTelemetry'):
current_version = package_ref.get('Version', '')
latest_version = get_latest_version(include)

if latest_version and current_version != latest_version:
package_ref.set('Version', latest_version)
updated = True
print(f"Updated {include}: {current_version} → {latest_version}")
elif latest_version:
print(f"{include} already at latest version: {latest_version}")

if updated:
tree.write(file_path, encoding='utf-8', xml_declaration=True)
print("Dependencies updated successfully")
return True
else:
print("No OpenTelemetry dependencies needed updating")
return False

except (ET.ParseError, OSError, IOError) as file_error:
print(f"Error updating dependencies: {file_error}")
sys.exit(1)

def update_build_cs_file(file_path):
"""Update the openTelemetryAutoInstrumentationDefaultVersion in Build.cs."""
try:
latest_version = get_latest_dotnet_instrumentation_version()
if not latest_version:
print("Could not get latest dotnet-instrumentation version")
return False

with open(file_path, 'r', encoding='utf-8') as input_file:
content = input_file.read()

pattern = r'private const string OpenTelemetryAutoInstrumentationDefaultVersion = "v[^"]*";'
replacement = f'private const string OpenTelemetryAutoInstrumentationDefaultVersion = "{latest_version}";'

if re.search(pattern, content):
new_content = re.sub(pattern, replacement, content)

if new_content != content:
with open(file_path, 'w', encoding='utf-8') as output_file:
output_file.write(new_content)
print(f"Updated OpenTelemetryAutoInstrumentationDefaultVersion to {latest_version}")
return True
else:
print(f"OpenTelemetryAutoInstrumentationDefaultVersion already at latest version: {latest_version}")
return False
else:
print("Could not find OpenTelemetryAutoInstrumentationDefaultVersion in Build.cs")
return False

except (OSError, IOError) as file_error:
print(f"Error updating Build.cs: {file_error}")
sys.exit(1)

def main():
csproj_path = 'src/AWS.Distro.OpenTelemetry.AutoInstrumentation/AWS.Distro.OpenTelemetry.AutoInstrumentation.csproj'
build_cs_path = 'build/Build.cs'

csproj_updated = update_csproj_file(csproj_path)
build_cs_updated = update_build_cs_file(build_cs_path)

if not csproj_updated and not build_cs_updated:
print("No updates were made")

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