Skip to content

Commit 5147aea

Browse files
committed
update to use plugin for python wheel build
1 parent 8263b59 commit 5147aea

8 files changed

Lines changed: 216 additions & 433 deletions

File tree

.github/workflows/build-wheel.yml

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
name: Build Python Wheel
2+
3+
on:
4+
workflow_call:
5+
inputs:
6+
ref:
7+
description: Git ref to check out
8+
required: false
9+
type: string
10+
default: ""
11+
12+
jobs:
13+
build-wheel:
14+
name: Build Python wheel
15+
runs-on: ubuntu-latest
16+
17+
steps:
18+
- name: Checkout repository
19+
uses: actions/checkout@v7
20+
with:
21+
fetch-depth: 0
22+
ref: ${{ inputs.ref || github.ref }}
23+
24+
- name: Set up Java
25+
uses: actions/setup-java@v5
26+
with:
27+
distribution: temurin
28+
java-version: 21
29+
30+
- name: Set up Gradle
31+
uses: gradle/actions/setup-gradle@v6
32+
33+
- name: Make Gradle wrapper executable
34+
run: chmod +x ./gradlew
35+
36+
- name: Build and test
37+
run: ./gradlew clean build buildPythonWheel
38+
39+
- name: Collect wheel
40+
run: |
41+
mkdir -p dist
42+
find . -path "*/build/install/*/dist/*.whl" -exec cp {} dist/ \;
43+
44+
- name: Upload Python wheel artifact
45+
uses: actions/upload-artifact@v4
46+
with:
47+
name: python-wheel
48+
path: dist/*.whl
49+
if-no-files-found: error
50+
retention-days: 14

.github/workflows/build.yml

Lines changed: 8 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -5,68 +5,22 @@ on:
55
branches:
66
- main
77
pull_request:
8-
release:
9-
types:
10-
- created
118

129
permissions:
1310
contents: read
1411

12+
concurrency:
13+
group: ${{ github.workflow }}-${{ github.ref }}
14+
cancel-in-progress: true
15+
1516
jobs:
16-
build:
17+
build-wheel:
1718
name: Build and test
18-
runs-on: ubuntu-latest
19-
20-
steps:
21-
- name: Checkout repository
22-
uses: actions/checkout@v7
23-
with:
24-
fetch-depth: 0
25-
26-
- name: Set up Java
27-
uses: actions/setup-java@v5
28-
with:
29-
distribution: temurin
30-
java-version: 21
31-
32-
- name: Set up Gradle
33-
uses: gradle/actions/setup-gradle@v6
34-
35-
- name: Make Gradle wrapper executable
36-
run: chmod +x ./gradlew
37-
38-
- name: Build and test
39-
run: ./gradlew clean build buildPythonWheel
40-
- name: Upload Python wheel artifact
41-
uses: actions/upload-artifact@v4
42-
with:
43-
name: python-wheel
44-
path: "**/build/install/*/dist/*.whl"
45-
if-no-files-found: error
46-
47-
publish-wheel:
48-
name: Publish Python wheel to GitHub Release
49-
needs: build
50-
runs-on: ubuntu-latest
51-
if: github.event_name == 'release'
52-
permissions:
53-
contents: write
54-
55-
steps:
56-
- name: Download Python wheel artifact
57-
uses: actions/download-artifact@v4
58-
with:
59-
name: python-wheel
60-
path: dist
61-
62-
- name: Publish wheel to GitHub Release
63-
uses: softprops/action-gh-release@v2
64-
with:
65-
files: dist/**/*.whl
19+
uses: ./.github/workflows/build-wheel.yml
6620

6721
dependency-submission:
6822
name: Submit Gradle dependencies
69-
needs: build
23+
needs: build-wheel
7024
runs-on: ubuntu-latest
7125
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
7226
permissions:
@@ -86,5 +40,4 @@ jobs:
8640
uses: gradle/actions/setup-gradle@v6
8741

8842
- name: Submit Gradle dependencies
89-
uses: gradle/actions/dependency-submission@v6
90-
43+
uses: gradle/actions/dependency-submission@v6

.github/workflows/release.yml

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
name: Release
2+
3+
on:
4+
release:
5+
types:
6+
- published
7+
8+
permissions:
9+
contents: write
10+
actions: read
11+
12+
concurrency:
13+
group: release-${{ github.event.release.id }}
14+
cancel-in-progress: false
15+
16+
jobs:
17+
build-wheel:
18+
name: Build wheel from release tag
19+
uses: ./.github/workflows/build-wheel.yml
20+
with:
21+
ref: ${{ github.event.release.tag_name }}
22+
23+
publish-wheel:
24+
name: Publish Python wheel to GitHub Release
25+
needs: build-wheel
26+
runs-on: ubuntu-latest
27+
28+
steps:
29+
- name: Download Python wheel artifact
30+
uses: actions/download-artifact@v4
31+
with:
32+
name: python-wheel
33+
path: dist
34+
35+
- name: Generate checksums
36+
run: |
37+
cd dist
38+
sha256sum *.whl > SHA256SUMS.txt
39+
40+
- name: Publish wheel to GitHub Release
41+
uses: softprops/action-gh-release@v2
42+
with:
43+
tag_name: ${{ github.event.release.tag_name }}
44+
files: |
45+
dist/*.whl
46+
dist/SHA256SUMS.txt

regi-headless/build.gradle

Lines changed: 76 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -57,31 +57,31 @@ pythonPlugin {
5757

5858
tasks.register('installPythonBuildTools', VenvTask) {
5959
group = 'build setup'
60-
description = 'Installs Python packages needed to build the wheel.'
60+
description = 'Installs Python packages needed to build and test the wheel.'
6161

6262
venvExec = 'pip'
63-
args = ['install', '--upgrade', 'pip', 'build']
64-
}
65-
66-
tasks.register('buildPythonWheel', VenvTask) {
67-
group = "distribution"
68-
description = "Builds a Python .whl file using the Gradle-managed Python environment."
69-
70-
dependsOn bundlePython
71-
dependsOn installPythonBuildTools
63+
args = ['install', '--upgrade', 'pip', 'build', 'pytest']
7264

73-
workingDir = file("${buildDir}/install/regi-python")
74-
venvExec = "python"
75-
args = ["-m", "build", "--wheel"]
65+
outputs.file(layout.buildDirectory.file("python-build-tools/install.marker"))
7666

7767
doLast {
78-
println "Python Wheel built in: ${workingDir}/dist"
68+
def markerFile = layout.buildDirectory.file("python-build-tools/install.marker").get().asFile
69+
markerFile.parentFile.mkdirs()
70+
markerFile.text = "pip build pytest installed\n"
7971
}
8072
}
8173

8274
tasks.register('bundlePython', Sync) {
8375
description = 'Bundles Python scripts and creates the java_lib directory'
84-
into "${buildDir}/install/regi-python/"
76+
77+
dependsOn jar
78+
79+
into layout.buildDirectory.dir("install/regi-python")
80+
81+
inputs.dir("src/main/python")
82+
inputs.file(jar.archiveFile)
83+
inputs.files(configurations.runtimeClasspath)
84+
inputs.property("version", project.version.toString())
8585

8686
from('src/main/python') {
8787
include 'pyproject.toml'
@@ -99,34 +99,70 @@ tasks.register('bundlePython', Sync) {
9999
}
100100
}
101101

102-
tasks.register('testPythonWheel') {
102+
tasks.register('buildPythonWheel', VenvTask) {
103+
group = "distribution"
104+
description = "Builds a Python .whl file using the Gradle-managed Python environment."
105+
106+
dependsOn bundlePython
107+
dependsOn installPythonBuildTools
108+
109+
workingDir = layout.buildDirectory.dir("install/regi-python").get().asFile
110+
venvExec = "python"
111+
args = ["-m", "build", "--wheel"]
112+
113+
inputs.files(fileTree(layout.buildDirectory.dir("install/regi-python")) {
114+
exclude "dist/**"
115+
exclude "build/**"
116+
exclude "*.egg-info/**"
117+
})
118+
inputs.property("version", project.version.toString())
119+
outputs.dir(layout.buildDirectory.dir("install/regi-python/dist"))
120+
121+
doFirst {
122+
delete layout.buildDirectory.dir("install/regi-python/dist")
123+
}
124+
125+
doLast {
126+
println "Python Wheel built in: ${workingDir}/dist"
127+
}
128+
}
129+
130+
tasks.register('installPythonWheelForSmokeTest', VenvTask) {
103131
group = 'verification'
104-
description = 'Creates a venv, installs the wheel, and runs a test script.'
132+
description = 'Installs the built Python wheel into the Gradle-managed Python environment.'
133+
105134
dependsOn buildPythonWheel
106135

136+
venvExec = 'pip'
137+
138+
inputs.files(fileTree(dir: "${buildDir}/install/regi-python/dist", include: '*.whl'))
139+
outputs.file(layout.buildDirectory.file("test-python-wheel/install.marker"))
140+
141+
doFirst {
142+
def wheelFile = fileTree(dir: "${buildDir}/install/regi-python/dist", include: '*.whl').singleFile
143+
args = ['install', '--force-reinstall', wheelFile.absolutePath]
144+
}
145+
107146
doLast {
108-
def venvName = "test_venv"
109-
def wheelDir = "${projectDir}/build/install/regi-headless/dist"
110-
def testScript = "src\\test\\resources\\usace\\rowcps\\headless\\examples\\GateFlowCalc2_Jpype.py"
111-
112-
// 1. Create VENV if it doesn't exist
113-
exec {
114-
commandLine 'cmd', '/c', "python -m venv ${venvName}"
115-
}
116-
117-
// 2. Install Wheel and Run Script
118-
// We chain these using '&&' so they run in the same shell session where the venv is active
119-
exec {
120-
workingDir projectDir
121-
def wheelFile = fileTree(dir: wheelDir, include: '*.whl').singleFile.absolutePath
122-
def venvActivate = file("${venvName}/Scripts/activate.bat").absolutePath
123-
environment 'CDA_URL', project.findProperty('CDA_URL') ?: ""
124-
environment 'API_KEY', project.findProperty('API_KEY') ?: ""
125-
environment 'OFFICE_ID', project.findProperty('OFFICE_ID') ?: ""
126-
environment 'JAVA_HOME', System.getProperty('java.home')
127-
commandLine 'cmd', '/c', "\"${venvActivate}\" && pip install --force-reinstall \"${wheelFile}\" && python -u ${testScript}"
128-
standardOutput = System.out
129-
errorOutput = System.err
130-
}
147+
def wheelFile = fileTree(dir: "${buildDir}/install/regi-python/dist", include: '*.whl').singleFile
148+
def markerFile = layout.buildDirectory.file("test-python-wheel/install.marker").get().asFile
149+
markerFile.parentFile.mkdirs()
150+
markerFile.text = "${wheelFile.name}\n${wheelFile.length()} bytes\n"
131151
}
132152
}
153+
tasks.register('testPythonWheel', VenvTask) {
154+
group = 'verification'
155+
description = 'Runs pytest against the installed Python wheel.'
156+
157+
dependsOn installPythonWheelForSmokeTest
158+
159+
venvExec = 'python'
160+
args = ['-m', 'pytest', 'src/test/python']
161+
162+
inputs.files(fileTree(dir: 'src/test/python', include: '**/*.py'))
163+
outputs.upToDateWhen { false }
164+
}
165+
166+
check {
167+
dependsOn testPythonWheel
168+
}

0 commit comments

Comments
 (0)