29 Commits

Author SHA1 Message Date
0e35c82dec Fix workflow 2024-08-27 23:50:05 -07:00
2a04aa00a8 Release Version 1.4.3
### Fixed

- Fixed package missing the cli module in some circumstances

### Changed

- Added the `body-file` output to the github action. `body_file` still exists but is aliased to `body-file`
2024-08-27 23:42:06 -07:00
fbcd178205 update changelog 2024-08-27 23:41:23 -07:00
c37387360b update docs 2024-08-27 23:39:31 -07:00
fe8c38f62f better debug logging 2024-08-27 23:04:34 -07:00
d8ba08cc6a fine, be that way 2024-08-27 22:59:59 -07:00
ad19a2b530 🙄 2024-08-27 22:56:19 -07:00
4f22d74721 run with markdown 2024-08-27 22:52:01 -07:00
a6259aa1b3 action self-test 2024-08-27 22:48:55 -07:00
aad894fa08 Add body-file output, alias body_file to it 2024-08-27 22:27:24 -07:00
e31a8d094e Redo workflow
why do I do this to myself
2024-08-27 21:18:50 -07:00
0ca8609bb7 Try to guess version from action ref 2024-08-27 01:42:29 -07:00
394cac155f Fix possible exclusion of yaclog.cli 2024-08-27 01:42:18 -07:00
4d57ef2fb0 fix deploy permissions 2024-08-27 01:03:09 -07:00
4626e25838 Release Version 1.4.2
### Fixed

- Fixed package failing to install without git history

### Added

- Added the ability to specify the changelog path in the action
2024-08-27 00:51:21 -07:00
5373cb9b48 Add ability to specify changelog path 2024-08-27 00:49:40 -07:00
e3fc69d305 minor action tweaks
(cherry picked from commit 73a5ae0f9b7e64f2c52d9928a9e3a7fc9d49555d)
2024-08-27 00:36:04 -07:00
d61208b583 Add pretend version when installing in action 2024-08-27 00:20:53 -07:00
2a39c69700 Setup pypi trusted publishing 2024-08-26 23:30:05 -07:00
7a8b3c7160 Release Version 1.4.1
### Fixed

- Fixed escape characters being included in github actions body file

### Added

- Added pypi tags for python 3.11 and 3.12
2024-08-24 21:25:46 -07:00
b0d6288ae8 Release Version 1.4.0
### Added

- added a github action to the repository. The action can create new releases and fetch version information. For mor information see the "Github Actions" page in the handbook
2024-08-24 20:53:01 -07:00
bc6d0e1886 Document how action works 2024-08-24 20:29:44 -07:00
76d2d55af8 fix syntax error 2024-08-21 22:39:51 -07:00
fe3bd2f604 Turns out that was important 2024-08-21 22:39:25 -07:00
e701a33ce5 Use pipx to ensure command in path
idk why I forgot this was an option
2024-08-21 22:35:32 -07:00
1f01bda2f4 dogfood own action 2024-08-20 00:28:48 -07:00
629d931979 Don't trample over existing python installs 2024-08-20 00:28:38 -07:00
d2296fb926 name and description 2024-08-19 23:31:42 -07:00
80e35de136 Add github action for getting version info and making releases 2024-08-19 23:30:45 -07:00
11 changed files with 486 additions and 136 deletions

148
.github/workflows/build.yml vendored Normal file
View File

@ -0,0 +1,148 @@
# This workflow will upload a Python Package using Twine when a release is created
# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries
name: build
on: [ push, pull_request ]
jobs:
test:
name: Test Python Module
runs-on: ubuntu-22.04
strategy:
matrix:
python-version: [ "3.8", "3.9", "3.10", "3.11", "3.12" ]
click-version: [ "click~=8.0" ]
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5.1.1
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install flake8
python -m pip install ${{ matrix.click-version }}
- name: Lint with flake8
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
- name: Install module
run: python -m pip install .
- name: Run Unit Tests
run: python -m unittest -v
test-action:
name: Test Github Action
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- name: Get Changelog Information
uses: ./
id: yaclog-show
with:
changelog-path: 'tests/Test-Changelog.md'
- name: Copy Body File
run:
cp ${{ steps.yaclog-show.outputs.body-file }} body.md
- name: Fail
if: >
!(
steps.yaclog-show.outputs.name == '0.13.0 "Aquarius"' &&
steps.yaclog-show.outputs.header == '## 0.13.0 "Aquarius" - 1970-04-11 [YANKED]' &&
steps.yaclog-show.outputs.version == '0.13.0' &&
endsWith(steps.yaclog-show.outputs.changelog, 'tests/Test-Changelog.md') &&
hashFiles('body.md') == 'ad49b5c946b7d361db1c3dacc73de4f6222cca6272aab426786de168eede702b'
)
run: |
echo "Action self-test failed!"
echo "${{ toJSON(steps.yaclog-show.outputs) }}"
echo "${{ hashFiles('body.md') }}"
false
build:
name: Build Distribution
needs:
- test
- test-action
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5.1.1
with:
python-version: '3.12'
- name: Install pypa/build
run: python -m pip install build --user
- name: Build a binary wheel and source tarball
run: python -m build --sdist --wheel --outdir dist/
- uses: actions/upload-artifact@v4
with:
name: python-distribution
path: dist/
compression-level: 0 # already compressed
publish-pypi:
name: Deploy to PyPI
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
needs: build
runs-on: ubuntu-22.04
environment:
name: Publish
url: https://pypi.org/project/yaclog/${{ github.ref_name }}
permissions:
id-token: write
steps:
- uses: actions/download-artifact@v4
with:
name: python-distribution
path: dist/
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
publish-github:
name: Deploy to Github
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
needs: build
runs-on: ubuntu-22.04
environment:
name: Publish
url: https://github.com/${{ github.repository }}/releases/tag/${{ github.ref_name }}
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
name: python-distribution
path: dist/
- name: Get Changelog Information
id: yaclog-show
uses: ./ # self-hosting!
- name: Publish to Github
run: >
gh release create ${{ github.ref_name }}
--notes-file "${{ steps.yaclog-show.outputs.body-file }}"
--title "${{ steps.yaclog-show.outputs.name }}"
dist/*
env:
GH_TOKEN: ${{ github.token }}

View File

@ -1,84 +0,0 @@
# This workflow will upload a Python Package using Twine when a release is created
# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries
name: build
on: [ push, pull_request ]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [ "3.8", "3.9", "3.10", "3.11", "3.12" ]
click-version: [ "click~=8.0" ]
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5.1.1
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install flake8
python -m pip install ${{ matrix.click-version }}
- name: Install module
run: python -m pip install .
- name: Lint with flake8
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
- name: Run unit tests
run: python -m unittest -v
deploy:
needs: test
runs-on: ubuntu-latest
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5.1.1
with:
python-version: '>=3.8'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install setuptools wheel twine
python -m pip install . # Self hosting!
- name: Install pypa/build
run: python -m pip install build --user
- name: Build a binary wheel and source tarball
run: python -m build --sdist --wheel --outdir dist/
- name: Get version name and body
run: |
echo "VERSION_TILE=$(yaclog show -n)" >> $GITHUB_ENV
echo "$(yaclog show -mb)" >> RELEASE.md
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
password: ${{ secrets.PYPI_API_TOKEN }}
- name: Publish to Github
uses: softprops/action-gh-release@v2
with:
files: dist/*
name: ${{ env.VERSION_TITLE }}
body_path: RELEASE.md
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -2,31 +2,71 @@
All notable changes to this project will be documented in this file All notable changes to this project will be documented in this file
## Version 1.4.3 - 2024-08-28
### Fixed
- Fixed package missing the cli module in some circumstances
### Changed
- Added the `body-file` output to the github action. `body_file` still exists but is aliased to `body-file`
## Version 1.4.2 - 2024-08-27
### Fixed
- Fixed package failing to install without git history
### Added
- Added the ability to specify the changelog path in the action
## Version 1.4.1 - 2024-08-25
### Fixed
- Fixed escape characters being included in github actions body file
### Added
- Added pypi tags for python 3.11 and 3.12
## Version 1.4.0 - 2024-08-25
### Added
- Added a github action to the repository. The action can create new releases and fetch version information. For more information see the "Github Actions" page in the handbook
## Version 1.3.0 - 2024-08-08 ## Version 1.3.0 - 2024-08-08
### Added ### Added
- added a `--version` option to `yaclog show` that prints just the version number - Added a `--version` option to `yaclog show` that prints just the version number
### Changed ### Changed
- removed support for Click 7 as a dependency - Removed support for Click 7 as a dependency
## Version 1.2.0 - 2024-04-16 ## Version 1.2.0 - 2024-04-16
### Added ### Added
- added the `-s` option to `yaclog release` to increment arbitrary version segments - Added the `-s` option to `yaclog release` to increment arbitrary version segments
- added the `-n` option to `yaclog release` to create a new release instead of releasing a new one - Added the `-n` option to `yaclog release` to create a new release instead of releasing a new one
- added the `-y` option to `yaclog release` to answer "yes" to all confirmation dialogs. Use with caution! - Added the `-y` option to `yaclog release` to answer "yes" to all confirmation dialogs. Use with caution!
## Version 1.1.2 - 2022-12-29 ## Version 1.1.2 - 2022-12-29
### Changed ### Changed
- yaclog now only tries to use git when invoked with a command that needs it, meaning most sub commands can now be used on systems without git - Yaclog now only tries to use git when invoked with a command that needs it, meaning most sub commands can now be used on systems without git
## Version 1.1.1 - 2022-08-15 ## Version 1.1.1 - 2022-08-15

69
action.yaml Normal file
View File

@ -0,0 +1,69 @@
name: Yaclog
description: Get version information from a changelog
branding:
icon: file-text
color: orange
inputs:
changelog-path:
description: "Path of the changelog markdown file"
markdown:
description: If outputs should be in markdown format or not
default: 'true'
release:
description: >
Creates a new release and commits it if set. Directly passed to the arguments of `yaclog release`.
Can be a version number or an increment tag like `--major`, `--minor`, or `--patch`.
The resulting commit and tag will NOT be pushed back to the repo. You must add a step to do this yourself
outputs:
name:
description: "The current version name. For example, `Version 1.3.0`"
value: ${{ steps.yaclog-show.outputs.name}}
header:
description: "The entire header for the current version. For example, `Version 1.3.0 - 2024-08-08`"
value: ${{ steps.yaclog-show.outputs.header }}
version:
description: "The current version number. For example, `1.3.0`"
value: ${{ steps.yaclog-show.outputs.version }}
body-file:
description: "Path to a temporary file containing the version body"
value: ${{ steps.yaclog-show.outputs.body-file }}
body_file:
description: "Alias for body-file"
value: ${{ steps.yaclog-show.outputs.body-file }}
changelog:
description: "Path to the entire changelog file."
value: ${{ steps.yaclog-show.outputs.changelog }}
runs:
using: "composite"
steps:
- id: setup-python
uses: actions/setup-python@v5
with:
python-version: '3.12'
update-environment: 'false'
- name: Setup Yaclog
shell: bash
run: |
[[ "$ACTION_REF" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] && export SETUPTOOLS_SCM_PRETEND_VERSION_FOR_YACLOG="$ACTION_REF"
pipx install --python ${{ steps.setup-python.outputs.python-path }} ${{ github.action_path }}
env:
ACTION_REF: ${{ github.action_ref }}
- name: Create New Release
shell: bash
if: ${{ inputs.release }}
run: yaclog release --yes --commit ${{ inputs.release }}
- name: Get Changelog Information
id: yaclog-show
shell: bash
run: >
yaclog ${{ inputs.changelog-path && format('--path {0}', inputs.changelog-path) }}
show ---gh-actions ${{ inputs.markdown && '--markdown' }}
| tee -a "$GITHUB_OUTPUT"

View File

@ -4,7 +4,7 @@
# list see the documentation: # list see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html # https://www.sphinx-doc.org/en/master/usage/configuration.html
from pkg_resources import get_distribution from importlib.metadata import version
# -- Path setup -------------------------------------------------------------- # -- Path setup --------------------------------------------------------------
@ -22,8 +22,9 @@ sys.path.insert(0, os.path.abspath('..'))
project = 'Yaclog' project = 'Yaclog'
copyright = '2021, Andrew Cassidy' copyright = '2021, Andrew Cassidy'
author = 'Andrew Cassidy' author = 'Andrew Cassidy'
release = get_distribution('yaclog').version release = version('yaclog')
version = '.'.join(release.split('.')[:3]) version = '.'.join(release.split('.')[:3])
ref = version if len(release.split('.')) == 3 else 'main'
# -- General configuration --------------------------------------------------- # -- General configuration ---------------------------------------------------
@ -36,9 +37,13 @@ extensions = [
'sphinx_rtd_theme', 'sphinx_rtd_theme',
'sphinx.ext.autodoc', 'sphinx.ext.autodoc',
'sphinx.ext.intersphinx', 'sphinx.ext.intersphinx',
'sphinx_jinja'
] ]
myst_heading_anchors = 2 myst_heading_anchors = 2
myst_enable_extensions = [
"colon_fence"
]
# Add any paths that contain templates here, relative to this directory. # Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates'] templates_path = ['_templates']
@ -76,6 +81,8 @@ autodoc_default_options = {
'undoc-members': True, 'undoc-members': True,
} }
# -- Options for Intersphinx ------------------------------------------------- # -- Options for Intersphinx -------------------------------------------------
# This config value contains the locations and names of other projects that # This config value contains the locations and names of other projects that
@ -85,3 +92,9 @@ intersphinx_mapping = {
'python': ('https://docs.python.org/3', None), 'python': ('https://docs.python.org/3', None),
'packaging': ('https://packaging.pypa.io/en/latest/', None), 'packaging': ('https://packaging.pypa.io/en/latest/', None),
} }
jinja_globals = {
'version': version,
'release': release,
'ref': ref,
}

View File

@ -34,45 +34,6 @@ Tags are additional metadata added to a version header, denoted by all-caps text
## Example ## Example
```markdown ```{literalinclude} ../../tests/Test-Changelog.md
# Changelog :language: markdown
All notable changes to this project will be documented in this file.
## 0.13.0 "Aquarius" - 1970-04-11 [YANKED]
Yanked due to issues with oxygen tanks, currently investigating
### Added
- Extra propellant in preparation for future versions
### Changed
- Replaced Ken Mattingly
- Stirred oxygen tanks
## 0.12.0 "Intrepid" - 1969-11-14
### Added
- New ALSEP package for surface science
- Color cameras
- Surface rendezvous with Surveyor 3
### Fixed
- 1201/1202 alarm distracting crew during landing
### Known Issues
- Lightning strike during launch: No effect on performance
## 0.11.0 "Eagle" - 1969-07-20
Initial stable release
### Changed
- Fully fueled lander to allow landing on the lunar surface
``` ```

View File

@ -0,0 +1,141 @@
# Github Actions
Yaclog makes an action available for Github Actions and compatible CI systems.
## The Yaclog Action
To use the Yaclog action add the following to your workflow steps
````{jinja}
```yaml
- name: Get version info
uses: drewcassidy/yaclog@{{ ref }}
id: yaclog
```
````
### Inputs
```{confval} release
:type: string
When set, creates a new release and commits it. Directly passed to the arguments of `yaclog release --yes --commit`.
Can be a version number or an increment tag like `--major`, `--minor`, or `--patch`.
The resulting commit and tag will NOT be pushed back to the repo. You must add a step to do this yourself
```
```{confval} markdown
:type: boolean
:default: true
If the output should be in markdown format or not. Equivalent to the `--markdown` flag
```
### Outputs
```{confval} version
The current version number, equivalent to the output of `yaclog show --version`. For example, `1.3.1`
```
```{confval} name
The most recent version name, equivalent to the output of `yaclog show --name`. For example, `Version 1.3.0`
```
```{confval} header
The entire header for the most recent version, equivalent to the output of `yaclog show --header`. For example, `Version 1.3.0 - 2024-08-08`
```
```{confval} body-file
The path to a temporary file containing the body of the most recent version. Contents equivalent to `yaclog show --body`
```
```{confval} changelog
The path to the changelog file. Usually `CHANGELOG.md` in the current directory.
```
## Example Usage
### Get changelog information in your Build workflow
````{jinja}
```yaml
name: Build
on:
push:
pull_request:
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout Mod Repo
uses: actions/checkout@v4
- uses: drewcassidy/yaclog@{{ ref }}
id: yaclog
# Your build and test actions go here
- name: Publish to Github
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
run: |
gh release create {{ '${{ github.ref_name }}' }} \
--notes-file "{{ '${{ steps.yaclog.outputs.body-file }}' }}" \
--title "{{ '${{ steps.yaclog.outputs.name }}' }}"
env:
GH_TOKEN: {{ '${{ github.token }}' }}
```
````
### Workflow to make a new release
If you want to be able to create a new release for your project directly from the Github UI, you can make a new workflow
you can dispatch directly.
Please note that this workflow does NOT create any releases in Github or any package managers. Instead, your normal build workflow should do this when it detects a push to a tag.
````{jinja}
```yaml
name: Release
on:
workflow_dispatch:
inputs:
release:
description: 'type of release to use'
required: true
default: 'patch'
type: choice
options:
- major
- minor
- patch
permissions:
contents: write
jobs:
yaclog-release:
runs-on: ubuntu-latest
steps:
- name: Checkout Mod Repo
uses: actions/checkout@v4
- name: Yaclog Release
uses: drewcassidy/yaclog@{{ ref }}
with:
release: '--{{ '${{ inputs.release }}' }}'
- name: Push Changes
run: |
git config --global user.name "github-actions"
git config --global user.email "github-actions@github.com"
git push
git push --tags
env:
GH_TOKEN: {{ '${{ github.token }}' }}
```
````

View File

@ -8,4 +8,5 @@ maxdepth: 3
getting_started getting_started
changelog_files changelog_files
commands commands
github_actions
``` ```

View File

@ -22,6 +22,8 @@ classifiers = [
"Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Topic :: Text Processing :: Markup :: Markdown", "Topic :: Text Processing :: Markup :: Markdown",
"Topic :: Software Development :: Version Control :: Git", "Topic :: Software Development :: Version Control :: Git",
"Topic :: Utilities" "Topic :: Utilities"
@ -43,6 +45,7 @@ docs = [
"sphinx-click >= 2.7", "sphinx-click >= 2.7",
"sphinx-rtd-theme", "sphinx-rtd-theme",
"myst-parser >= 0.14", "myst-parser >= 0.14",
"sphinx-jinja >=1.2.1",
] ]
[project.scripts] [project.scripts]
@ -54,6 +57,7 @@ Changelog = "https://github.com/drewcassidy/yaclog/blob/main/CHANGELOG.md"
Docs = "https://yaclog.readthedocs.io/" Docs = "https://yaclog.readthedocs.io/"
[tool.setuptools_scm] [tool.setuptools_scm]
fallback_version = "0.0.0"
[tool.setuptools.packages.find] [tool.setuptools.packages.find]
include = ["yaclog"] include = ["yaclog*"]

40
tests/Test-Changelog.md Normal file
View File

@ -0,0 +1,40 @@
# Changelog
All notable changes to this project will be documented in this file.
## 0.13.0 "Aquarius" - 1970-04-11 [YANKED]
Yanked due to issues with oxygen tanks, currently investigating
### Added
- Extra propellant in preparation for future versions
### Changed
- Replaced Ken Mattingly
- Stirred oxygen tanks
## 0.12.0 "Intrepid" - 1969-11-14
### Added
- New ALSEP package for surface science
- Color cameras
- Surface rendezvous with Surveyor 3
### Fixed
- 1201/1202 alarm distracting crew during landing
### Known Issues
- Lightning strike during launch: No effect on performance
## 0.11.0 "Eagle" - 1969-07-20
Initial stable release
### Changed
- Fully fueled lander to allow landing on the lunar surface

View File

@ -16,6 +16,7 @@
import datetime import datetime
import os.path import os.path
from sys import stdout
import click import click
@ -72,9 +73,10 @@ def reformat(obj: Changelog):
help='Show only the version header.') help='Show only the version header.')
@click.option('--version', '-v', 'mode', flag_value='version', help='Show only the version number. If the current version is unreleased, ' @click.option('--version', '-v', 'mode', flag_value='version', help='Show only the version number. If the current version is unreleased, '
'this is inferred by incrementing the patch number of the last released version') 'this is inferred by incrementing the patch number of the last released version')
@click.option('---gh-actions', 'gh_actions', is_flag=True, hidden=True)
@click.argument('version_names', metavar='VERSIONS', type=str, nargs=-1) @click.argument('version_names', metavar='VERSIONS', type=str, nargs=-1)
@click.pass_obj @click.pass_obj
def show(obj: Changelog, all_versions, markdown, mode, version_names): def show(obj: Changelog, all_versions, markdown, mode, version_names, gh_actions):
""" """
Show the changes for VERSIONS. Show the changes for VERSIONS.
@ -90,7 +92,7 @@ def show(obj: Changelog, all_versions, markdown, mode, version_names):
} }
str_func = functions[mode] str_func = functions[mode]
kwargs = {'md': markdown, 'color': True} kwargs = {'md': markdown, 'color': stdout.isatty()}
try: try:
if all_versions: if all_versions:
@ -110,6 +112,21 @@ def show(obj: Changelog, all_versions, markdown, mode, version_names):
raise click.ClickException(str(v)) raise click.ClickException(str(v))
sep = '\n\n' if mode == 'body' or mode == 'full' else '\n' sep = '\n\n' if mode == 'body' or mode == 'full' else '\n'
if gh_actions:
import tempfile
kwargs['color'] = False
all_modes = [ 'name', 'header', 'version' ]
outputs = [f'{mode}={sep.join([functions[mode](v, kwargs) for v in versions])}' for mode in all_modes]
click.echo('\n'.join(outputs))
body_fd, body_file = tempfile.mkstemp(text=True)
with os.fdopen(body_fd, 'w') as f:
f.write(sep.join([functions['body'](v, kwargs) for v in versions]))
click.echo(f'body-file={body_file}')
click.echo(f'changelog={obj.path}')
return
click.echo(sep.join([str_func(v, kwargs) for v in versions])) click.echo(sep.join([str_func(v, kwargs) for v in versions]))