Skip to content

Release 2.47.0

Release 2.47.0 #294

Workflow file for this run

name: Release
run-name: Release ${{ inputs.new_tags }}
on:
workflow_dispatch:
inputs:
new_tags:
description: "Release version."
type: string
required: true
python_version:
description: "Python version to use when building binaries."
type: string
required: false
default: "3.12"
artifact_retention_days:
description: "Number of days to retain build artifacts in GitHub Actions."
type: number
required: false
default: 7
timeout_minutes:
description: "Timeout in minutes for jobs in GitHub Actions."
type: number
required: false
default: 10
runs_on:
description: "GitHub Actions runner environment for jobs in the workflow."
type: string
required: false
default: windows-latest
env:
CLI: python -m tools.github_actions.cli.commands
NEW_VERSION: ${{ inputs.new_tags }}
ID: "${{ inputs.new_tags }}_${{ github.ref_name }}_${{ github.run_id }}"
VERSION_CONTROL_PATH: ".github/configs/version_control.json"
VERSION_PY_PATH: "src/subsearch/data/version.py"
MSI_NAME: "Subsearch-${{ inputs.new_tags }}-win64.msi"
EXE_NAME: "Subsearch.exe"
HASHES_NAME: "hashes.sha256"
CHANGELOG_NAME: "changelog.md"
jobs:
init:
name: Initializing environments
runs-on: ${{ inputs.runs_on }}
timeout-minutes: ${{ fromJSON(inputs.timeout_minutes)}} # fromJson because https://github.com/orgs/community/discussions/55332#discussioncomment-5887877
outputs:
current_tags: "${{ steps.current_tags.outputs.tags }}"
previous_tags: "${{ steps.previous_tags.outputs.tags }}"
last_stable_release: "${{ steps.last_stable_release.outputs.tags }}"
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.ref_name }}
- uses: actions/setup-python@v5
with:
python-version: "*"
- name: Validate that the tags are new
run: git tag ${{ inputs.new_tags }}
- name: Validate inputs
id: valid_inputs
run: >
${{ env.CLI }} init
--validate-inputs
"new_tags=${{ inputs.new_tags }};
python_version=${{ inputs.python_version }};
checkout_branch=${{ github.ref_name }}"
- name: Current tags
id: current_tags
run: ${{ env.CLI }} json --read current_version # tags=value
- name: Previous stable tags
id: last_stable_release
run: ${{ env.CLI }} json --read last_stable_release # tags=value
- name: Previous tags
id: previous_tags
run: ${{ env.CLI }} json --read previous_version # tags=value
version_control:
name: Version control
needs: init
runs-on: ${{ inputs.runs_on }}
timeout-minutes: ${{ fromJSON(inputs.timeout_minutes)}}
steps:
- uses: crazy-max/ghaction-import-gpg@v6
with:
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
passphrase: ${{ secrets.GPG_PASSPHRASE }}
git_user_signingkey: true
git_commit_gpgsign: true
git_config_global: true
- uses: actions/checkout@v4
with:
ref: ${{ github.ref_name }}
- uses: actions/setup-python@v5
with:
python-version: "*"
- name: Get previous version
id: version
run: ${{ env.CLI}} python --read-string # version=value
- name: Create new tags
if: ${{ !contains(inputs.new_tags, 'dev') }}
run: git tag -a ${{ inputs.new_tags }} -m "Release ${{ inputs.new_tags }}"
- name: Bump subsearch version
run: ${{ env.CLI}} python --write-string ${{ inputs.new_tags }}
- name: Bump current version
run: ${{ env.CLI }} json -w current_version ${{ inputs.new_tags }}
- name: Bump previous version
run: ${{ env.CLI }} json -w previous_version ${{ needs.init.outputs.current_tags }}
- name: Bump last stable release
if: ${{ !contains(inputs.new_tags, 'dev') }}
run: ${{ env.CLI }} json -w last_stable_release ${{ inputs.new_tags }}
- name: Push commits
run: |
git status
git fetch origin ${{ github.ref_name }}
git add ${{ env.VERSION_PY_PATH }} ${{ env.VERSION_CONTROL_PATH }}
git commit -S -m "Bump version to ${{ inputs.new_tags }}"
git push origin HEAD:${{ github.ref_name }}
- name: Push tags
if: ${{ !contains(inputs.new_tags, 'dev') }}
run: |
git push origin --tags
build_binaries:
name: Build binaries
needs: [init, version_control]
runs-on: ${{ inputs.runs_on }}
timeout-minutes: ${{ fromJSON(inputs.timeout_minutes) }}
outputs:
msi_hash: ${{ steps.hashes.outputs.msi_hash }}
exe_hash: ${{ steps.hashes.outputs.exe_hash }}
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.ref_name }}
- uses: actions/setup-python@v5
with:
python-version: ${{ inputs.python_version }}
- name: Build binaries
id: build
run: |
git fetch origin ${{ github.ref_name }}
python -m pip install --upgrade pip
pip install -e .[build]
python -m tools.build bdist_msi
- name: Create hashes file and set outputs
id: hashes
run: ${{ env.CLI }} binaries --write-hash # suffix_hash=value
- name: Prepare artifacts
run: ${{ env.CLI }} binaries --prepare-build-artifacts
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: build_${{ env.ID }}
path: artifacts
if-no-files-found: error
retention-days: ${{ inputs.artifact_retention_days }}
test_binaries:
name: Test binaries
needs: [init, version_control, build_binaries]
runs-on: ${{ inputs.runs_on }}
timeout-minutes: ${{ fromJSON(inputs.timeout_minutes) }}
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.ref_name }}
- uses: actions/setup-python@v5
with:
python-version: "*"
- uses: actions/download-artifact@v4
id: download
with:
name: build_${{ env.ID }}
path: artifacts
- name: Display structure of downloaded files
run: ls -R
working-directory: ${{ steps.download.outputs.download-path }}
- run: python -m tools.github_actions.jobs.test_binaries
upload_binaries:
name: Upload binaries to virustotal
if: ${{ !contains(inputs.new_tags, 'dev') }}
needs: [init, build_binaries]
runs-on: ${{ inputs.runs_on }}
timeout-minutes: ${{ fromJSON(inputs.timeout_minutes)}}
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.ref_name }}
- uses: actions/download-artifact@v4
id: download
with:
name: build_${{ env.ID }}
path: artifacts
- name: Display structure of downloaded files
run: ls -R
working-directory: ${{ steps.download.outputs.download-path }}
- uses: crazy-max/ghaction-virustotal@v4
with:
vt_api_key: ${{ secrets.VIRUSTOTAL_API_KEY }}
github_token: ${{ secrets.ACTIONS_TOKEN }}
update_release_body: false
request_rate: 4
files: |
artifacts/${{ env.EXE_NAME }}
artifacts/${{ env.MSI_NAME }}
changelog:
name: Changelog
if: ${{ !contains(inputs.new_tags, 'dev') }}
needs: [init, build_binaries]
runs-on: ${{ inputs.runs_on }}
timeout-minutes: ${{ fromJSON(inputs.timeout_minutes)}}
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.ref_name }}
- name: Build
id: build
uses: mikepenz/release-changelog-builder-action@v4
with:
fromTag: ${{ needs.init.outputs.last_stable_release }}
toTag: ${{ inputs.new_tags }}
configuration: .github/configs/changelog_builder.json
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Create markdown
run: |
mkdir "artifacts"
echo "${{ steps.build.outputs.changelog }}" > artifacts/${{ env.CHANGELOG_NAME }}
- name: Update
run: >
${{ env.CLI }} changelog
--tags "${{ inputs.new_tags }};${{ needs.init.outputs.last_stable_release }}"
--file-names "${{ env.MSI_NAME }};${{ env.EXE_NAME }}"
--hashes "${{ needs.build_binaries.outputs.msi_hash }};${{ needs.build_binaries.outputs.exe_hash }}"
- name: Upload changelog artifact
uses: actions/upload-artifact@v4
with:
name: changelog_${{ env.ID }}
path: artifacts
if-no-files-found: error
retention-days: ${{ inputs.artifact_retention_days }}
pr_merge:
name: Create pr and merge
if: ${{ !contains(inputs.new_tags, 'dev') }}
needs: [init, test_binaries, changelog]
runs-on: ${{ inputs.runs_on }}
timeout-minutes: ${{ fromJSON(inputs.timeout_minutes) }}
steps:
- uses: actions/checkout@v4
- uses: crazy-max/ghaction-import-gpg@v6
with:
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
passphrase: ${{ secrets.GPG_PASSPHRASE }}
git_user_signingkey: true
git_commit_gpgsign: true
git_config_global: true
- uses: actions/download-artifact@v4
id: download
with:
path: artifacts
- name: Display structure of downloaded files
run: ls -R
working-directory: ${{ steps.download.outputs.download-path }}
- name: Create PR
run: |
$changelogTitle = "Release ${{ inputs.new_tags }}"
$changelogBody = Get-Content -Raw "artifacts\changelog_${{ env.ID }}\${{ env.CHANGELOG_NAME }}"
git fetch --all
gh pr create -B main -H dev -t "$changelogTitle" -b "$changelogBody" -l "release"
gh pr merge -m
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Synchronize dev with main
run: |
git fetch --all
git checkout dev
git rebase main
git push origin dev --force-with-lease
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
publish_github:
name: Publish to github
if: ${{ !contains(inputs.new_tags, 'dev') }}
needs: [init, test_binaries, changelog, pr_merge]
runs-on: ${{ inputs.runs_on }}
timeout-minutes: ${{ fromJSON(inputs.timeout_minutes)}}
steps:
- uses: crazy-max/ghaction-import-gpg@v6
with:
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
passphrase: ${{ secrets.GPG_PASSPHRASE }}
git_user_signingkey: true
git_commit_gpgsign: true
git_config_global: true
- uses: actions/checkout@v4
with:
ref: ${{ github.ref_name }}
- uses: actions/download-artifact@v4
id: download
with:
path: artifacts
- name: Display structure of downloaded files
run: ls -R
working-directory: ${{ steps.download.outputs.download-path }}
- uses: softprops/action-gh-release@v2
with:
name: ${{ inputs.new_tags }}
tag_name: ${{ inputs.new_tags }}
body_path: artifacts/changelog_${{ env.ID }}/${{ env.CHANGELOG_NAME }}
token: ${{ secrets.ACTIONS_TOKEN }}
prerelease: ${{ contains(inputs.new_tags, 'dev') }}
files: |
artifacts/build_${{ env.ID }}/${{ env.HASHES_NAME }}
artifacts/build_${{ env.ID }}/${{ env.MSI_NAME }}
publish_pypi:
name: Publish to pypi
if: ${{ !contains(inputs.new_tags, 'dev') }}
needs: [version_control, test_binaries, pr_merge]
runs-on: ${{ inputs.runs_on }}
timeout-minutes: ${{ fromJSON(inputs.timeout_minutes) }}
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.ref_name }}
- uses: actions/setup-python@v5
with:
python-version: ${{ inputs.python_version }}
- name: Install requirements
run: |
git fetch origin ${{ github.ref_name }}
python -m pip install --upgrade --disable-pip-version-check pip
python -m pip install --upgrade build twine
- name: Build wheel and source distributions
run: |
python -m build
- name: Upload to pypi
env:
TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}
run: |
twine upload --verbose -u '__token__' dist/*