P
Patching is the most significant feature of ADT. You can do a lot of cool things in ADT, but patching is the coolest one. I call this automated patching, because typically I don't have to intervene and I can deploy a patch without any change.
The whole idea behind ADT is to focus on your job as a developer and don't worry about mundane tasks like creating patch files manually. ADT has many checks and features to give you confidence on deploying and time to focus on more important or interesting things.
ADT does not store anything in database and it does not need any objects in database either. The patch.py script gets all the information from your Git repo (folders, files and config file). To make this work, you must be using Git. Without Git repo you will not be able to generate patch files.
This is part of multiple ADT articles:
- Introduction & workflow
- Setup connections, config, folder structure
- Recompile invalid objects
- Searching APEX and searching repo for objects
- Export APEX & live upload
- Export database objects
- Patching & deployment (this article)
Lets talk about workflow
- you will get a task/card to work on
- you will add/change database objects and/or APEX pages/components as needed and in any tool you prefer; you can work with exported files, you can change database objects directly, you can work on your own instance, you can work on the shared one, you can work in a shared branch, you can work in yours, all of that is up to you
- you will export database changes, possibly also data and commit your changes to Git; it really helps a lot to add the task/card number and a meaningful description to the commit summary (for release notes and for better orientation when searching for things and also you will be able to see related commits in Jira), you will use this task/card number later to identify which commits will be part of your patch; also keep in mind that you can commit just parts of the file and you can do unlimited number of commits
- you will export recent APEX changes and commit your changes in Git; again with a proper task/card number
- you will generate and deploy patch file for your next environment (typically UAT, INT, LAB3, however it is called in your company), so you can test your code there with proper data; to do that you will run patch.py and this little magic script will create a patch file for you
You can repeat any of these steps as many times as you need. Before deploying you can change any of the generated files. And you can deploy them via ADT, manually or via your CI/CD pipeline.
Features
The output of patch will be a list of matching commits, patch file in your patch folder and snapshot of each file in snapshots subfolder. The patch file will contain the overview at top so you can see what is planned, it will be enriched with prompts so you don't get lost while reading the logs, it would also contain the source of the files (commit numbers) so you can track it to the source.
There are several cool features built into the ADT to make your life as a developer (or release manager) easier. All your object changes will be sorted properly, so you don't have to worry about that (which also minimize invalidated objects). Grants for your APEX schema will be added automatically. Some other minor source modifications will happen, variables in templates will be replaced, ALTER statements in scripts will be wrapped into a repeatable blocks... And all your files will be copied to snapshots folder in the patch, so you have complete patch there. You can check it and you can change it before deployment.
You can specify patch templates which basically adds template files to specific points in each patch file (for example to setup NLS at start, recompile invalid objects before materialized views, or increase APEX app version after APEX deployment...). Basically anything you would include in every patch.
You can specify patch scripts for specific card numbers, these scripts will be added to a specific point in patch file, but just for this specific patch (typically used for ALTER statements after tables, data changes...), anything you need to add just once for a specific patch. If you delete object or alter table, ADT will generate a file for you in the patch_scripts folder. You have to take care of data changes only. Imagine that, you modify your table (anyhow you want) and you don't have to write the ALTER statements for the patch...
You can also specify which commits you want or don't want to be part of your patch (explore the -search, -commit, -ignore and -my options). You can list individual commits or you can provide ranges.
Multiple schemas are supported in a way. You can have database schema and you can have different APEX schema. If you have multiple database schemas, the dependencies are not resolved beyond each schema. Each APEX application will get its own patch file and if you prefer do deploy full application export (instead of changed pages/components), you can. There are plenty of config options available to customize patching, so it can be tailored to your individual needs. ADT also supports the replacing of existing pages and components.
If your patch can't be deployed right away, you are risking deployment issues later. Depending on your deployment strategy it might happen that you deploy a patch in different order. Imagine you change package in patch 1. And you modify same package in patch 2 and deploy patch 2 first. Later you decide to deploy patch 1 and that would lead to loss of changes made by patch 2. ADT will let you know when you are about to break something and give you more confidence to quickly move around.
Sometimes you just want to deploy older patch but with current files or even you local (uncommitted) files. You can do that too, you just add the -head or -local modifiers.
Some people name columns on views in the view definition and not on the query. I think this is really wrong and you should name columns correctly in the query itself. ADT will check this during the deployment and it will show you the warnings.
For APEX exports it will add some scripts around to setup workspace properly, install (actually replace) shared components first, pages last. It can change page creation/audit columns to match the patch code and date so you know by which patch was the page changed. Via templates you can also change the application version to current date and patch code, set requested authentication scheme (handy if you run different auth scheme on production), keep sessions alive... You can define any pre/post APEX scripts through patch template folder.
There are other features there, I don't remember them all. I will try to update this article later.
Examples
Overview
Show the help and available options:
adt patch
Show recent commits and/or patches (plus option to show just yours):
adt patch -target UAT -commits 50 adt patch -target UAT -commits 50 -my adt patch -target UAT -patches 20 adt patch -target UAT -patches 20 -my
Patching
The main feature, create the patch base on task_id commits:
adt patch -target UAT -patch TASK_ID adt patch -target UAT -patch TASK_ID -create
Create the patch base on task_id commits, but with exceptions (add or ignore specific commit numbers with numbers separated by spaces, you can also use ranges using dash), add -create when ready:
adt patch -target UAT -patch TASK_ID -commit # # #-# #-# adt patch -target UAT -patch TASK_ID -ignore # # #-# #-# adt patch -target UAT -patch TASK_ID -commit 1-20 30-32 35 36 -ignore 2 3 8-12 14-15 31
Use latest committed files or local files (including all uncommitted changes):
adt patch -target UAT -patch TASK_ID -head adt patch -target UAT -patch TASK_ID -local
Create driving patch file above the patch folder:
adt patch -target UAT -patch TASK_ID -moveup
Create patch file based on commits from specific branch:
adt patch -target UAT -patch TASK_ID -branch NAME
Create patch file based on specific words in commit summary:
adt patch -target UAT -patch TASK_ID -search WORDS adt patch -target UAT -patch TASK_ID -search %
Create patch with full application export (ignore changed pages/components):
adt patch -target UAT -patch TASK_ID -create -full
Deployment
Deploy patch to target or specific environment:
adt patch -target UAT -patch TASK_ID -deploy adt patch -target LAB3 -patch TASK_ID -deploy
If there are some errors during the deployment and you don't want to stop on them:
adt patch -target UAT -patch TASK_ID -deploy -continue
If you want to ignore some prechecks:
adt patch -target UAT -patch TASK_ID -deploy -force
Others
Rebuild the Git file (needed when you do some crazy things with your repo):
adt patch -target UAT -rebuild
It might happen that you will see tables in your schema ending with $1/$2, these are temp tables used to generate diff in between the tables and you can drop them:
adt patch -deldiff
There is also a small independent feature which allows you to merge files in specified folder into a single file:
adt patch -implode FOLDER
More on patch templates & scripts
You can create a patch template, which is a list of folders and files which will be added to each your patch at specific point, which depends on object type/group and timing (before, after). All files and subfolders will be sorted alphabetically. You can change the order of objects via the patch_map in your config file. Typically it would go in this order (and again, you can adjust this your config.yaml file):
patch_map: sequences: # group name - SEQUENCE # object type tables: - TABLE types: - TYPE - TYPE BODY synonyms: - SYNONYM objects: - VIEW - PROCEDURE - FUNCTION - PACKAGE - PACKAGE BODY triggers: - TRIGGER mviews: - MVIEW LOG - MATERIALIZED VIEW indexes: - INDEX data: - DATA grants: - GRANT jobs: - JOB
So in your patch_template folder you can create subfolders like tables/before/, tables_before/, before_tables/, tables/after/, tables_after/, after_tables/, after_objects/... You probably get it, right? The pattern is before or after combined with group name. Same logic is used for your patch_scripts/{$PATCH_CODE}/ folder. This way you can specify at which time point will your scripts be executed.
Issues
If you just change the objects grants and not the object itself, the grants will not make it to do patch. In that case, you can add your whole grant file to patch_scripts folder for the specific patch or into patch template for all patches. Revoked grants are not covered yet.
If you change just the comment on table and not the table itself, the comment will not make it to the patch.
Some objects are not supported (what you don't see on the patch_map above).
Some of the 23ai features might not be supported, but I plan to test my apps on 23ai soon.
Happy patching!
Hi Jan, First of all, thank you for sharing ADT with the world! I’m testing it out as a CI/CD tool for our APEX workflow, and it seems much better than SQLcl Liquibase so far. I was able to apply a patch with the example database objects without any problems. However, I ran into an issue when applying an example app:
ReplyDelete```
Error starting at line: 2
File @ /u04/adt-poc/patch/S1240926-2-1235/./snapshots/apex/103_ADT-EXAMPLE.application.pages.page_groups.sql
```
How crucial is it to use Instant Client 19.16? I could only find 19.19, which gives a warning about "Thick driver unavailable for use."
Any advice would be greatly appreciated!
That is awesome, thank you!
DeleteWell, it should work with other clients too, but I cant test every combination on every platform. If you can, I would recommend to use Thin mode if possible, that way you wont need IC at all. In some cases you have to have Thick driver to connect, in that case, you can install/unzip older IC, like the 19.16 and in connection.yaml file you can use the path (instead of thick:Y) like: thick: "C:\..."
In "adt config -version" you should be able to verify which IC it is using.
Also, I did now noticed the file name. Ideally if you are installing the app for the first time, you should just do it with/via fulle export. Then you can use ADT for additional changes. I dont think you can run the page_groups file.
Delete