This guide will show you how to patch a package in Backstage using the patch-package
tool.
- Have a
rhdh
instance locally cloned - Have a
backstage
instance/fork locally cloned
-
Create a new branch in your
backstage
instance for your target backstage version -
Navigate to the
backstage
project and make your changes to the package/plugin you want to patch as if you were going to submit a PR -
Run the following commands in the root directory of the
backstage
project, we will use the scaffolder-backend plugin (v1.23.0 for backstage v1.29.2) as an example:yarn tsc # Generate typescript types for build cd plugins/scaffolder-backend
-
Then in the
backstage/plugins/scaffolder-backend
directory, run the following commands:# Build the plugin yarn build # Generate the tar archive for the plugin npm pack . # Extract the contents of the tar archive tar -xzf scaffolder-backend-1.23.0.tgz rm scaffolder-backend-1.23.0.tgz # Rename the extracted package directory to match the package name in the @backstage/node_modules mv package plugin-scaffolder-backend # This is an optional step to remove the old .cjs.js and .cjs.js.map files in the dist/cjs directory of the package. Please refer to the caveats section for more information update_file_references # Merge the contents of the patched package into the node_modules directory of the rhdh project cp -Rv plugin-scaffolder-backend/* /home/user/rhdh/node_modules/@backstage/plugin-scaffolder-backend
-
Then navigate to the
rhdh
project and run the following commands to generate the patch files:# Generate the patch file yarn patch-package @backstage/plugin-scaffolder-backend # Reinstall the dependencies to verify patches were applied properly yarn install --force
-
Repeat for the rest of your plugins/packages
Using the patch-package
script
-
Create a new branch in your
backstage
instance for your target backstage version -
Navigate to the
backstage
project and make your changes to the package/plugin you want to patch as if you were going to submit a PR -
Navigate to the
rhdh
project and run the.scripts/patch-package.sh
to create a patch file for the package(s) you want to patch.-
Script Usage:
./patch-package.sh [src] [dest] [package-name-1] [package-name-2] ...
-
The
src
is the path to thebackstage
project containing your patch changes -
The
dest
is the path to therhdh
project where the patch file will be created -
The
package-name
array of arguments is the name of the package(s) you want to patch -
When listing package names, please ensure it matches the package name in the
@backstage/node_modules
directory of therhdh
project -
Example usage of patching a plugin and a package:
./patch-package.sh /path/to/backstage /path/to/rhdh @backstage/plugin-scaffolder-backend @backstage/integration
-
-
The script will create patch files in the
patches
directory of therhdh
project. Runyarn install --force
in therhdh
project and verify that the patches were applied correctly
-
The
patch-package
script will not work if the package you are trying to patch is not installed in therhdh
project -
The
patch-package
script will not be able to patch modifications to thepackage.json
to add new dependencies or change the version of existing dependencies- You will need to manually update the
package.json
in therhdh
project to include the new dependencies or changes to existing dependencies since the patches are applied after theyarn install
command is run
- You will need to manually update the
-
The
patch-package
script will leave behind the old.cjs.js
and.cjs.js.map
files in thedist/cjs
directory of the package if the resultant package's adist/cjs
directory that contains more than 2 files-
This is due to the resultant file names after a build being different if any modifications were made to them.
-
The
cp -R
command would not be able to overwrite the old files with the new files since the file names would be different. However, all file references in the package should be automatically updated to point to the new files, so the behavior of the package should not be affected.-
For example, the
dist
directory of thecatalog-backend
package in thenode_modules
would be structured like so AFTER merging the patched package:. ├── alpha.cjs.js ├── alpha.cjs.js.map ├── alpha.d.ts ├── cjs │ ├── CatalogBuilder-Cu6UKYtc.cjs.js # Newly Patched Version │ ├── CatalogBuilder-Cu6UKYtc.cjs.js.map # Newly Patched Version │ ├── CatalogBuilder-g0TDave-.cjs.js # Old Package │ └── CatalogBuilder-g0TDave-.cjs.js.map # Old Package ├── index.cjs.js ├── index.cjs.js.map └── index.d.ts
-
-
Deleting these files would result in the patches failing to apply properly due to the
patch-package
package not being able to handle patches that modify a file while also changing it's name. See ds300/patch-package#518. -
If you do want to remove the old versions of these files, you would need to follow the following procedure BEFORE merging the newly patched package with the
node_modules
package withcp -R
(we will use theplugin-catalog-backend
as an example):-
You would need to manually rename the new files to match the old file names in the patched version of the package:
FILE_NAME=CatalogBuilder-Cu6UKYtc NEWLY_BUILT_FILE_NAME=CatalogBuilder-g0TDave- cd path-to-patched-package/plugin-catalog-backend/ mv dist/cjs/${FILE_NAME}.cjs.js dist/cjs/${NEWLY_BUILT_FILE_NAME}.cjs.js mv dist/cjs/${FILE_NAME}.cjs.js.map dist/cjs/${NEWLY_BUILT_FILE_NAME}.cjs.js.map
-
Update all references to the newly patched file names in the package to point to the old file names. This is automatically done for you by the
patch-package.sh
script when there are only 2 files in thedist/cjs
directory of the package. It will skip the renaming step if there are more than 2 files in thedist/cjs
directories, so you will need to manually update the references in those cases:cd path-to-patched-package/plugin-catalog-backend/ find . -type f -exec sed -i "s/${NEWLY_BUILT_FILE_NAME}/${FILE_NAME}/g" {} \;
-
Repeat for any other files that need to be renamed
-
Merge the patched package with the
node_modules
package in therhdh
project
-
-