Skip to content
Merged
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
160 changes: 102 additions & 58 deletions .ci/unit-tests/python/test_py2cs/test_workflows.py

Large diffs are not rendered by default.

60 changes: 60 additions & 0 deletions .github/actions/bhom-assemblies/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
name: Built BHoM assemblies
description: >
Installs the built assemblies of the repositories in Included-repositories.txt into C:\ProgramData\BHoM\Assemblies, from a cache when none of them
has a new commit, otherwise by cloning and building them (and saving the cache).

runs:
using: composite
steps:
# The built assemblies only change when one of the cloned repositories does, so they are cached under the current commit of each
# repository (the same branch choice as Clone-Repositories.ps1). A new commit anywhere gives a new key, so the cache is never stale.
- name: Find the current commit of each repository
id: commits
shell: pwsh
run: |
$lines = foreach ($repository in (Get-Content Included-repositories.txt | ForEach-Object { $_.Trim() } | Where-Object { $_ -ne "" -and -not $_.StartsWith("#") })) {
$commit = ""
foreach ($branch in "develop", "main", "master") {
$found = git ls-remote "https://github.com/$repository.git" "refs/heads/$branch"
if ($found) { $commit = ($found -split "\s+")[0]; break }
}

if (-not $commit) { throw "Could not find a develop, main or master branch of $repository" }
"$repository $commit"
}

$text = $lines -join "`n"
Write-Host $text
$hash = [System.BitConverter]::ToString([System.Security.Cryptography.SHA256]::Create().ComputeHash([System.Text.Encoding]::UTF8.GetBytes($text))).Replace("-", "").ToLower()
"key=bhom-assemblies-v1-$hash" >> $env:GITHUB_OUTPUT

- name: Restore the built BHoM assemblies
id: assemblies
uses: actions/cache/restore@v4
with:
path: C:\ProgramData\BHoM\Assemblies
key: ${{ steps.commits.outputs.key }}

- uses: microsoft/setup-msbuild@v2
if: steps.assemblies.outputs.cache-hit != 'true'

- uses: NuGet/setup-nuget@v2
if: steps.assemblies.outputs.cache-hit != 'true'

- name: Clone the repositories
if: steps.assemblies.outputs.cache-hit != 'true'
shell: pwsh
run: ./.github/scripts/Clone-Repositories.ps1 -List Included-repositories.txt

- name: Build the repositories in dependency order
if: steps.assemblies.outputs.cache-hit != 'true'
shell: pwsh
run: ./.github/scripts/Build-Repositories.ps1 -List Included-repositories.txt

# Saved right after the build, so a failure later in the job does not lose it
- name: Save the built BHoM assemblies
if: steps.assemblies.outputs.cache-hit != 'true'
uses: actions/cache/save@v4
with:
path: C:\ProgramData\BHoM\Assemblies
key: ${{ steps.commits.outputs.key }}
116 changes: 116 additions & 0 deletions .github/actions/linked-pr-context/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
name: Linked pull request context
description: >
Finds out about the Python pull request (its number, commits, whether it is closed, and whether it comes from a fork), checks out its base and head,
and lists the C# repositories the change touches. Used by the linked C# pull request workflows.

inputs:
pr-number:
description: Number of the Python pull request for a manual run; leave empty for a pull_request event
required: false
default: ''

outputs:
number:
description: The pull request number
value: ${{ steps.pr.outputs.number }}
url:
description: The pull request address
value: ${{ steps.pr.outputs.url }}
merged:
description: true when the pull request was merged
value: ${{ steps.pr.outputs.merged }}
open:
description: true for a pull request of this repository (not a fork) that is not closed
value: ${{ steps.gate.outputs.open }}
raise:
description: true when it is open and the change touches a C# repository
value: ${{ steps.gate.outputs.raise }}
close:
description: true when it is closed and the change touches a C# repository
value: ${{ steps.gate.outputs.close }}
repos:
description: The C# repositories touched, as a JSON list of Owner/Name
value: ${{ steps.repos.outputs.repos }}
names:
description: The same repositories as a comma-separated list of names, for the App token
value: ${{ steps.repos.outputs.names }}

runs:
using: composite
steps:
- name: Find out about the pull request
id: pr
shell: bash
env:
GH_TOKEN: ${{ github.token }}
EVENT: ${{ github.event_name }}
INPUT_NUMBER: ${{ inputs.pr-number }}
run: |
if [ "$EVENT" = "workflow_dispatch" ]; then
data=$(gh api "repos/$GITHUB_REPOSITORY/pulls/$INPUT_NUMBER")
else
data=$(gh api "repos/$GITHUB_REPOSITORY/pulls/${{ github.event.pull_request.number }}")
fi

# Forks never receive the App secrets, so a pull request from a fork gets no linked C# pull request
if [ "$(echo "$data" | jq -r '.head.repo.full_name')" != "$GITHUB_REPOSITORY" ]; then
echo "eligible=false" >> "$GITHUB_OUTPUT"
echo "The pull request is from a fork: no linked C# pull request."
exit 0
fi

{
echo "eligible=true"
echo "number=$(echo "$data" | jq -r '.number')"
echo "url=$(echo "$data" | jq -r '.html_url')"
echo "base_sha=$(echo "$data" | jq -r '.base.sha')"
echo "head_sha=$(echo "$data" | jq -r '.head.sha')"
echo "closed=$([ "$(echo "$data" | jq -r '.state')" = closed ] && echo true || echo false)"
echo "merged=$(echo "$data" | jq -r '.merged')"
} >> "$GITHUB_OUTPUT"

# The tooling (py2cs, the patcher) comes from the pull request, so a fix to it works on the same pull request. The Python before the change
# and the list of repositories a C# pull request may be raised in come from the base branch.
- uses: actions/checkout@v4
if: steps.pr.outputs.eligible == 'true'
with:
ref: ${{ steps.pr.outputs.base_sha }}
path: base

- uses: actions/checkout@v4
if: steps.pr.outputs.eligible == 'true'
with:
ref: ${{ steps.pr.outputs.head_sha }}
path: head

- uses: actions/setup-python@v5
if: steps.pr.outputs.eligible == 'true'
with:
python-version: '3.12'

- name: Which repositories does the change touch?
id: repos
if: steps.pr.outputs.eligible == 'true'
shell: bash
env:
PYTHONPATH: head/.ci/generation
run: |
repos=$(python -m py2cs repos --base-root base/src/bhom_schema --head-root head/src/bhom_schema --allowed-repos base/Converted-repositories.txt)
echo "Repositories: $repos"
echo "repos=$repos" >> "$GITHUB_OUTPUT"
echo "names=$(echo "$repos" | jq -r 'map(split("/")[1]) | join(",")')" >> "$GITHUB_OUTPUT"
echo "any=$([ "$repos" != "[]" ] && echo true || echo false)" >> "$GITHUB_OUTPUT"

- name: What is to be done?
id: gate
shell: bash
env:
ELIGIBLE: ${{ steps.pr.outputs.eligible }}
CLOSED: ${{ steps.pr.outputs.closed }}
ANY: ${{ steps.repos.outputs.any }}
run: |
{
echo "open=$([ "$ELIGIBLE" = true ] && [ "$CLOSED" = false ] && echo true || echo false)"
echo "raise=$([ "$ELIGIBLE" = true ] && [ "$CLOSED" = false ] && [ "$ANY" = true ] && echo true || echo false)"
echo "close=$([ "$ELIGIBLE" = true ] && [ "$CLOSED" = true ] && [ "$ANY" = true ] && echo true || echo false)"
} >> "$GITHUB_OUTPUT"
71 changes: 71 additions & 0 deletions .github/workflows/linked-csharp-pr-close.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
name: Linked C# pull request (close)

# When the Python pull request is closed: unmerged closes the linked C# draft with a comment, merged only comments on it.
# A separate workflow from linked-csharp-pr.yml, so that nothing of it shows on a pull request that is still open.

on:
pull_request:
types: [closed]
paths:
- 'src/bhom_schema/**'
workflow_dispatch:
inputs:
pr_number:
description: Number of the Python pull request (it must be closed)
required: true
type: string
dry_run:
description: List what would be done, change nothing (the App token is still made, which proves the installation)
type: boolean
default: true

permissions:
contents: read

# The same group as linked-csharp-pr.yml: closing the pull request cancels a raise that is still running
concurrency:
group: linked-csharp-pr-${{ github.event.pull_request.number || inputs.pr_number }}
cancel-in-progress: true

jobs:
close:
name: close the C# draft
runs-on: ubuntu-latest
steps:
# The repository itself, only to reach the shared action below
- uses: actions/checkout@v4

- name: Find the pull request and the C# repositories it touches
id: ctx
uses: ./.github/actions/linked-pr-context
with:
pr-number: ${{ inputs.pr_number }}

- name: Make a token for the C# repositories touched
id: token
if: steps.ctx.outputs.close == 'true'
uses: actions/create-github-app-token@v2
with:
app-id: ${{ secrets.BHOM_APP_ID }}
private-key: ${{ secrets.BHOM_APP_PRIVATE_KEY }}
owner: ${{ github.repository_owner }}
repositories: ${{ steps.ctx.outputs.names }}

# Unmerged: the linked draft is closed with a comment. Merged: only a comment.
- name: Close or comment on the linked pull request
if: steps.ctx.outputs.close == 'true'
shell: bash
env:
PYTHONPATH: head/.ci/generation
PY2CS_CSHARP_TOKEN: ${{ steps.token.outputs.token }}
DRY_RUN: ${{ inputs.dry_run }}
MERGED: ${{ steps.ctx.outputs.merged }}
REPOS: ${{ steps.ctx.outputs.repos }}
run: |
flags=""
if [ "$DRY_RUN" = "true" ]; then flags="$flags --dry-run"; fi
if [ "$MERGED" = "true" ]; then flags="$flags --merged"; fi
for repo in $(echo "$REPOS" | jq -r '.[]'); do
python -m py2cs close --repo "$repo" --python-repo "${{ github.repository }}" \
--python-pr "${{ steps.ctx.outputs.number }}" $flags
done
42 changes: 42 additions & 0 deletions .github/workflows/linked-csharp-pr-sweep.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: Linked C# pull request (hourly status)

# Every hour: has the C# pull request of an open Python PR been merged (or closed) since? Nothing tells this repository when that happens.
# This only reads the C# repositories, which must be public, and writes the commit status "linked C# pull request" on this repository.
# A schedule only, so nothing of it shows on a pull request.

on:
schedule:
- cron: '17 * * * *'
workflow_dispatch:

permissions:
contents: read

jobs:
sweep:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
statuses: write
steps:
# The default branch, so the tooling is the trusted one
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: '3.12'

- name: Update the status of every open Python PR that changes the classes
shell: bash
env:
GH_TOKEN: ${{ github.token }}
PYTHONPATH: .ci/generation
PY2CS_PYTHON_TOKEN: ${{ github.token }}
run: |
gh pr list --state open --limit 100 --json number,headRefOid,headRepositoryOwner,files \
--jq '.[] | select(.headRepositoryOwner.login == "${{ github.repository_owner }}") | select(any(.files[]; .path | startswith("src/bhom_schema/"))) | "\(.number) \(.headRefOid)"' |
while read -r number sha; do
echo "Python PR #$number"
python -m py2cs status --python-repo "${{ github.repository }}" --python-pr "$number" --sha "$sha" --repos-file Converted-repositories.txt
done
Loading
Loading