Skip to content

Commit 33e768e

Browse files
committed
Add a new action-gh-release-parameters input
This is a JSON string that can contain most parameters accepted by the `softprops/action-gh-release@v2` action.
1 parent 82729c7 commit 33e768e

File tree

9 files changed

+166
-23
lines changed

9 files changed

+166
-23
lines changed

.github/workflows/test-no-changes-file.yml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,14 @@ jobs:
3030
executable-name: test-project
3131
target: x86_64-unknown-linux-gnu
3232
changes-file: ""
33-
# We don't want to actually do a release when running tests.
34-
release-tag-prefix: "do-not-release"
33+
# We always to do a release during tests, just to make sure that the release part of the
34+
# action works.
35+
_force-release-for-testing: true
36+
action-gh-release-parameters: |
37+
{
38+
"repository": "houseabsolute/actions-rust-release-testing",
39+
"token": "${{ secrets.ACTIONS_RUST_RELEASE_TESTING_TOKEN }}"
40+
}
3541
- name: Install psutils on Windows
3642
run: choco install --ignore-checksums psutils
3743
if: runner.os == 'Windows'

.github/workflows/test-working-directory.yml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,14 @@ jobs:
5050
executable-name: sub-project
5151
working-directory: sub-project
5252
target: ${{ matrix.platform.target }}
53-
# We don't want to actually do a release when running tests.
54-
release-tag-prefix: "do-not-release"
53+
# We always to do a release during tests, just to make sure that the release part of the
54+
# action works.
55+
_force-release-for-testing: true
56+
action-gh-release-parameters: |
57+
{
58+
"repository": "houseabsolute/actions-rust-release-testing",
59+
"token": "${{ secrets.ACTIONS_RUST_RELEASE_TESTING_TOKEN }}"
60+
}
5561
- name: Install psutils on Windows
5662
run: choco install --ignore-checksums psutils
5763
if: runner.os == 'Windows'

.github/workflows/test.yml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,14 @@ jobs:
4848
with:
4949
executable-name: test-project
5050
target: ${{ matrix.platform.target }}
51-
# We don't want to actually do a release when running tests.
52-
release-tag-prefix: "do-not-release"
51+
# We always to do a release during tests, just to make sure that the release part of the
52+
# action works.
53+
_force-release-for-testing: true
54+
action-gh-release-parameters: |
55+
{
56+
"repository": "houseabsolute/actions-rust-release-testing",
57+
"token": "${{ secrets.ACTIONS_RUST_RELEASE_TESTING_TOKEN }}"
58+
}
5359
- name: Install psutils on Windows
5460
run: choco install --ignore-checksums psutils
5561
if: runner.os == 'Windows'

Changes.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
- Added validation for all input parameters. This should provide better errors when a required
44
parameter is missing or a parameter is invalid (like referring to a path which does not exist).
5+
- Added a new `action-gh-release-parameters` input parameter. This takes a JSON string which can
6+
contain most parameters accepted by the
7+
[the `softprops/action-gh-release@v2` action](https://github.com/softprops/action-gh-release)
8+
action.
59

610
## 0.0.5 - 2025-02-09
711

README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,17 @@ If you set this to an empty string, then no changelog file will be included.
128128
The current working directory in which all actions are performed. This defaults to the checked out
129129
repo's root. You use relative paths to set this to a subdirectory in the repo.
130130

131+
### `action-gh-release-parameters`
132+
133+
- **Required**: no
134+
135+
This must be a string containing valid JSON. The JSON should be an object where the keys are the
136+
parameters for
137+
[the `softprops/action-gh-release@v2` action](https://github.com/softprops/action-gh-release).
138+
139+
Note that the `actions-rust-release` action will always set the `draft` and `files` parameters, so
140+
any values you set for these parameter will be in the JSON string will be ignored.
141+
131142
## Outputs
132143

133144
This action provides two outputs.

action.yml

Lines changed: 45 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,16 @@ inputs:
5858
current working directory.
5959
default: "."
6060

61+
action-gh-release-parameters:
62+
description: |
63+
A JSON string containing parameters to pass to `softprops/action-gh-release@v2`. You can use
64+
the `toJSON()` function in your action to make passing this easier.
65+
default: "{}"
66+
67+
_force-release-for-testing:
68+
description: |
69+
This exists to let me test the release parts of this action.
70+
6171
outputs:
6272
artifact-id:
6373
description: |
@@ -93,6 +103,7 @@ runs:
93103
INPUTS_extra-files: ${{ inputs.extra-files }}
94104
INPUTS_changes_file: ${{ inputs.changes-file }}
95105
INPUTS_working_directory: ${{ inputs.working-directory }}
106+
INPUTS_action_gh_release_parameters: ${{ inputs.action-gh-release-parameters }}
96107

97108
- name: Package as archive
98109
id: package-archive
@@ -114,8 +125,8 @@ runs:
114125
115126
cd ${{ inputs.working-directory }}
116127
shasum --algorithm 256 \
117-
"${{ steps.package-archive.outputs.archive-basename }}" \
118-
> "${{ steps.package-archive.outputs.archive-basename }}.sha256"
128+
"${{ steps.package-archive.outputs.archive-file }}" \
129+
> "${{ steps.package-archive.outputs.archive-file }}.sha256"
119130
if: runner.os != 'Windows'
120131

121132
- name: Install dos2unix and psutils on Windows
@@ -129,23 +140,44 @@ runs:
129140
run: |
130141
cd ${{ inputs.working-directory }}
131142
shasum --algorithm 256 `
132-
"${{ steps.package-archive.outputs.archive-basename }}" `
133-
> "${{ steps.package-archive.outputs.archive-basename }}.sha256"
134-
dos2unix "${{ steps.package-archive.outputs.archive-basename }}.sha256"
143+
"${{ steps.package-archive.outputs.archive-file }}" `
144+
> "${{ steps.package-archive.outputs.archive-file }}.sha256"
145+
dos2unix "${{ steps.package-archive.outputs.archive-file }}.sha256"
135146
if: runner.os == 'Windows'
136147

137148
- name: Publish release artifact for run
138149
id: publish-release-artifact
139150
uses: actions/upload-artifact@v4
140151
with:
141-
name: ${{ steps.package-archive.outputs.archive-basename }}
142-
path: ${{ inputs.working-directory }}/${{ steps.package-archive.outputs.archive-basename }}*
152+
name: ${{ steps.package-archive.outputs.archive-file }}
153+
path: ${{ inputs.working-directory }}/${{ steps.package-archive.outputs.archive-file }}*
154+
155+
- name: Parse `action-gh-release-parameters` and set inputs for `softprops/action-gh-release`
156+
id: action-gh-release-parameters
157+
shell: bash
158+
run: |
159+
set -e
160+
set -x
161+
set -o pipefail
162+
163+
FAKE_TAG=""
164+
if [ -n "${{ inputs._force-release-for-testing }}" ]; then
165+
workflow_path=${${{ github.workflow_ref }}%%@*}
166+
workflow_file=basename "$workflow_path"
167+
FAKE_TAG="v-${{ github.ref_name }}-${{ github.sha }}-${{ github.run_number }}-$workflow_file"
168+
fi
169+
# This will get the inputs JSON from the `ACTION_GH_RELEASE_PARAMETERS` env var. This avoids
170+
# any string interpolation issues, since the inputs will contain quotes.
171+
parse-and-set-action-gh-release-parameters.py \
172+
--working-directory "${{ inputs.working-directory }}" \
173+
--archive-file "${{ steps.package-archive.outputs.archive-file }}" \
174+
--changes-file "${{ inputs.changes-file }}" \
175+
--fake-tag "$FAKE_TAG"
176+
env:
177+
ACTION_GH_RELEASE_PARAMETERS: ${{ inputs.action-gh-release-parameters }}
178+
if: ( github.ref_type == 'tag' && startsWith( github.ref_name, inputs.release-tag-prefix ) ) || inputs._force-release-for-testing
143179

144180
- name: Publish GitHub release
145181
uses: softprops/action-gh-release@v2
146-
with:
147-
draft: true
148-
# The trailing "*" should pick up the checksum file.
149-
files: ${{ inputs.working-directory }}/${{ steps.package-archive.outputs.archive-basename }}*
150-
body_path: ${{ ( inputs.changes-file && format( '{0}/{1}', inputs.working-directory, inputs.changes-file ) ) || '' }}
151-
if: github.ref_type == 'tag' && startsWith( github.ref_name, inputs.release-tag-prefix )
182+
with: ${{ steps.action-gh-release-parameters.outputs }}
183+
if: ( github.ref_type == 'tag' && startsWith( github.ref_name, inputs.release-tag-prefix ) ) || inputs._force-release-for-testing

make-archive.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#!/usr/bin/env python3
22

3+
# Mostly written by Claude.ai.
4+
35
import os
46
import sys
57
import glob
@@ -110,7 +112,7 @@ def gather_additional_files(
110112
) -> List[str]:
111113
"""Gather additional files to include in the archive."""
112114
if extra_files:
113-
return extra_files.strip().split("\n")
115+
return list(filter(None, map(str.strip, extra_files.splitlines())))
114116

115117
files = []
116118
if changes_file:
@@ -126,8 +128,8 @@ def create_archive(
126128
td = None
127129
try:
128130
td = tempfile.mkdtemp()
129-
# Copy files to temporary directory
130-
for file in [f for f in found_files if f]:
131+
132+
for file in found_files:
131133
shutil.copy2(file, td)
132134

133135
# Set executable permissions
@@ -172,7 +174,7 @@ def write_github_output(archive_file: str) -> None:
172174
sys.exit("GITHUB_OUTPUT environment variable not set.")
173175

174176
with open(output_file, "a") as f:
175-
print(f"archive-basename={Path(archive_file).name}", file=f)
177+
print(f"archive-file={Path(archive_file).name}", file=f)
176178

177179

178180
def target_to_archive_name(target: str) -> str:
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
#!/usr/bin/env python3
2+
3+
import argparse
4+
import json
5+
import os
6+
import sys
7+
from typing import Any, Dict
8+
9+
10+
def main():
11+
args = parse_arguments()
12+
validate_arguments(args)
13+
14+
archive_path = os.path.join(args.working_directory, args.archive_file)
15+
if not os.path.isfile(archive_path):
16+
sys.exit(f"Archive file '{archive_path}' does not exist.")
17+
18+
vars = json.loads(os.environ["ACTION_GH_RELEASE_PARAMETERS"])
19+
vars["draft"] = True
20+
# Appending a glob ensures we pick up the checksum file as well.
21+
vars["files"] = f"{archive_path}*"
22+
23+
if args.changes_file:
24+
vars["body_path"] = args.changes_file
25+
26+
if args.fake_tag:
27+
vars["tag_name"] = args.fake_tag
28+
29+
write_github_output(args.archive_file, vars)
30+
31+
32+
def parse_arguments() -> argparse.Namespace:
33+
"""Parse and return command line arguments."""
34+
parser = argparse.ArgumentParser()
35+
parser.add_argument("--working-directory", required=True)
36+
parser.add_argument("--archive-file", required=True)
37+
parser.add_argument("--changes-file", required=True)
38+
parser.add_argument("--fake-tag")
39+
return parser.parse_args()
40+
41+
42+
def validate_arguments(args: argparse.Namespace) -> None:
43+
"""Validate command line arguments."""
44+
if not args.working_directory or not os.path.isdir(args.working_directory):
45+
sys.exit("You must provide directory for the --working-directory option.")
46+
47+
if not args.archive_file:
48+
sys.exit("You must provide a file file for the --archive-file option.")
49+
50+
if args.changes_file and not os.path.isfile(args.changes_file):
51+
sys.exit(f"Changes file '{args.changes_file}' does not exist.")
52+
53+
54+
def write_github_output(archive_file: str, vars: Dict[str, Any]) -> None:
55+
"""Write the archive information to GitHub Actions output."""
56+
output_file = os.environ.get("GITHUB_OUTPUT", os.devnull)
57+
if not output_file:
58+
sys.exit("GITHUB_OUTPUT environment variable not set.")
59+
60+
with open(output_file, "a") as f:
61+
# for each key in sorted order from vars, print it to the output file
62+
for key in sorted(vars.keys()):
63+
print(f"{key}={vars[key]}", file=f)
64+
65+
66+
main()

validate-inputs.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#!/usr/bin/env python3
22

33
import os
4+
import json
45
from pathlib import Path
56
from typing import Dict, List, Union
67
import tempfile
@@ -98,6 +99,15 @@ def validate(self) -> List[str]:
9899
if "extra_files" in self.inputs:
99100
validation_errors.extend(self.validate_extra_files())
100101

102+
# Validate action-gh-release-parameters JSON if present
103+
if "action_gh_release_parameters" in self.inputs:
104+
try:
105+
json.loads(self.inputs["action_gh_release_parameters"])
106+
except json.JSONDecodeError:
107+
validation_errors.append(
108+
"'action-gh-release-parameters' must be valid JSON"
109+
)
110+
101111
return validation_errors
102112

103113
def validate_extra_files(self) -> List[str]:

0 commit comments

Comments
 (0)