Skip to content

Commit

Permalink
fix(deployment): Edit Page V2 Automate the deploy of the SDK librar (#…
Browse files Browse the repository at this point in the history
…28259) (#29876)

### Proposed Changes
* This pull request introduces an improved approach for managing version
increments and dependency updates for the dotCMS SDK libraries. Unlike
the previous solution that handled version calculations locally before
committing, this new method performs version calculation and updates
directly within the continuous integration flow, specifically after a
merge and during the deployment phase.

The new solution ensures that all SDK libraries in the repository are
updated centrally and consistently. Key improvements include:

Version Updates: Automatically increments the version of each SDK
package found in the relevant directory.
Dependency Management: Updates peerDependencies between SDK libraries to
maintain internal compatibility.
NPM Publishing: Publishes each updated SDK library to the NPM registry,
ensuring that the latest versions are readily available.

### Additional Info
Related to #28259 (Edit Page V2 Automate the deploy of the SDK librar).
  • Loading branch information
dcolina authored Sep 5, 2024
1 parent b840eaf commit acea671
Show file tree
Hide file tree
Showing 10 changed files with 249 additions and 146 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,26 +33,29 @@ This GitHub Action is designed to automate the process of publishing dotCMS SDK
5. **Publish SDK into NPM Registry**: Publishes the SDK libraries to NPM if the version is validated.

## Detailed Steps
1. **Checkout**
The action uses `actions/checkout@v4` to check out the specified branch, allowing the workflow to access the repository's contents.

2. **Set Up Node.js**
`actions/setup-node@v4` sets up the Node.js environment, crucial for running scripts and managing dependencies.
1. **Checkout**
The action uses `actions/checkout@v4` to check out the specified branch, allowing the workflow to access the repository's contents.

3. **Get Next Version**
This step retrieves the next version of the SDK by reading the `package.json` file from the specified directory.
2. **Set Up Node.js**
`actions/setup-node@v4` sets up the Node.js environment, crucial for running scripts and managing dependencies.

4. **Validate Version**
The version retrieved in the previous step is compared to the current version in the NPM registry. The workflow checks if the version is already published or if it follows the expected versioning scheme.
3. **Get Next Version**
This step retrieves the next version of the SDK by reading the `package.json` file from the specified directory.

5. **Publish SDK into NPM Registry**
If the validation passes, the SDK libraries are published to the NPM registry. The libraries are iterated over, and each is published using the provided NPM token and tag.
4. **Validate Version**
The version retrieved in the previous step is compared to the current version in the NPM registry. The workflow checks if the version is already published or if it follows the expected versioning scheme.

5. **Publish SDK into NPM Registry**
If the validation passes, the SDK libraries are published to the NPM registry. The libraries are iterated over, and each is published using the provided NPM token and tag.

### Notes

- The versions of the SDK libraries will be incremented in the NPM registry, but they will not be updated in the codebase itself through this process. This simplification avoids automatic pull requests and all the considerations necessary due to protections on the main branch, as well as the lengthy execution process that would be required to ultimately publish the libraries.
- This is a temporary solution until we determine the most appropriate pattern to handle the lifecycle of each module that needs to be released individually (e.g., dotCLI and the SDKs).
- Additionally, the example projects should point to the 'latest' tag to ensure that version updates do not impact their functionality due to version inconsistency.
- Ensure that the NPM token provided has the correct permissions to publish packages.
- The action assumes that the `package.json` files are located under `core-web/libs/sdk/client`.
- The publish step only runs if the version validation passes, ensuring that no duplicate versions are published.

## Usage Example

Expand All @@ -71,7 +74,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Publish to NPM
uses: ./path-to-this-action
uses: ./.github/actions/core-cicd/deployment/deploy-javascript-sdk
with:
ref: 'master'
npm-token: ${{ secrets.NPM_TOKEN }}
Expand Down
218 changes: 218 additions & 0 deletions .github/actions/core-cicd/deployment/deploy-javascript-sdk/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
# Note: The versions of the SDK libraries will be incremented in the NPM registry,
# but they will not be updated in the codebase itself through this process.
# This simplification avoids automatic pull requests and all the considerations
# necessary due to protections on the main branch, as well as the lengthy execution
# process that would be required to ultimately publish the libraries.
#
# This is a temporary solution until we determine the most appropriate pattern
# to handle the lifecycle of each module that needs to be released individually
# (e.g., dotCLI and the SDKs).
#
# Additionally, the example projects should point to the 'latest' tag to ensure
# that version updates do not impact their functionality due to version inconsistency.
name: 'SDK Publish NPM Packages'
description: 'Publish the dotCMS SDK libs on NPM registry.'
inputs:
ref:
description: 'Branch to build from'
required: false
default: 'master'
npm-token:
description: 'NPM token'
required: true
npm-package-tag:
description: 'Package tag'
required: false
default: 'alpha'
node-version:
description: 'Node.js version'
required: false
default: '19'
github-token:
description: 'GitHub Token'
required: true
outputs:
npm-package-version:
description: 'SDK libs - NPM package version'
value: ${{ steps.next_version.outputs.next_version }}
published:
description: 'SDK libs - Published'
value: ${{ steps.next_version.outputs.publish }}
runs:
using: "composite"
steps:
- name: 'Checkout'
uses: actions/checkout@v4
with:
ref: ${{ inputs.ref }}
token: ${{ inputs.github-token }}

- name: 'Set up Node.js'
uses: actions/setup-node@v4
with:
node-version: ${{ inputs.node-version }}

- name: 'Get current version from NPM'
id: current_version
run: |
echo "::group::Get current version"
CURRENT_VERSION=$(npm view @dotcms/client dist-tags --json | jq -r '.alpha')
echo "Current version: $CURRENT_VERSION"
echo "current_version=$CURRENT_VERSION" >> $GITHUB_OUTPUT
echo "::endgroup::"
shell: bash

- name: Calculate next version
id: next_version
env:
CURRENT_VERSION: ${{ steps.current_version.outputs.current_version }}
run: |
echo "::group::Calculate next version"
VERSION_PARTS=(${CURRENT_VERSION//./ })
BASE_VERSION="${VERSION_PARTS[0]}.${VERSION_PARTS[1]}.${VERSION_PARTS[2]}"
ALPHA_PART=${VERSION_PARTS[3]#*-}
ALPHA_NUMBER=${ALPHA_PART#*.}
NEW_ALPHA_NUMBER=$((ALPHA_NUMBER + 1))
NEXT_VERSION="${BASE_VERSION}.${NEW_ALPHA_NUMBER}"
echo "Next version: $NEXT_VERSION"
echo "next_version=$NEXT_VERSION" >> $GITHUB_OUTPUT
echo "::endgroup::"
shell: bash

- name: 'Printing versions'
working-directory: ${{ github.workspace }}/core-web/libs/sdk/
env:
NEXT_VERSION: ${{ steps.next_version.outputs.next_version }}
CURRENT_VERSION: ${{ steps.current_version.outputs.current_version }}
run: |
echo "::group::Update versions"
echo "Current version: $CURRENT_VERSION"
echo "Next version: $NEXT_VERSION"
echo "::endgroup::"
shell: bash

- name: 'Bump SDK version and update dependencies'
working-directory: ${{ github.workspace }}/core-web/libs/sdk/
env:
NEXT_VERSION: ${{ steps.next_version.outputs.next_version }}
EXAMPLES_PATH: ${{ github.workspace }}/examples
run: |
echo "Updating version to $NEXT_VERSION"
# Function to update the version in package.json using jq
update_version() {
local pkg_dir="$1"
local new_version="$2"
local package_json_path="$pkg_dir/package.json"
if [ -f "$package_json_path" ]; then
jq --arg new_version "$new_version" '.version = $new_version' "$package_json_path" > tmp.$$.json && mv tmp.$$.json "$package_json_path"
echo "Updated version in $package_json_path to $new_version"
else
echo "::warn::Warning: No package.json found in $pkg_dir"
fi
}
# Function to update peerDependencies in package.json
update_peer_dependencies() {
local pkg_dir="$1"
local new_version="$2"
local package_json_path="$pkg_dir/package.json"
if [ -f "$package_json_path" ]; then
for dep in "${sdk_packages[@]}"; do
if jq -e ".peerDependencies[\"@dotcms/$dep\"]" "$package_json_path" >/dev/null; then
jq --arg new_version "$new_version" ".peerDependencies[\"@dotcms/$dep\"] = \$new_version" "$package_json_path" > tmp.$$.json && mv tmp.$$.json "$package_json_path"
echo "::debug::Updated peerDependency @dotcms/$dep in $package_json_path to $new_version"
else
echo "::debug::PeerDependency @dotcms/$dep not found in $package_json_path, skipping update."
fi
done
else
echo "::warn::Warning: No package.json found in $pkg_dir"
fi
}
# Function to update dependencies in examples package.json
update_dependencies_in_examples() {
local example_dir="$1"
local new_version="$2"
local package_json_path="$example_dir/package.json"
if [ -f "$package_json_path" ]; then
for dep in "${sdk_packages[@]}"; do
if jq -e ".dependencies[\"@dotcms/$dep\"]" "$package_json_path" >/dev/null; then
jq --arg sdk_name "@dotcms/$dep" --arg new_version "$new_version" \
'.dependencies[$sdk_name] = $new_version' \
"$package_json_path" > tmp.$$.json && mv tmp.$$.json "$package_json_path"
echo "::debug::Updated dependency @dotcms/$dep in $package_json_path to $new_version"
else
echo "::debug::Dependency @dotcms/$dep not found in $package_json_path, skipping update."
fi
done
else
echo "::warn::Warning: No package.json found in $example_dir"
fi
}
# Detect all SDK packages dynamically in the libs/sdk directory
sdk_packages=($(find . -maxdepth 1 -type d -exec basename {} \; | grep -v "^\.$"))
# Step 1: Update the version in each SDK package
for sdk in "${sdk_packages[@]}"; do
update_version "$sdk" "$NEXT_VERSION"
done
# Step 2: Update peerDependencies in each SDK package
for sdk in "${sdk_packages[@]}"; do
update_peer_dependencies "$sdk" "$NEXT_VERSION"
done
# Step 3: Update dependencies in example projects
example_packages=$(find $EXAMPLES_PATH -name "package.json" -not -path "*/node_modules/*")
for package_json_path in $example_packages; do
example_dir=$(dirname "$package_json_path")
update_dependencies_in_examples "$example_dir" "$NEXT_VERSION"
done
shell: bash

- name: 'Printing SDK packages'
env:
SDK_LIBS_PATH: ${{ github.workspace }}/core-web/libs/sdk
EXAMPLES_PATH: ${{ github.workspace }}/examples
run: |
print_packages() {
cd $1
ls -ls | awk '{ print$10 }' | grep -v '^$' | while read a; do echo -e "${a}:\n" && cat ./${a}/package.json && echo -e "\n"; done
}
echo "::group::Printing SDK and Example packages"
echo "SDK libs:"
print_packages "$SDK_LIBS_PATH"
echo ""
echo "Examples:"
print_packages "$EXAMPLES_PATH"
echo "::endgroup::"
shell: bash

- name: 'Publishing sdk into NPM registry'
if: ${{ steps.validate_version.outputs.publish == 'true' }}
working-directory: ${{ github.workspace }}/core-web/libs/sdk/
env:
NEXT_VERSION: ${{ steps.next_version.outputs.next_version }}
NPM_AUTH_TOKEN: ${{ inputs.npm-token }}
NPM_TAG: ${{ inputs.npm-package-tag }}
run: |
echo "::group::Publishing SDK packages"
sdks=$(ls)
for sdk in $sdks; do
echo "Publishing SDK lib [${sdk}]"
cd $sdk && echo "$(pwd)"
echo "//registry.npmjs.org/:_authToken=${NPM_AUTH_TOKEN}" > ~/.npmrc
npm publish --access public --tag $NPM_TAG
npm dist-tag $NEXT_VERSION latest
cd ..
done
echo "::endgroup::"
shell: bash

105 changes: 0 additions & 105 deletions .github/actions/core-cicd/deployment/deploy-sdk-npm/action.yml

This file was deleted.

6 changes: 3 additions & 3 deletions .github/workflows/cicd_comp_deployment-phase.yml
Original file line number Diff line number Diff line change
Expand Up @@ -152,11 +152,10 @@ jobs:
- name: SDKs Publish
id: sdks_publish
if: inputs.publish-npm-sdk-libs
uses: ./.github/actions/core-cicd/deployment/deploy-sdk-npm
uses: ./.github/actions/core-cicd/deployment/deploy-javascript-sdk
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
npm-token: ${{ secrets.NPM_ORG_TOKEN }}
sdk-artifact-run-id: ${{ github.run_id }}

# Send Slack notification for Docker image deployment (if repository is 'dotcms/core')
- name: Slack Notification (Docker image announcement)
Expand All @@ -179,7 +178,8 @@ jobs:
payload: |
> :large_purple_circle: *Attention dotters:* dotCLI published!
>
> This automated script is happy to announce that a new *_dotCLI_* version *tagged as:* [ `${{ steps.cli_publish.outputs.npm-package-version }}, ${{ steps.cli_publish.outputs.npm-package-version-tag }}` ] is now available on the `NPM` registry :package:!\n \n>`npm i -g @dotcms/dotcli@${{ steps.cli_publish.outputs.npm-package-version-tag }}`
> This automated script is happy to announce that a new *_dotCLI_* version *tagged as:* [ `${{ steps.cli_publish.outputs.npm-package-version }}, ${{ steps.cli_publish.outputs.npm-package-version-tag }}` ] is now available on the `NPM` registry :package:!
> `npm i -g @dotcms/dotcli@${{ steps.cli_publish.outputs.npm-package-version-tag }}`
slack-bot-token: ${{ secrets.SLACK_BOT_TOKEN }}

# Send Slack notification for SDK publication (if required)
Expand Down
Loading

0 comments on commit acea671

Please sign in to comment.