@dotcms/dotcli 24.1.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,278 @@
1
+ # dotCMS CLI
2
+ The dotCMS CLI is a command-line tool that you can use to populate and modify your dotCMS instances from a command shell.
3
+
4
+ ## Quick start
5
+ 1. Download the CLI: The dotCMS CLI is delivered as an uber jar that can be downloaded from [here](https://repo.dotcms.com/artifactory/libs-snapshot-local/com/dotcms/dotcms-cli/).
6
+ Once downloaded, you just need to run it with:
7
+
8
+ ```shell script
9
+ java -jar dotcli.jar
10
+ ```
11
+
12
+ 2. Configure the dotCMS instances you want to connect to using a dot-service.yml file. More details on how to do it [on this section](## CLI Instance Configuration). Make sure you make a site active in the yml file, otherwise you will have to active one using the [`instance` command](## Available Commands)
13
+
14
+ 3. Log in to the selected instance
15
+ ```shell script
16
+ java -jar dotcli.jar login --user={USER} --password
17
+ ```
18
+
19
+
20
+
21
+ ## Available Commands
22
+
23
+ | Command | Description |
24
+ |--------------------------------------------|-------------------------------------------------------------------------------------|
25
+ | [content-type](cli/docs/content-type.adoc) | Performs operations over content types. For example: pull, push, remove |
26
+ | [files](cli/docs/files.adoc) | Performs operations over files. For example: tree, ls, push |
27
+ | [instance](cli/docs/instance.adoc) | Prints a list of available dotCMS instances |
28
+ | [language](cli/docs/language.adoc) | Performs operations over languages. For example: pull, push, remove |
29
+ | [login](cli/docs/login.adoc) | Logs into a dotCMS instance |
30
+ | [push](cli/docs/push.adoc) | Global push command used to sync a GitHub repo with a target dotCMS environment |
31
+ | [pull](cli/docs/pull.adoc) | Global pull command used to sync a target dotCMS environment with a local workspace |
32
+ | [site](cli/docs/site.adoc) | Performs operations over sites. For example: pull, push, remove |
33
+ | [status](cli/docs/status.adoc) | Provides information about the current logged-in user and dotCMS instance status |
34
+
35
+
36
+ You can find more details about how to use the dotCMS CLI in the [Examples](#examples) section.
37
+
38
+
39
+
40
+ ## Examples
41
+
42
+ 1. Log in with an admin user
43
+ ```shell script
44
+ login --user=admin@dotCMS.com --password
45
+ ```
46
+ 2. List and choose the dotCMS instance we want to run against
47
+ ```shell script
48
+ instance --list
49
+ ```
50
+ 3. Activate a dotCMS instance profile called `demo`
51
+ ```shell script
52
+ instance --activate demo
53
+ ```
54
+ 4. Get info of the current instance running
55
+ ```shell
56
+
57
+ status
58
+
59
+ #You will get an output similar to:
60
+ 2023-02-22 11:25:29,499 INFO [com.dot.api.cli.HybridServiceManagerImpl] (Quarkus Main Thread) Service [default] is missing credentials.
61
+ 2023-02-22 11:25:29,500 INFO [com.dot.api.cli.HybridServiceManagerImpl] (Quarkus Main Thread) Service [demo] is missing credentials.
62
+ Active instance is [demo] API is [https://demo.dotcms.com/api] No active user Use login Command.
63
+ ```
64
+
65
+ 5. Pull a content type
66
+ ```shell script
67
+ content-type pull FileAsset
68
+ ```
69
+ 6. Create a new site
70
+ ```shell script
71
+ site create "my.cool.bikes.site.com"
72
+ ```
73
+
74
+ ## Building the CLI (dev mode)
75
+
76
+ The CLI is a quarkus/pico-cli project made up of two modules [cli](cli) and [api-data-module](api-data-model).
77
+ This project acts as a maven reactor pom build. You can build at the top level to build the modules.
78
+
79
+ ```shell script
80
+ ./mvnw clean install -DskipTests=true
81
+ ```
82
+
83
+ We suggest to build the project ignoring test execution (`-DskipTests=true`). It will run faster and avoid setting up a testing environment.
84
+
85
+ #### Running the CLI (dev mode)
86
+
87
+ You might use [quarkus cli](https://es.quarkus.io/guides/cli-tooling) or [maven](https://maven.apache.org/install.html)
88
+ First, start a dotCMS instance locally.
89
+ Then, execute the following commands
90
+
91
+ ```shell script
92
+ # from top level to build all
93
+ cd cli
94
+ # command is same as the following to run the quarkus build plugin
95
+ # ../mvnw quarkus:dev
96
+ quarkus dev
97
+ ```
98
+ **NOTE:** To reduce duplication in the multi-module project, mvnw is not included on each submodule.
99
+ The quarkus command finds the executable
100
+
101
+ To run mvnw from a submodule just use a relative path to the parent mvn.
102
+ If running from a submodule folder, all the dependencies will need to be up to date and installed to the local mvn with maven install
103
+
104
+ Alternatively, you can specify the subproject from the parent folder
105
+ ```shell script
106
+ # from top level to build all
107
+ cd cli
108
+ # The command is same as the following to run the quarkus build plugin
109
+ # ../mvnw quarkus:dev
110
+ ../mvnw -pl cli quarkus:dev
111
+ ```
112
+
113
+ Once the cli is launched in dev mode it'll print out a list of available commands.
114
+
115
+ followed by
116
+
117
+ ```shell script
118
+ --
119
+ Tests paused
120
+ Press [space] to restart, [e] to edit command line args (currently ''), [r] to resume testing, [o] Toggle test output, [:] for the terminal, [h] for more options>
121
+ ```
122
+
123
+ We can also instruct Quarkus dev mode to launch our cli using a preconfigured param by doing:
124
+ ```shell script
125
+ ../mvn quarkus:dev -Dquarkus.args=status
126
+ ```
127
+ This will launch the cli passing directly into it the arguments that tell them to execute the command status.
128
+
129
+ ## Building a CLI jar
130
+ In order to generate the cli as a jar packaged with all necessary dependencies you need to run the following command from the `cli` directory:
131
+ ```shell script
132
+ ../mvnw clean install package
133
+ ```
134
+
135
+ All the commands can be executed directly from the generated jar which can be found under `cli/target/quarkus-app/`.
136
+
137
+ Example:
138
+ ```shell script
139
+ java -jar ./cli/target/quarkus-app/quarkus-run.jar status
140
+ ```
141
+
142
+ ## Logging
143
+
144
+ When running the CLI, a **_dotcms-cli.log_** file will be created in the directory where the CLI
145
+ executable is run.
146
+
147
+ #### File log level
148
+
149
+ To increase the file log level to _DEBUG_ when running in dev mode, use the following command:
150
+
151
+ ```shell
152
+ ../mvnw quarkus:dev -Dquarkus.log.file.level=DEBUG
153
+ ```
154
+
155
+ #### Console log level
156
+
157
+ To increase the console log level to _DEBUG_ when running in dev mode, use the following command:
158
+
159
+ ```shell
160
+ ../mvnw quarkus:dev -Dquarkus.log.handler.console.\"DOTCMS_CONSOLE\".level=DEBUG
161
+ ```
162
+
163
+ #### File log location
164
+
165
+ To override the default location of the log file, you have two options:
166
+
167
+ ##### 1. Set the environment variable
168
+
169
+ Example:
170
+
171
+ ```shell
172
+ export QUARKUS_LOG_FILE_PATH=/Users/my-user/CLI/dotcms-cli.log
173
+ java -jar cli-1.0.0-SNAPSHOT-runner.jar login -u admin@dotcms.com -p
174
+ ```
175
+
176
+ ##### 2. Set the system property
177
+
178
+ Example:
179
+
180
+ ```shell
181
+ ../mvnw quarkus:dev -Dquarkus.log.file.path=/Users/my-user/CLI/dotcms-cli.log
182
+ ```
183
+
184
+ ## CLI Instance Configuration
185
+
186
+ The CLI can be used to manage multiple dotCMS instances. Each instance profile is defined in the `~/.dotcms/dot-service.yml` file.
187
+ Whatever profile is active will be used by the CLI to execute the commands.
188
+ The selected profile can be obtained by running the `status` command.
189
+ Here's an example of the default `dot-service.yml` file shipped with the CLI:
190
+
191
+ ```yaml
192
+ - name: "default"
193
+ credentials:
194
+ user: "admin@dotcms.com"
195
+ - name: "demo"
196
+ active: true
197
+ credentials:
198
+ user: "admin@dotCMS.com"
199
+ ```
200
+
201
+ The profiles declared on this file are paired up with properties defined in an internal `application.properties` file.
202
+
203
+ ```properties
204
+ # Your configuration properties
205
+ dotcms.client.servers.default=http://localhost:8080/api
206
+ dotcms.client.servers.demo=https://demo.dotcms.com/api
207
+ ```
208
+
209
+ Notice how the `dotcms.client.servers` property has a suffix matching the profile name in the `dot-service.yml` file.
210
+
211
+ Therefore, in order to add a new instance profile, you need to add a new entry in the `dot-service.yml` file and a new property extending the `application.properties` file.
212
+ Application properties can be extended via system properties, environment variables, `.env` file or in `$PWD/config/application.properties` file.
213
+
214
+ To learn more about how to extend the `application.properties` file see the Quarkus configuration guide [Here](https://es.quarkus.io/guides/config-reference#application-properties-file)
215
+
216
+ In future versions this process will be facilitated by the CLI itself.
217
+
218
+ ### Workspace
219
+
220
+ The CLI needs a workspace to be able to pull and push content to a dotCMS instance.
221
+ The workspace is basically a set of directories and files used to house and organize the different type of assets that can be managed by the CLI.
222
+ Additionally, a marker file called `.dot-workspace.yml` indicates to the CLI that the current directory is a valid workspace.
223
+ In the following table you can see the different directories and files that conform a workspace.
224
+
225
+ | File/Directory | Type | Description |
226
+ |----------------------|------|-------------------------|
227
+ | `content-types/` | Dir | Content-Types directory |
228
+ | `files/` | Dir | Files directory |
229
+ | `languages/` | Dir | Languages Directory |
230
+ | `sites/` | Dir | Sites Directory |
231
+ | `.dot-workspace.yml` | File | CLI workspace marker |
232
+
233
+ ## GitHub Actions Integration
234
+ We provide support for GitHub Actions to be able to run the CLI as part of your CI/CD pipeline.
235
+
236
+ The following example shows how to create a brand-new repository and seed it with a CLI workspace.
237
+ In order to incorporate the CLI into your GitHub Actions workflow, you need to:
238
+
239
+ - Create a GitHub Repository to manage your dotCMS assets.
240
+ - Copy the contents of the [action](./action) directory into your root project `.github/workflows` directory.
241
+ - In Your repository General Settings, enable the following permissions:
242
+ - Workflow Permissions : Read and Write permissions
243
+ - In Your repository General Settings, Secrets and variables, Actions
244
+ - Create a new variable called `DOT_API_URL` and set the value to a valid dotCMS URL. e.g. `https://demo.dotcms.com/api`
245
+ ![How to create a variable](doc_images/create_variable.png)
246
+ - Create a new secret called `DOT_TOKEN` and set the value to a valid dotCMS CLI token.
247
+ ![How to create a secret](doc_images/create_secret.png)
248
+ - Seed your local repository with a CLI workspace
249
+ * A cli workspace can be created by running any pull command e.g. `java -jar dotcli.jar files pull //demo.dotcms.com`
250
+ * Run any pull command from the root of your project see [examples](#examples) section.
251
+ * A valid CLI workspace should contain a `.dot-workspace` file in the root of your project. Make sure to commit this file to your repository and the others that conform your workspace see the [workspace](#workspace) section.
252
+ * Commit and push the changes to your repository.
253
+
254
+ - Now if the integration is successful, you should see a new commits made into your repository reflect in you dotCMS instance.
255
+
256
+ Here's an example of how a Git repository could look like after the GitHub Action has been integrated:
257
+
258
+ | File/Directory | Type | Description |
259
+ |----------------------|------|---------------------------|
260
+ | `.github/workflows/` | Dir | GitHub Actions workflow |
261
+ | `content-types/` | Dir | Content-Types directory |
262
+ | `files/` | Dir | Files directory |
263
+ | `languages/` | Dir | Languages Directory |
264
+ | `sites/` | Dir | Sites Directory |
265
+ | `.dot-workspace.yml` | File | CLI workspace marker |
266
+ | `.gitignore` | File | Git files exclude |
267
+ | `README.md` | File | Project readme |
268
+ | `.env` | File | Push command Options Spec |
269
+
270
+ - The default command executed by our GitHub Action is the global `push`
271
+ - Global Push has different options. For more details to control the execution of the command see [Global Push](cli/docs/push.adoc) section for more details.
272
+ - Any additional Options required by the Global push command can be specified in the `.env` file in the following format `DOT_CLI_OPTS="--option1 --option2"`
273
+ So a valid example of a `.env` file could look like this `DOT_CLI_OPTS="--force --dry-run"`
274
+ ```shell script
275
+ DOT_CLI_OPTS=" --removeAssets --removeFolders --removeSites --removeContentTypes --removeLanguages --errors"
276
+ ```
277
+ These options can cause data loss, so use them with caution. That's why they are not enabled by default.
278
+ Do not enable them unless you know what you are doing.
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "@dotcms/dotcli",
3
+ "version": "24.01.26",
4
+ "scripts": {
5
+ "postinstall": "node src/postinstall.js install",
6
+ "postuninstall": "node src/postinstall.js uninstall && npm prune"
7
+ },
8
+ "binaries": {
9
+ "dotcms-cli-darwin-arm64": "bin/dotcms-cli-24.01.26-osx-aarch_64",
10
+ "dotcms-cli-darwin-x64": "bin/dotcms-cli-24.01.26-osx-x86_64",
11
+ "dotcms-cli-linux-x64": "bin/dotcms-cli-24.01.26-linux-x86_64"
12
+ },
13
+ "alias": "dotcli",
14
+ "packageName": "dotcms-cli",
15
+ "files": [
16
+ "bin",
17
+ "src"
18
+ ],
19
+ "description": "Official command-line tool to manage dotCMS content.",
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "git+https://github.com/dotCMS/core.git#master"
23
+ },
24
+ "keywords": [
25
+ "dotCMS",
26
+ "CMS",
27
+ "Content Management",
28
+ "CLI",
29
+ "dotCMS CLI",
30
+ "dotCMS command-line tool"
31
+ ],
32
+ "author": "dotcms <dev@dotcms.com>",
33
+ "license": "MIT",
34
+ "bugs": {
35
+ "url": "https://github.com/dotCMS/core/issues"
36
+ }
37
+ }
@@ -0,0 +1,154 @@
1
+ "use strict";
2
+
3
+ const path = require('path');
4
+ const fs = require('fs').promises;
5
+ const os = require('os');
6
+
7
+ const ARCHITECTURE_MAPPING = {
8
+ "x64": "x86_64",
9
+ "arm64": "aarch_64"
10
+ };
11
+
12
+ const PLATFORM_MAPPING = {
13
+ "darwin": "osx",
14
+ "linux": "linux"
15
+ };
16
+
17
+ function getGlobalBinPath() {
18
+ const npmGlobalPrefix = process.env.PREFIX || process.env.npm_config_prefix || process.env.HOME;
19
+ return path.join(npmGlobalPrefix, 'bin');
20
+ }
21
+
22
+ function validatePackageConfig(packageJson) {
23
+ if (!packageJson.version || !packageJson.packageName || !packageJson.alias || !packageJson.binaries || typeof packageJson.binaries !== "object") {
24
+ throw new Error("Invalid package.json. 'version', 'packageName', 'alias' and 'binaries' must be specified.");
25
+ }
26
+ }
27
+
28
+ async function parsePackageJson() {
29
+
30
+ console.log("Installing CLI");
31
+ const platform = os.platform();
32
+ const architecture = os.arch();
33
+
34
+ console.log("Platform: " + platform);
35
+ console.log("Architecture: " + architecture);
36
+
37
+ if (!(os.arch() in ARCHITECTURE_MAPPING) || !(os.platform() in PLATFORM_MAPPING)) {
38
+ throw new Error(`Installation is not supported for this ${platform}/${architecture} combination.`);
39
+ }
40
+
41
+ const packageJsonPath = path.join(".", "package.json");
42
+
43
+ try {
44
+ const packageJsonContent = await fs.readFile(packageJsonPath, "utf-8");
45
+ const packageJson = JSON.parse(packageJsonContent.toString());
46
+ validatePackageConfig(packageJson);
47
+
48
+ const packageName = packageJson.packageName;
49
+ const alias = packageJson.alias;
50
+ const binaries = packageJson.binaries;
51
+ const extension = platform === "win32" ? ".exe" : "";
52
+ const binaryKey = `${packageName}-${platform}-${architecture}`;
53
+ const binaryPath = binaries[binaryKey];
54
+
55
+ if (binaryPath) {
56
+ console.log(`Binary found for your platform ${platform}-${architecture}: ${binaryPath}`);
57
+ } else {
58
+ throw new Error(`No binary found for your platform ${platform}-${architecture}.`);
59
+ }
60
+
61
+ return {
62
+ alias,
63
+ binaryKey,
64
+ binaryPath,
65
+ extension
66
+ };
67
+ } catch (error) {
68
+ throw new Error("Unable to read or parse package.json. Please run this script at the root of the package you want to be installed.");
69
+ }
70
+ }
71
+
72
+
73
+ async function createSymlink(binarySource, binaryDestination) {
74
+ const globalBinPath = getGlobalBinPath();
75
+ const symlinkPath = path.join(globalBinPath, binaryDestination);
76
+
77
+ try {
78
+ try {
79
+ await fs.access(symlinkPath, fs.constants.F_OK);
80
+ // If the symlink exists, remove it.
81
+ await fs.unlink(symlinkPath);
82
+ console.log(`Existing symlink ${symlinkPath} found and removed.`);
83
+ } catch (error) {
84
+ // The symlink does not exist, continue.
85
+ }
86
+
87
+ if (os.platform() === "win32") {
88
+ // Create a junction for the binary for Windows.
89
+ // await fs.symlink(binarySource, symlinkPath, "junction");
90
+ } else {
91
+ // Create a symlink for the binary for macOS and Linux.
92
+ await fs.symlink(binarySource, symlinkPath);
93
+ }
94
+ console.info(`Created symlink ${symlinkPath} pointing to ${binarySource}`);
95
+ } catch (error) {
96
+ console.error("Error while creating symlink:", error);
97
+ throw new Error("Failed to create symlink.");
98
+ }
99
+ }
100
+
101
+ async function installCli() {
102
+ const config = await parsePackageJson();
103
+
104
+ console.log({
105
+ config
106
+ });
107
+
108
+ console.info(`Creating symlink for the relevant binary for your platform ${os.platform()}-${os.arch()}`);
109
+
110
+ const currentDir = __dirname;
111
+ const targetDir = path.join(currentDir, '..');
112
+ const binarySource = path.join(targetDir, config.binaryPath);
113
+ const binaryDestination = config.alias;
114
+
115
+ console.info("Installing cli:", binarySource, binaryDestination);
116
+
117
+ await createSymlink(binarySource, binaryDestination + config.extension);
118
+ }
119
+
120
+ async function uninstallCli() {
121
+ const config = await parsePackageJson();
122
+
123
+ try {
124
+ const globalBinPath = getGlobalBinPath();
125
+ const symlinkPath = path.join(globalBinPath, config.alias + config.extension);
126
+
127
+ console.info("Removing symlink:", symlinkPath);
128
+
129
+ await fs.unlink(symlinkPath);
130
+ } catch (ex) {
131
+ console.error("Error while uninstalling:", ex);
132
+ }
133
+
134
+ console.info("Uninstalled cli successfully");
135
+ }
136
+
137
+ const actions = {
138
+ "install": installCli,
139
+ "uninstall": uninstallCli
140
+ };
141
+
142
+ const [cmd] = process.argv.slice(2);
143
+ if (cmd && actions[cmd]) {
144
+ actions[cmd]().then(
145
+ () => process.exit(0),
146
+ (err) => {
147
+ console.error(err);
148
+ process.exit(1);
149
+ }
150
+ );
151
+ } else {
152
+ console.log("Invalid command. `install` and `uninstall` are the only supported commands");
153
+ process.exit(1);
154
+ }