Skip to content

Commit b0b8a39

Browse files
rickycodesGudahttmcmire
authored
Support monorepos with independent versions (#51)
* add env variables to constants * add option for a new json file * use env variable constants in tests * add more constants * add VERSION_STRATEGY * stub behaviour for independent release strategy * delete get.sh * update dist file * begin to stub out idependent functionality * ls * add shell * block out independent functionality * update dist/index.js * add get-updated-packages * update * add getUpdatedPackages * update dist/index.js * update getUpdatedPackages * include package version * update dist/index.js * update release notes * add some notes and set some flags * add tag.sh * implement per-package tags * add .name * use $UPDATED_PACKAGES * update dist * cleanup * update dist * cleanup * add test for getUpdatedPackages * update test * add throw test case * add UPDATED_PACKAGES_ERROR constant * cleanup * path is unused here * use constant * coverage 100% * +Mock * update dist * address nit * update tests * we only care about https * update dist * make script based on workspaces * add "updated-packages-test" * address lint nit * verify unchanged lengths * address syntax error * fix outputs * fix outputs * use -ne * complete functional test * try to fail * try another failing test * fix tests * use loop * remove zero case * delete * Update .github/workflows/build-lint-test.yml Co-authored-by: Mark Stacey <markjstacey@gmail.com> * move fixedOrIndependent to utils * update dist * move MOCK_UPDATED_PACAKGES to `getReleaseNotes.test.ts` * remove string coercion * make PackageRecord constant * remove getUpdatedPackagesMock * inline updatedPackages * inline EMPTY_PACKAGES * update dist * call jq once here * address shellcheck lints * remove constants * update dist * extract to two functions * update dist * move No updated packages check * get all packages from yarn workspaces and pick two * remove to_increment * re-add mock for console.log * account for private * remove comments * add echo * add Get Packages step * add cd * add some echo * try join * try join * try join * use comma delimited strings * packages* * package* * fix packages length * fix packages length * update test * remove quotes * -ne * remove echo * add parseChangelogMockImplementation and inline getStringifiedReleaseMockFactory * inline getStringifiedReleaseMockFactory * remove | undefined * move this check back * s/VERSION_STRATEGY/RELEASE_STRATEGY * update get-packages test * update updated-packages-test * cleanup * remove newlines * test * try again * try quoting? * update outputs name * try to fix * debug * debug * stick with upper * update test * cleanup * does this still work? * Update .github/workflows/build-lint-test.yml Co-authored-by: Elliot Winkler <elliot.winkler@gmail.com> * this works, but the mock is wrong? * deduplicate * Check for RELEASE_PACKAGES only for independent monorepos * Fix this script * UPDATED_PACKAGES -> RELEASE_PACKAGES * Make this name consistent * Don't assume all versions are the same when assembling changelogs * Update dist/index.js * remove set-output re: https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/ * remove set-output re: https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/ Co-authored-by: Mark Stacey <markjstacey@gmail.com> Co-authored-by: Elliot Winkler <elliot.winkler@gmail.com>
1 parent de4d2a8 commit b0b8a39

12 files changed

Lines changed: 517 additions & 117 deletions

.github/workflows/build-lint-test.yml

Lines changed: 89 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,97 @@ jobs:
1616
- run: git diff --quiet || { echo 'working directory dirty after "yarn build"'; exit 1; }
1717
- run: yarn lint
1818
- run: yarn test
19+
# tests to ensure get-release-packages.sh functions as expected
20+
updated-packages-test:
21+
runs-on: ubuntu-20.04
22+
steps:
23+
- name: Get Latest Version from npm
24+
id: latestrelease
25+
run: echo "releasever=$(npm view MetaMask/snaps-skunkworks version --workspaces=false)" >> "$GITHUB_OUTPUT"
26+
- uses: actions/checkout@v3
27+
with:
28+
repository: MetaMask/snaps-skunkworks
29+
ref: v${{ steps.latestrelease.outputs.releasever }}
30+
path: skunkworks
31+
- uses: actions/checkout@v3
32+
with:
33+
path: action-publish-release
34+
- name: Get Packages
35+
id: get-packages
36+
run: |
37+
cd skunkworks || exit
38+
WORKSPACES=$(yarn workspaces list --verbose --json)
39+
PUBLIC_PACKAGES=()
40+
PRIVATE_PACKAGE=()
41+
42+
while read -r location name; do
43+
if [[ "$name" != "root" ]]; then
44+
PRIVATE=$(jq --raw-output '.private' "$location/package.json")
45+
if [[ "$PRIVATE" != true && "${#PUBLIC_PACKAGES[@]}" -ne 3 ]]; then
46+
PUBLIC_PACKAGES+=("$location")
47+
fi
48+
if [[ "$PRIVATE" == true && "${#PRIVATE_PACKAGE[@]}" -ne 1 ]]; then
49+
PRIVATE_PACKAGE+=("$location")
50+
fi
51+
fi
52+
done< <(echo "$WORKSPACES" | jq --raw-output '"\(.location) \(.name)"')
53+
54+
RELEASE_PACKAGES=("${PUBLIC_PACKAGES[@]}" "${PRIVATE_PACKAGE[@]}")
55+
IFS="," RELEASE_PACKAGES_FORMATTED="${RELEASE_PACKAGES[*]}"
56+
echo "RELEASE_PACKAGES=$RELEASE_PACKAGES_FORMATTED" >> "$GITHUB_OUTPUT"
57+
- name: Modify + Get RELEASE_PACKAGES lengths
58+
id: modify-get-release-packages
59+
run: |
60+
function update_manifest() {
61+
MANIFEST="${1}/package.json"
62+
MANIFEST_TEMP="${MANIFEST}_temp"
63+
VERSION=$(jq --raw-output .version "$MANIFEST")
64+
IFS='.' read -r -a VERSIONS <<< "$VERSION"
65+
MAJOR="${VERSIONS[0]}"
66+
MINOR="${VERSIONS[1]}"
67+
PATCH="${VERSIONS[2]}"
68+
if [[ "$2" == "unbump" ]]; then
69+
if [[ "$PATCH" == "0" ]]; then
70+
if [[ "$MINOR" == "0" ]]; then
71+
# e.g. 10.0.0 -> 9.9.9
72+
NEW_VERSION="$((MAJOR - 1)).9.9"
73+
else
74+
# e.g. 1.10.0 -> 1.9.9
75+
NEW_VERSION="${MAJOR}.$((MINOR - 1)).9"
76+
fi
77+
else
78+
# e.g. 1.2.10 -> 1.2.9
79+
NEW_VERSION="${MAJOR}.${MINOR}.$((PATCH - 1))"
80+
fi
81+
else
82+
# e.g. 1.0.0 -> 1.0.1
83+
NEW_VERSION="${MAJOR}.${MINOR}.$((PATCH + 1))"
84+
fi
85+
jq --arg version "$NEW_VERSION" '.version = $version' "$MANIFEST" > "$MANIFEST_TEMP"
86+
mv "$MANIFEST_TEMP" "$MANIFEST"
87+
}
88+
cd skunkworks || exit
89+
IFS="," read -r -a RELEASE_PACKAGES <<< "${{ steps.get-packages.outputs.RELEASE_PACKAGES }}"
90+
for i in {0..1}
91+
do
92+
update_manifest "${RELEASE_PACKAGES[$i]}" "bump"
93+
done
94+
update_manifest "${RELEASE_PACKAGES[2]}" "unbump"
95+
update_manifest "${RELEASE_PACKAGES[3]}" "bump"
96+
../action-publish-release/scripts/get-release-packages.sh
97+
- name: Get modified RELEASE_PACKAGES lengths
98+
id: get-modified-updated-packages-length
99+
run: |
100+
echo "length=$(echo '${{ steps.modify-get-release-packages.outputs.RELEASE_PACKAGES }}' | jq '.packages | length')" >> "$GITHUB_OUTPUT"
101+
- name: Verify modified RELEASE_PACKAGES lengths
102+
run: |
103+
if [[ ${{ steps.get-modified-updated-packages-length.outputs.length }} -ne 3 ]]; then
104+
echo "modified RELEASE_PACKAGES is an unexpected length"
105+
exit 1
106+
fi;
19107
20108
all-tests-pass:
21109
runs-on: ubuntu-20.04
22-
needs: build-lint-test
110+
needs: [build-lint-test, updated-packages-test]
23111
steps:
24112
- run: echo "Great success"

action.yml

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,24 +9,37 @@ outputs:
99
runs:
1010
using: 'composite'
1111
steps:
12-
- id: get-release-version
12+
- id: get-version-strategy
1313
shell: bash
1414
run: |
15-
${{ github.action_path }}/scripts/get.sh ".version" "RELEASE_VERSION"
15+
RELEASE_STRATEGY=$(jq --raw-output ".versioningStrategy" "release.config.json" || echo "fixed")
16+
echo "RELEASE_STRATEGY=$RELEASE_STRATEGY" >> "$GITHUB_OUTPUT"
17+
- id: get-release-version
18+
shell: bash
19+
run: echo "RELEASE_VERSION=$(jq --raw-output '.version' package.json)" >> "$GITHUB_OUTPUT"
1620
- id: get-repository-url
21+
shell: bash
22+
run: echo "REPOSITORY_URL=$(jq --raw-output '.repository.url' package.json)" >> "$GITHUB_OUTPUT"
23+
- id: get-release-packages
24+
if: steps.get-version-strategy.outputs.RELEASE_STRATEGY == 'independent'
1725
shell: bash
1826
run: |
19-
${{ github.action_path }}/scripts/get.sh ".repository.url" "REPOSITORY_URL"
27+
${{ github.action_path }}/scripts/get-release-packages.sh
2028
# This sets RELEASE_NOTES as an environment variable, which is expected
2129
# by the create-github-release step.
2230
- id: get-release-notes
2331
shell: bash
2432
run: node ${{ github.action_path }}/dist/index.js
2533
env:
34+
RELEASE_STRATEGY: ${{ steps.get-version-strategy.outputs.RELEASE_STRATEGY }}
2635
RELEASE_VERSION: ${{ steps.get-release-version.outputs.RELEASE_VERSION }}
2736
REPOSITORY_URL: ${{ steps.get-repository-url.outputs.REPOSITORY_URL }}
37+
RELEASE_PACKAGES: ${{ steps.get-release-packages.outputs.RELEASE_PACKAGES }}
2838
- id: create-github-release
2939
shell: bash
3040
run: |
31-
${{ github.action_path }}/scripts/create-github-release.sh \
32-
${{ steps.get-release-version.outputs.RELEASE_VERSION }}
41+
${{ github.action_path }}/scripts/create-github-release.sh
42+
env:
43+
RELEASE_STRATEGY: ${{ steps.get-version-strategy.outputs.RELEASE_STRATEGY }}
44+
RELEASE_VERSION: ${{ steps.get-release-version.outputs.RELEASE_VERSION }}
45+
RELEASE_PACKAGES: ${{ steps.get-release-packages.outputs.RELEASE_PACKAGES }}

dist/index.js

Lines changed: 51 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10789,10 +10789,8 @@ var dist = __nccwpck_require__(1281);
1078910789
// EXTERNAL MODULE: ./node_modules/@metamask/auto-changelog/dist/index.js
1079010790
var auto_changelog_dist = __nccwpck_require__(9272);
1079110791
;// CONCATENATED MODULE: ./lib/constants.js
10792-
// error messages
10793-
const GITHUB_WORKSPACE_ERROR = 'process.env.GITHUB_WORKSPACE must be set.';
10794-
const RELEASE_VERSION_ERROR = 'process.env.RELEASE_VERSION must be a valid SemVer version.';
10795-
const REPOSITORY_URL_ERROR = 'process.env.REPOSITORY_URL must be a valid URL.';
10792+
const FIXED = 'fixed';
10793+
const INDEPENDENT = 'independent';
1079610794
//# sourceMappingURL=constants.js.map
1079710795
;// CONCATENATED MODULE: ./lib/utils.js
1079810796

@@ -10805,9 +10803,10 @@ const isValidUrl = (str) => {
1080510803
catch (_) {
1080610804
return false;
1080710805
}
10808-
return url.protocol === 'http:' || url.protocol === 'https:';
10806+
return url.protocol === `https:`;
1080910807
};
1081010808
const removeGitEx = (url) => url.substring(0, url.lastIndexOf('.git'));
10809+
const fixedOrIndependent = (value) => value === FIXED || value === INDEPENDENT;
1081110810
/**
1081210811
* Utility function for parsing expected environment variables.
1081310812
*
@@ -10819,21 +10818,28 @@ const removeGitEx = (url) => url.substring(0, url.lastIndexOf('.git'));
1081910818
function parseEnvironmentVariables(environmentVariables = process.env) {
1082010819
const workspaceRoot = (0,dist.getStringRecordValue)('GITHUB_WORKSPACE', environmentVariables);
1082110820
if (!(0,dist.isTruthyString)(workspaceRoot)) {
10822-
throw new Error(GITHUB_WORKSPACE_ERROR);
10821+
throw new Error('process.env.GITHUB_WORKSPACE must be set.');
1082310822
}
1082410823
const releaseVersion = (0,dist.getStringRecordValue)('RELEASE_VERSION', environmentVariables);
1082510824
if (!(0,dist.isTruthyString)(releaseVersion) || !(0,dist.isValidSemver)(releaseVersion)) {
10826-
throw new Error(RELEASE_VERSION_ERROR);
10825+
throw new Error('process.env.RELEASE_VERSION must be a valid SemVer version.');
1082710826
}
1082810827
const repositoryUrl = (0,dist.getStringRecordValue)('REPOSITORY_URL', environmentVariables);
1082910828
if (!isValidUrl(repositoryUrl)) {
10830-
throw new Error(REPOSITORY_URL_ERROR);
10829+
throw new Error('process.env.REPOSITORY_URL must be a valid URL.');
1083110830
}
1083210831
const repoUrl = removeGitEx(repositoryUrl);
10832+
const releaseStrategy = (0,dist.getStringRecordValue)('RELEASE_STRATEGY', environmentVariables);
10833+
if (!fixedOrIndependent(releaseStrategy)) {
10834+
throw new Error(`process.env.RELEASE_STRATEGY must be one of "${FIXED}" or "${INDEPENDENT}"`);
10835+
}
10836+
const releasePackages = (0,dist.getStringRecordValue)('RELEASE_PACKAGES', environmentVariables) || undefined;
1083310837
return {
1083410838
releaseVersion,
1083510839
repoUrl,
1083610840
workspaceRoot,
10841+
releaseStrategy,
10842+
releasePackages,
1083710843
};
1083810844
}
1083910845
//# sourceMappingURL=utils.js.map
@@ -10844,6 +10850,17 @@ function parseEnvironmentVariables(environmentVariables = process.env) {
1084410850

1084510851

1084610852

10853+
10854+
const getReleasePackages = () => {
10855+
const { releasePackages } = parseEnvironmentVariables();
10856+
if (releasePackages === undefined) {
10857+
throw new Error('The updated packages are undefined');
10858+
}
10859+
else {
10860+
const { packages } = JSON.parse(releasePackages);
10861+
return packages;
10862+
}
10863+
};
1084710864
/**
1084810865
* Action entry function. Gets the release notes for use in a GitHub release.
1084910866
* Works for both monorepos and polyrepos.
@@ -10852,13 +10869,13 @@ function parseEnvironmentVariables(environmentVariables = process.env) {
1085210869
* @see getPackageManifest - For details on polyrepo workflow.
1085310870
*/
1085410871
async function getReleaseNotes() {
10855-
const { releaseVersion, repoUrl, workspaceRoot } = parseEnvironmentVariables();
10872+
const { releaseVersion, repoUrl, workspaceRoot, releaseStrategy } = parseEnvironmentVariables();
1085610873
const rawRootManifest = await (0,dist.getPackageManifest)(workspaceRoot);
1085710874
const rootManifest = (0,dist.validatePackageManifestVersion)(rawRootManifest, workspaceRoot);
1085810875
let releaseNotes;
1085910876
if (dist.ManifestFieldNames.Workspaces in rootManifest) {
1086010877
console.log('Project appears to have workspaces. Applying monorepo workflow.');
10861-
releaseNotes = await getMonorepoReleaseNotes(releaseVersion, repoUrl, workspaceRoot, (0,dist.validateMonorepoPackageManifest)(rootManifest, workspaceRoot));
10878+
releaseNotes = await getMonorepoReleaseNotes(releaseVersion, repoUrl, workspaceRoot, (0,dist.validateMonorepoPackageManifest)(rootManifest, workspaceRoot), releaseStrategy);
1086210879
}
1086310880
else {
1086410881
console.log('Project does not appear to have any workspaces. Applying polyrepo workflow.');
@@ -10870,6 +10887,26 @@ async function getReleaseNotes() {
1087010887
}
1087110888
(0,core.exportVariable)('RELEASE_NOTES', releaseNotes.concat('\n\n'));
1087210889
}
10890+
async function getReleaseNotesForMonorepoWithIndependentVersions(repoUrl) {
10891+
let releaseNotes = '';
10892+
for (const [packageName, { path, version }] of Object.entries(getReleasePackages())) {
10893+
releaseNotes = releaseNotes.concat(`## ${packageName}\n\n`, await getPackageReleaseNotes(version, repoUrl, path), '\n\n');
10894+
}
10895+
return releaseNotes;
10896+
}
10897+
async function getReleaseNotesForMonorepoWithFixedVersions(releaseVersion, repoUrl, workspaceRoot, rootManifest) {
10898+
const workspaceLocations = await (0,dist.getWorkspaceLocations)(rootManifest.workspaces, workspaceRoot);
10899+
let releaseNotes = '';
10900+
for (const workspaceLocation of workspaceLocations) {
10901+
const completeWorkspacePath = external_path_default().join(workspaceRoot, workspaceLocation);
10902+
const rawPackageManifest = await (0,dist.getPackageManifest)(completeWorkspacePath);
10903+
const { name: packageName, version: packageVersion } = (0,dist.validatePolyrepoPackageManifest)(rawPackageManifest, completeWorkspacePath);
10904+
if (packageVersion === releaseVersion) {
10905+
releaseNotes = releaseNotes.concat(`## ${packageName}\n\n`, await getPackageReleaseNotes(releaseVersion, repoUrl, completeWorkspacePath), '\n\n');
10906+
}
10907+
}
10908+
return releaseNotes;
10909+
}
1087310910
/**
1087410911
* Gets the combined release notes for all packages in the monorepo that are
1087510912
* included in the current release.
@@ -10883,17 +10920,10 @@ async function getReleaseNotes() {
1088310920
* @param rootManifest - The parsed package.json file of the root directory.
1088410921
* @returns The release notes for all packages included in the release.
1088510922
*/
10886-
async function getMonorepoReleaseNotes(releaseVersion, repoUrl, workspaceRoot, rootManifest) {
10887-
const workspaceLocations = await (0,dist.getWorkspaceLocations)(rootManifest.workspaces, workspaceRoot);
10888-
let releaseNotes = '';
10889-
for (const workspaceLocation of workspaceLocations) {
10890-
const completeWorkspacePath = external_path_default().join(workspaceRoot, workspaceLocation);
10891-
const rawPackageManifest = await (0,dist.getPackageManifest)(completeWorkspacePath);
10892-
const { name: packageName, version: packageVersion } = (0,dist.validatePolyrepoPackageManifest)(rawPackageManifest, completeWorkspacePath);
10893-
if (packageVersion === releaseVersion) {
10894-
releaseNotes = releaseNotes.concat(`## ${packageName}\n\n`, await getPackageReleaseNotes(releaseVersion, repoUrl, completeWorkspacePath), '\n\n');
10895-
}
10896-
}
10923+
async function getMonorepoReleaseNotes(releaseVersion, repoUrl, workspaceRoot, rootManifest, versioningStrategy) {
10924+
const releaseNotes = versioningStrategy === INDEPENDENT
10925+
? await getReleaseNotesForMonorepoWithIndependentVersions(repoUrl)
10926+
: await getReleaseNotesForMonorepoWithFixedVersions(releaseVersion, repoUrl, workspaceRoot, rootManifest);
1089710927
return releaseNotes;
1089810928
}
1089910929
/**

jest.config.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
1+
const coverage = 100;
2+
13
module.exports = {
24
collectCoverage: true,
35
collectCoverageFrom: ['src/**/*.ts', '!**/*.d.ts'],
46
coverageReporters: ['text', 'html'],
57
coverageThreshold: {
68
global: {
7-
branches: 100,
8-
functions: 100,
9-
lines: 100,
10-
statements: 100,
9+
branches: coverage,
10+
functions: coverage,
11+
lines: coverage,
12+
statements: coverage,
1113
},
1214
},
1315
moduleFileExtensions: ['ts', 'js', 'json', 'node'],

scripts/create-github-release.sh

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,40 @@ if [[ -z $RELEASE_NOTES ]]; then
99
exit 1
1010
fi
1111

12-
RELEASE_VERSION="${1}"
13-
1412
if [[ -z $RELEASE_VERSION ]]; then
1513
echo "Error: No release version specified."
1614
exit 1
1715
fi
1816

17+
if [[ -z $RELEASE_STRATEGY ]]; then
18+
echo "Error: No version strategy specified."
19+
exit 1
20+
fi
21+
22+
if [[ "$(jq 'has("workspaces")' package.json)" = "true" && "$RELEASE_STRATEGY" = "independent" ]]; then
23+
IS_MONOREPO_WITH_INDEPENDENT_VERSIONS=1
24+
else
25+
IS_MONOREPO_WITH_INDEPENDENT_VERSIONS=0
26+
fi
27+
28+
if [[ $IS_MONOREPO_WITH_INDEPENDENT_VERSIONS -eq 1 && -z $RELEASE_PACKAGES ]]; then
29+
echo "Error: No updated packages specified."
30+
exit 1
31+
fi
32+
1933
gh release create \
2034
"v$RELEASE_VERSION" \
2135
--title "$RELEASE_VERSION" \
2236
--notes "$RELEASE_NOTES"
37+
38+
if [[ $IS_MONOREPO_WITH_INDEPENDENT_VERSIONS ]]; then
39+
echo "independent versioning strategy"
40+
41+
git config user.name github-actions
42+
git config user.email github-actions@github.com
43+
44+
while read -r name version; do
45+
git tag "${name}@${version}" HEAD
46+
git push --tags
47+
done< <(echo "$RELEASE_PACKAGES" | jq --raw-output '.packages[] | "\(.name) \(.version)"')
48+
fi

scripts/get-release-packages.sh

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#!/usr/bin/env bash
2+
3+
set -x
4+
set -e
5+
set -u
6+
set -o pipefail
7+
8+
# JSON string of packages to publish
9+
# shape is as follows:
10+
# {
11+
# "packages": {
12+
# "@metamask/snaps-cli": {
13+
# "name": "@metamask/snaps-cli",
14+
# "path": "packages/cli",
15+
# "version": "0.19.2"
16+
# },
17+
# "@metamask/snap-controllers": {
18+
# "name": "@metamask/snap-controllers",
19+
# "path": "packages/controllers",
20+
# "version": "0.19.2"
21+
# }
22+
# }
23+
# }
24+
toPublish="{\"packages\":{"
25+
# store initial length of toPublish
26+
len="${#toPublish}"
27+
28+
workspaces=$(yarn workspaces list --verbose --json)
29+
30+
while read -r location name; do
31+
MANIFEST="$location/package.json"
32+
read -r PRIVATE CURRENT_PACKAGE_VERSION < <(jq --raw-output '.private, .version' "$MANIFEST" | xargs)
33+
if [[ "$PRIVATE" != "true" ]]; then
34+
LATEST_PACKAGE_VERSION=$(npm view "$name" version --workspaces=false || echo "")
35+
if [ "$LATEST_PACKAGE_VERSION" != "$CURRENT_PACKAGE_VERSION" ]; then
36+
toPublish+="\"$name\":{\"name\":"\"$name\"",\"path\":"\"$location\"",\"version\":"\"$CURRENT_PACKAGE_VERSION"\"},"
37+
fi
38+
fi
39+
done< <(echo "$workspaces" | jq --raw-output '"\(.location) \(.name)"')
40+
41+
# if the length of toPublish is greater than the initial length
42+
# trim off the last char (,)
43+
if [[ "${#toPublish}" -gt "$len" ]]; then
44+
toPublish=${toPublish::-1}
45+
fi
46+
47+
RELEASE_PACKAGES="$toPublish}}"
48+
49+
# echo "$RELEASE_PACKAGES"
50+
echo "RELEASE_PACKAGES=$RELEASE_PACKAGES" >> "$GITHUB_OUTPUT"

0 commit comments

Comments
 (0)