diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index b3483ce2..bd35c297 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -2,13 +2,6 @@ name: create-release run-name: Create Release on: - workflow_dispatch: - inputs: - tag_name: - description: 'The tag name to release' - default: '' - required: false - type: string push: tags: - "v?[0-9]+.[0-9]+.[0-9]+" @@ -36,30 +29,26 @@ jobs: - name: Extract tag and Details id: release run: | - TAG_NAME="${{ inputs.tag_name }}" - if [[ -z "$TAG_NAME" && "${GITHUB_REF_TYPE}" == "tag" ]]; then + if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then TAG_NAME="${GITHUB_REF#refs/tags/}" else - if [[ -z "$TAG_NAME" ]]; then - echo "No tags found!" - git tag - exit 1 - fi + echo "No tags found!" + exit 1 fi NEW_VERSION=$(echo $TAG_NAME | awk -F'-' '{print $1}') SUFFIX=$(echo $TAG_NAME | grep -oP '[a-z]+[0-9]+' || echo "") echo "new_version=$NEW_VERSION" >> "$GITHUB_OUTPUT" echo "suffix=$SUFFIX" >> "$GITHUB_OUTPUT" echo "tag_name=$TAG_NAME" >> "$GITHUB_OUTPUT" - echo "Version is $NEW_VERSION" - echo "Suffix is $SUFFIX" - echo "Tag name is $TAG_NAME" + echo "New Version is $NEW_VERSION" >> $GITHUB_STEP_SUMMARY + echo "Suffix is $SUFFIX" >> $GITHUB_STEP_SUMMARY + echo "Tag name is $TAG_NAME" >> $GITHUB_STEP_SUMMARY check_pypi: needs: details runs-on: ubuntu-latest steps: - - name: PyiI Information + - name: PyPi Information run: | response=$(curl -s https://pypi.org/pypi/${{ env.PACKAGE_NAME }}/json || echo "{}") latest_previous_version=$(echo $response | jq --raw-output "select(.releases != null) | .releases | keys_unsorted | last") @@ -111,7 +100,7 @@ jobs: run: | python3 -m pip install git+https://github.com/julian-r/python-magic.git - name: Install Python tools - run: gradle installBuildTools installModule + run: gradle installBuildTools sdist - name: Upload artifacts uses: actions/upload-artifact@v3 with: diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml deleted file mode 100644 index 12afcf89..00000000 --- a/.github/workflows/publish.yml +++ /dev/null @@ -1,85 +0,0 @@ -name: publish -run-name: Publish - -on: - workflow_dispatch: - inputs: - gradle_debug_params: - description: 'Gradle debug parameters' - default: '' - required: false - type: string - comment: - description: 'Publish description' - default: 'Push for new revision' - required: false - type: string - revision_type: - description: 'Revision type: Major/Minor/Patch' - type: choice - required: true - default: 'patch' - options: - - 'patch' - - 'minor' - - 'major' - -permissions: - contents: write - -jobs: - publish: - runs-on: ubuntu-latest - outputs: - version: ${{ steps.publish-it.outputs.version }} - steps: - - uses: actions/checkout@v4 - with: - submodules: 'true' - - uses: actions/setup-java@v3 - with: - distribution: temurin - java-version: ${{ vars.JAVA_VERSION }} - - uses: gradle/gradle-build-action@v2 - with: - gradle-version: ${{ vars.GRADLE_VERSION }} - - name: Cache Gradle packages - uses: actions/cache@v3 - with: - path: ~/.gradle/caches - key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} - restore-keys: ${{ runner.os }}-gradle - - uses: actions/setup-python@v3 - with: - python-version: ${{ matrix.python-version }} - - name: Install System packages - run: | - sudo apt-get update - sudo apt-get install -y libmagic1 libmagic-dev portaudio19-dev python3-pyaudio ffmpeg - - name: Update PIP - run: pip install --upgrade pip - - name: Workaround for Python Magic - run: | - python3 -m pip install git+https://github.com/julian-r/python-magic.git - - name: Build preparation - id: build_init - run: | - echo "branch=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" >> $GITHUB_OUTPUT - - name: Install Python tools - run: gradle installBuildTools build copyLicenseAndReadme ${{ inputs.gradle_debug_params }} - - name: Publish - id: publish-it - run: | - bumpver update "--${{ inputs.revision_type }}" - version="$(awk '/./{line=$0} END{print line}' $(find . -type f -name .version))" - echo "version=$( echo "$version" )" >> $GITHUB_OUTPUT - git config --global user.name "$(git log -n 1 --pretty=format:%an)" - git config --global user.email "$(git log -n 1 --pretty=format:%ae)" - git config github.token "${{ secrets.GITHUB_TOKEN }}" - git commit -a -m "[@${{ github.actor }}] ${{ inputs.comment }}" - git pull --rebase -Xtheirs && git push --atomic origin HEAD - git tag -a v"$version" -m "${{ inputs.comment }}" - git push origin --tags - echo "## Revision Information" >> $GITHUB_STEP_SUMMARY - echo "- Branch: ${{ steps.build_init.outputs.branch }}" >> $GITHUB_STEP_SUMMARY - echo "- Version: $version" >> $GITHUB_STEP_SUMMARY diff --git a/build.gradle b/build.gradle index 1d1a6d8a..ca14a9f4 100644 --- a/build.gradle +++ b/build.gradle @@ -40,6 +40,7 @@ ext { apply from: "${gradleDir}/dependencies.gradle" apply from: "${gradleDir}/python.gradle" apply from: "${gradleDir}/versioning.gradle" +apply from: "${gradleDir}/pypi-publish.gradle" apply from: "${gradleDir}/docker.gradle" apply from: "${gradleDir}/docgen.gradle" apply from: "${gradleDir}/idea.gradle" diff --git a/gradle/pypi-publish.gradle b/gradle/pypi-publish.gradle new file mode 100644 index 00000000..c119c4ee --- /dev/null +++ b/gradle/pypi-publish.gradle @@ -0,0 +1,161 @@ +/* + Gradle PyPi publisher extension + + Created: 23rd April, 2021 + License: MIT - Please refer to + Copyright·(c)·2024,·HSPyLib +*/ + +import groovy.json.JsonSlurper + +ext { + pypiRepository = System.getenv("PYPI_REPOSITORY") ?: 'https://test.pypi.org/legacy' + pypiModuleUrl = System.getenv("PYPI_MODULE_URL") ?: 'https://test.pypi.org/pypi' + pypiUsername = System.getenv("PYPI_USERNAME") ?: '' + pypiPassword = System.getenv("PYPI_PASSWORD") ?: '' +} + + +/* Helper Functions -------------------------------------------------------- */ + +Collection dirsByPattern(String baseDir, String pattern) { + def paths = [] + fileTree(baseDir).visit { FileVisitDetails details -> + if (details.isDirectory() && details.name ==~ pattern) paths << details.file.path + } + return paths +} + +String dirName(File file) { + file.getParentFile().getPath() +} + +/* Tasks ------------------------------------------------------------------- */ + +/* Cleanup distribution files from sourceRoot */ +task cleanDist(type: Task) { + group = 'Build' + description = "Cleanup distribution files from sourceRoot" + doLast { + println "Cleanup distribution files \n\t from $sourceRoot" + delete dirsByPattern(sourceRoot, /.*dist$/) + delete dirsByPattern(sourceRoot, /.*build$/) + delete dirsByPattern(sourceRoot, /.*egg-info$/) + } +} + +/* Copy LICENSE and README files into main folder */ +task copyLicenseAndReadme(type: Copy) { + group = 'Publish' + description = "Copy LICENSE file into main folder" + from(rootDir) { + include 'LICENSE*' + include 'README*' + } + into "${sourceRoot}/main" +} + +/* Check files created in dist folder */ +task checkDist(type: Task) { + group = 'Publish' + description = 'Check files created in dist folder' + doLast { + fileTree(sourceRoot).matching { + include "**/setup.py" + }.each { File module -> + def moduleDir = dirName(module) + def distDir = "${moduleDir}/dist" + println "Checking distribution files -> $distDir" + exec { + workingDir moduleDir + commandLine project.python, '-m', 'twine', 'check', "${distDir}/*" + } + } + } +} + +/* Generate PyPi distribution files */ +task sdist(type: Task) { + group = 'Publish' + description = 'Generate PyPi distribution files' + if (!project.hasProperty('no-patch') || !Boolean.valueOf(project.getProperty('no-patch'))) { + dependsOn patchVersion + } + dependsOn cleanDist + dependsOn copyLicenseAndReadme + dependsOn syncRequirements + finalizedBy checkDist + doLast { + fileTree("$sourceRoot").matching { + include "**/setup.py" + }.each { File module -> + def moduleDir = dirName(module) + println "Generating distribution files -> $moduleDir" + exec { + workingDir "$moduleDir" + commandLine project.python, "-m", "build", "--sdist" + } + exec { + workingDir "$moduleDir" + commandLine project.python, "-m", "build", "--wheel" + } + } + } +} + +/* Publish the module to PyPi repository */ +task publish(type: Task) { + group = 'Publish' + description = "Publish the module to PyPi repository" + def url = project.ext.pypiRepository + def un = project.ext.pypiUsername + def pw = project.ext.pypiPassword + doLast { + fileTree("$sourceRoot").matching { + include "**/setup.py" + }.each { File module -> + def moduleDir = dirName(module) + def distDir = "${moduleDir}/dist" + println "--- ${project.name} details ---" + println "|-version: ${project.ext.app_version}" + println "|-setup: ${module}" + println "|-url: ${url}" + println "|-user: ${un}" + println "|-dist: ${distDir}/*" + println '-------------------------------' + println "Publishing module to PyPi => ${url}" + } + exec { + commandLine 'git', 'tag', '-a', "v${app_version}", '-m', "New PyPi version v${app_version}" + } + exec { + commandLine 'git', 'push', 'origin', "v${app_version}" + } + } +} + +/* Show PyPi module details */ +task pypiShow(type: Task) { + group = 'Publish' + description = "Show PyPi module details" + doLast { + def tempDir = System.getenv("TEMP") ?: '/tmp' + def url = project.ext.pypiModuleUrl + "/${app_name}/json" + def outFile = "${tempDir}/${app_name}-info.json" + println("PyPi Instance: " + url) + exec { + commandLine 'curl', '-s', '-o', outFile, url + } + def json = new JsonSlurper().parseText(new File(outFile).getText()) + println("\n--------------------------------------------------------------------------------") + println("|-AppName: ${json.info.package_url}") + println("|-Summary: ${json.info.summary}") + println("|-Version: ${json.info.version}") + println("|-License: ${json.info.license}") + println("|-Python: ${json.info.requires_python}") + println("|-Keywords: \n ${json.info.keywords ? '#' + json.info.keywords.split(',').join(' #') : 'None'}") + println("|-Classifiers: \n ${json.info.classifiers ? '|-' + json.info.classifiers.join('\n |-') : 'None'}") + println("|-Dependencies: \n ${json.info.requires_dist ? '|-' + json.info.requires_dist.join('\n |-') : 'None'} ") + println("--------------------------------------------------------------------------------") + } +} diff --git a/gradle/python.gradle b/gradle/python.gradle index 7b1cb37e..bacf1b30 100644 --- a/gradle/python.gradle +++ b/gradle/python.gradle @@ -192,17 +192,6 @@ task syncPythonPackages(type: Task) { } } -/* Copy LICENSE and README files into main folder */ -task copyLicenseAndReadme(type: Copy) { - group = 'Publish' - description = "Copy LICENSE file into main folder" - from(rootDir) { - include 'LICENSE*' - include 'README*' - } - into "${sourceRoot}/main" -} - /* Install module in editable mode (i.e. setuptools 'develop mode') */ task installModule(type: Task) { group = 'Install' @@ -341,6 +330,7 @@ task mypy(type: Task) { tasks.register('clean', Task) { group = 'Build' dependsOn cleanPython + dependsOn cleanDist } tasks.register('compile', Task) {