-
Notifications
You must be signed in to change notification settings - Fork 467
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(CICD): #27805 Adding NPM publishing to nightly deployment workfl…
…ow. (#28248) * #27805 Adding NPM publishing to nightly deployment workflow. * #27805 Fixing the path of the download artifact step. * #27805 Refactor on publish npm cli workflow. * #27805 Fixing trigger conditional for publishing NPM package. * #27805 Find a previous build if the current is missing. --------- Co-authored-by: Daniel Colina <[email protected]>
- Loading branch information
Showing
5 changed files
with
385 additions
and
76 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
# CLI Publish NPM Package Action | ||
|
||
## Description | ||
|
||
This GitHub Action workflow packages the dotCMS CLI as an NPM project. | ||
|
||
## Inputs | ||
|
||
### `ref` | ||
|
||
Branch to build from. | ||
|
||
- **Description**: Branch to build the project from. | ||
- **Required**: No | ||
- **Default**: `master` | ||
|
||
### `github-token` | ||
|
||
GitHub Token. | ||
|
||
- **Description**: GitHub Token required to access GitHub resources. | ||
- **Required**: Yes | ||
|
||
### `npm-token` | ||
|
||
NPM Token. | ||
|
||
- **Description**: NPM Token required to publish the package to the NPM registry. | ||
- **Required**: Yes | ||
|
||
### `npm-package-name` | ||
|
||
NPM package name. | ||
|
||
- **Description**: NPM package name to be published. | ||
- **Required**: No | ||
- **Default**: `dotcli` | ||
|
||
### `npm-package-scope` | ||
|
||
NPM package scope. | ||
|
||
- **Description**: NPM package scope. | ||
- **Required**: No | ||
- **Default**: `@dotcms` | ||
|
||
### `node-version` | ||
|
||
Node.js version. | ||
|
||
- **Description**: Node.js version to be used to build the project. | ||
- **Required**: No | ||
- **Default**: `19` | ||
|
||
### `workflow-to-search` | ||
|
||
Workflow to search for artifacts. | ||
|
||
- **Description**: Name of the workflow to search for to get the artifacts. | ||
- **Required**: No | ||
- **Default**: `build-test-master.yml` | ||
|
||
### `artifact-id` | ||
|
||
Artifact id. | ||
|
||
- **Description**: Identifier of the artifact to be searched for and downloaded. | ||
- **Required**: No | ||
- **Default**: `cli-artifacts-*` | ||
|
||
## Usage | ||
|
||
```yaml | ||
- name: CLI Publish NPM Package | ||
uses: ./.github/actions/publish-npm-cli | ||
with: | ||
ref: 'master' | ||
github-token: ${{ secrets.GITHUB_TOKEN }} | ||
npm-token: ${{ secrets.NPM_TOKEN }} | ||
npm-package-name: 'dotcli' | ||
npm-package-scope: '@dotcms' | ||
node-version: '19' | ||
workflow-to-search: 'build-test-main.yml' | ||
artifact-id: 'cli-artifacts-*' | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,275 @@ | ||
name: 'CLI Publish NPM Package' | ||
description: 'Package the dotCMS CLI as an NPM project.' | ||
inputs: | ||
ref: | ||
description: 'Branch to build from' | ||
required: false | ||
default: 'master' | ||
github-token: | ||
description: 'GitHub Token' | ||
required: true | ||
npm-token: | ||
description: 'NPM Token' | ||
required: true | ||
npm-package-name: | ||
description: 'NPM package name' | ||
required: false | ||
default: 'dotcli' | ||
npm-package-scope: | ||
description: 'NPM package scope' | ||
required: false | ||
default: '@dotcms' | ||
node-version: | ||
description: 'Node.js version' | ||
required: false | ||
default: '19' | ||
artifact-id: | ||
description: 'Artifact id' | ||
required: false | ||
default: 'cli-artifacts-*' | ||
reuse-previous-build: | ||
description: 'Indicates if the workflow should reuse the previous build' | ||
required: false | ||
|
||
runs: | ||
using: "composite" | ||
steps: | ||
- name: 'Checkout' | ||
uses: actions/checkout@v4 | ||
with: | ||
ref: ${{ inputs.ref }} | ||
|
||
- name: 'Set up Node.js' | ||
uses: actions/setup-node@v4 | ||
with: | ||
node-version: ${{ inputs.node-version }} | ||
|
||
- name: 'Install Jinja2' | ||
run: pip install jinja2-cli | ||
shell: bash | ||
|
||
- name: 'Download Build Artifact' | ||
id: data-download | ||
uses: dawidd6/[email protected] | ||
with: | ||
github_token: ${{ inputs.github-token }} | ||
#workflow: ${{ inputs.workflow-to-search }} | ||
commit: ${{ github.sha }} | ||
workflow_conclusion: success | ||
search_artifacts: true | ||
dry_run: true | ||
name: ${{ inputs.artifact-id }} | ||
name_is_regexp: true | ||
path: . | ||
if_no_artifact_found: warn | ||
|
||
- name: 'Check if artifact exists' | ||
id: check | ||
run: | | ||
build_artifact_exists=${{ steps.data-download.outputs.found_artifact }} | ||
if [[ ${build_artifact_exists} == "true" ]]; then | ||
run_id=`echo '${{ steps.data-download.outputs.artifacts }}' | jq -r '.[0].workflow_run.id'` | ||
found_artifacts=true | ||
echo "Artifact Run id: $run_id" | ||
else | ||
echo "No artifact found" | ||
run_id="${{ github.run_id }}" | ||
found_artifacts=false | ||
fi | ||
echo "run_id=$run_id" >> $GITHUB_OUTPUT | ||
echo "found_artifacts=$found_artifacts" >> $GITHUB_OUTPUT | ||
shell: bash | ||
|
||
- name: Download Previous Build Artifact | ||
id: data-download-previous | ||
uses: dawidd6/[email protected] | ||
if: ${{ inputs.reuse-previous-build == true && steps.data-download.outputs.found_artifact == 'false' }} | ||
with: | ||
github_token: ${{ inputs.github-token }} | ||
#workflow: build-test-merge_group.yml | ||
workflow_search: true | ||
#commit: ${{ github.sha }} | ||
workflow_conclusion: success | ||
search_artifacts: true | ||
dry_run: true | ||
name: ${{ inputs.artifact-id }} | ||
path: . | ||
if_no_artifact_found: warn | ||
|
||
- name: 'Check if any previous artifact exists' | ||
id: check-previous | ||
if: ${{ inputs.reuse-previous-build == true && steps.data-download.outputs.found_artifact == 'false' }} | ||
run: | | ||
build_artifact_exists=${{ steps.data-download-previous.outputs.found_artifact }} | ||
if [[ ${build_artifact_exists} == "true" ]]; then | ||
run_id=`echo '${{ steps.data-download-previous.outputs.artifacts }}' | jq -r '.[0].workflow_run.id'` | ||
found_artifacts=true | ||
echo "Artifact Run id: $run_id" | ||
else | ||
echo "No artifact found" | ||
run_id="${{ github.run_id }}" | ||
found_artifacts=false | ||
fi | ||
echo "run_id=$run_id" >> $GITHUB_OUTPUT | ||
echo "found_artifacts=$found_artifacts" >> $GITHUB_OUTPUT | ||
shell: bash | ||
|
||
- name: 'Download all build artifacts' | ||
id: download-cli-artifacts | ||
uses: actions/download-artifact@v4 | ||
with: | ||
pattern: ${{ inputs.artifact-id }} | ||
path: ${{ github.workspace }}/artifacts | ||
github-token: ${{ inputs.github-token }} # token with actions:read permissions on target repo | ||
merge-multiple: true | ||
run-id: ${{ steps.check.outputs.run_id }} | ||
|
||
- name: 'List CLI Artifacts' | ||
run: | | ||
echo "::group::CLI Artifacts" | ||
echo "Artifacts" | ||
ls -R ${{ github.workspace }}/artifacts | ||
echo "::endgroup::" | ||
shell: bash | ||
|
||
- name: 'Extract run-id' | ||
id: extract-metadata | ||
run: | | ||
echo "run-id=${{ github.run_id }}" >> $GITHUB_OUTPUT | ||
shell: bash | ||
|
||
- name: 'Extract package version' | ||
id: project | ||
run: | | ||
echo "::group::Extract package version" | ||
version=$(./mvnw help:evaluate -Dexpression=project.version -q -DforceStdout -pl :dotcms-cli) | ||
echo "::debug::PROJECT VERSION: $version" | ||
echo "version=$version" >> $GITHUB_OUTPUT | ||
echo "::endgroup::" | ||
shell: bash | ||
# Determines the NPM package version and tag | ||
# Distinguishes between snapshots and releases | ||
|
||
- name: 'Dynamic configuration of NPM package Version and Tag' | ||
id: npm-version-tag | ||
run: | | ||
echo "::group::NPM package Version and Tag" | ||
MVN_PACKAGE_VERSION=$(echo ${{ steps.project.outputs.version }} | tr '[:lower:]' '[:upper:]') | ||
PACKAGE_FULL_NAME=${{ inputs.npm-package-scope }}/${{ inputs.npm-package-name }} | ||
# Check if the npm package exists | ||
if ! npm view $PACKAGE_FULL_NAME &> /dev/null; then | ||
echo "::error::The package $PACKAGE_FULL_NAME does not exist on npm." | ||
exit 1 | ||
fi | ||
# Check if the package is a snapshot | ||
REGEX="([0-9]+\.[0-9]+\.[0-9]+)-SNAPSHOT" | ||
if [[ $MVN_PACKAGE_VERSION =~ $REGEX ]]; then | ||
echo "::debug::Snapshot version found." | ||
NPM_PACKAGE_VERSION_TAG="rc" | ||
MVN_BASE_VERSION="${BASH_REMATCH[1]}" | ||
# Use regular expression to extract version components | ||
if [[ $MVN_BASE_VERSION =~ ([0-9]+)\.([0-9]+)\.([0-9]+) ]]; then | ||
MAJOR=$(echo "${BASH_REMATCH[1]}" | sed "s/\b0\+\([1-9]\)/\1/g") | ||
MINOR=$(echo "${BASH_REMATCH[2]}" | sed "s/\b0\+\([1-9]\)/\1/g") | ||
PATCH=$(echo "${BASH_REMATCH[3]}" | sed "s/\b0\+\([1-9]\)/\1/g") | ||
VERSION_NPM_FORMAT="${MAJOR}.${MINOR}.${PATCH}" | ||
echo "::debug::VERSION_NPM_FORMAT: ${VERSION_NPM_FORMAT}" | ||
else | ||
echo "::error::Invalid Maven version format: $MVN_BASE_VERSION" | ||
exit 1 | ||
fi | ||
echo "VERSION_NPM_FORMAT: ${VERSION_NPM_FORMAT}" | ||
LAST_RC_VERSIONS=$(npm view $PACKAGE_FULL_NAME versions --json) | ||
echo "LAST_RC_VERSIONS: ${LAST_RC_VERSIONS}" | ||
LAST_RC_VERSION=$(npm view $PACKAGE_FULL_NAME versions --json | jq --arg filter $VERSION_NPM_FORMAT 'map(.| select(. | contains($filter)))' | jq -r 'map(select(test("-rc\\d+$"))) | max') | ||
if [[ $LAST_RC_VERSION == "$VERSION_NPM_FORMAT"* ]]; then | ||
NEXT_RC_VERSION=$(echo "$LAST_RC_VERSION" | awk -F '-rc' '{print $1 "-rc" $2 + 1}') | ||
RC_SUFFIX=$(echo "$NEXT_RC_VERSION" | sed -n 's/.*-rc\([0-9]*\)/-rc\1/p') | ||
else | ||
RC_SUFFIX="-rc1" | ||
fi; | ||
NPM_PACKAGE_VERSION=${MVN_BASE_VERSION}${RC_SUFFIX} | ||
else | ||
echo "::debug::Release version found." | ||
NPM_PACKAGE_VERSION_TAG="latest" | ||
NPM_PACKAGE_VERSION=${MVN_PACKAGE_VERSION} | ||
fi; | ||
echo "::debug::NPM_PACKAGE_VERSION: $NPM_PACKAGE_VERSION" | ||
echo "::debug::NPM_PACKAGE_VERSION_TAG: $NPM_PACKAGE_VERSION_TAG" | ||
echo "npm-package-version=$NPM_PACKAGE_VERSION" >> $GITHUB_OUTPUT | ||
echo "npm-package-version-tag=$NPM_PACKAGE_VERSION_TAG" >> $GITHUB_OUTPUT | ||
echo "::endgroup::" | ||
shell: bash | ||
|
||
|
||
# Sets up the NPM package | ||
# Creates the bin folder with the binaries | ||
# Adds the postinstall.js script | ||
# Generates the package.json file with Jinja2 | ||
|
||
- name: 'NPM Package setup' | ||
working-directory: ${{ github.workspace }}/tools/dotcms-cli/npm/ | ||
env: | ||
NPM_PACKAGE_NAME: ${{ inputs.npm-package-name }} | ||
NPM_PACKAGE_VERSION: ${{ steps.npm-version-tag.outputs.npm-package-version }} | ||
MVN_PACKAGE_NAME: dotcms-cli | ||
MVN_PACKAGE_VERSION: ${{ steps.project.outputs.version }} | ||
run: | | ||
echo "::group::NPM Package setup" | ||
echo "Adding bin folder with all the binaries" | ||
mkdir -p bin | ||
find ${{ github.workspace }}/artifacts/cli/target/distributions/ -name "*.zip" -exec unzip -d bin {} \; | ||
echo "Adding wrapper script" | ||
mv src/postinstall.js.seed src/postinstall.js | ||
echo "Adding README.md file" | ||
cp ${{ github.workspace }}/tools/dotcms-cli/README.md . | ||
echo "Adding package.json file" | ||
jinja2 package.j2 -D packageName=${MVN_PACKAGE_NAME} -D npmPackageName=${NPM_PACKAGE_NAME} -D npmPackageVersion=${NPM_PACKAGE_VERSION} -D packageVersion=${MVN_PACKAGE_VERSION} --format json -o package.json | ||
rm -f package.j2 | ||
cat package.json | ||
cat src/postinstall.js | ||
echo "::endgroup::" | ||
shell: bash | ||
|
||
- name: 'NPM Package tree' | ||
run: ls -R ${{ github.workspace }}/tools/dotcms-cli/npm/ | ||
shell: bash | ||
|
||
- name: 'Validate NPM package' | ||
working-directory: ${{ github.workspace }}/tools/dotcms-cli/npm | ||
run: | | ||
echo "::group::NPM package contents" | ||
if [ ! -f package.json ]; then | ||
echo "::error::NPM package not found. Exiting..." | ||
exit 1 | ||
else | ||
echo "::notice::NPM package found. Proceeding..." | ||
cat package.json | ||
fi | ||
echo "::endgroup::" | ||
shell: bash | ||
|
||
- name: 'Publish to NPM registry' | ||
working-directory: ${{ github.workspace }}/tools/dotcms-cli/npm | ||
env: | ||
NPM_AUTH_TOKEN: ${{ inputs.npm-token }} | ||
NPM_PACKAGE_VERSION_TAG: ${{ steps.npm-version-tag.outputs.npm-package-version-tag }} | ||
run: | | ||
echo "//registry.npmjs.org/:_authToken=${NPM_AUTH_TOKEN}" > ~/.npmrc | ||
npm publish --access public --tag ${NPM_PACKAGE_VERSION_TAG} | ||
shell: bash |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.