Skip to content

Commit

Permalink
Merge pull request #465 from mittwald/feature/cronjob-update
Browse files Browse the repository at this point in the history
Feat: add cronjob update
  • Loading branch information
martin-helmich authored Sep 5, 2024
2 parents e18aaea + 402b77c commit 35e6efa
Show file tree
Hide file tree
Showing 5 changed files with 341 additions and 54 deletions.
135 changes: 124 additions & 11 deletions docs/cronjob.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,29 +12,30 @@ Manage cronjobs of your projects
* [`mw cronjob execution logs CRONJOB-ID EXECUTION-ID`](#mw-cronjob-execution-logs-cronjob-id-execution-id)
* [`mw cronjob get CRONJOB-ID`](#mw-cronjob-get-cronjob-id)
* [`mw cronjob list`](#mw-cronjob-list)
* [`mw cronjob update CRONJOB-ID`](#mw-cronjob-update-cronjob-id)

## `mw cronjob create`

Create a new cron job

```
USAGE
$ mw cronjob create --description <value> --interval <value> [-i <value>] [-q] [--disable] [--email <value>]
[--url <value> | --command <value>] [--interpreter <value>] [--timeout <value>]
$ mw cronjob create --description <value> --interval <value> [-i <value>] [-q] [--email <value>] [--url <value>]
[--command <value> --interpreter bash|php] [--disable] [--timeout <value>]
FLAGS
-i, --installation-id=<value> ID or short ID of an app installation; this flag is optional if a default app
installation is set in the context
-q, --quiet suppress process output and only display a machine-readable summary.
--command=<value> Command to execute for the cron job; either this or `--url` is required.
--description=<value> (required) Description of the cron job
--disable Disable the cron job after creation
--email=<value> Email address to send cron job output to
--interpreter=<value> [default: /bin/sh] Interpreter to use for the cron job
--interval=<value> (required) Interval of the cron job, in standard UNIX cron syntax
--timeout=<value> [default: 3600s] timeout for the cron job; common duration formats are supported (for
example, '1h', '30m', '30s')
--url=<value> URL to call for the cron job; either this or `--command` is required.
--command=<value> Specify the file and arguments to be executed when the cron job is run.
--description=<value> (required) Set cron job description.
--disable Disable the cron job.
--email=<value> Set the target email to which error messages will be sent.
--interpreter=<option> Set the interpreter to be used for execution.
<options: bash|php>
--interval=<value> (required) Set the interval for cron jobs to run.
--timeout=<value> [default: 3600s] Timeout after which the process will be killed.
--url=<value> Set the URL to use when running a cron job.
FLAG DESCRIPTIONS
-i, --installation-id=<value>
Expand All @@ -49,6 +50,43 @@ FLAG DESCRIPTIONS
This flag controls if you want to see the process output or only a summary. When using mw non-interactively (e.g. in
scripts), you can use this flag to easily get the IDs of created resources for further processing.
--command=<value> Specify the file and arguments to be executed when the cron job is run.
Specifies a file to be executed with the specified interpreter. Additional arguments can be appended to the command
to be passed to the script. Not required if a URL is given.
--description=<value> Set cron job description.
This will be displayed as the cron jobs 'name' of the cron job in mStudio.
--disable Disable the cron job.
When creating a cron job it is enabled by default. This flag can be used to set the status of the cron job to
inactive when creating one. Automatic execution will then be disabled until enabled manually.
--email=<value> Set the target email to which error messages will be sent.
If a cron job fails, a detailed error message will be sent to this email address.
--interpreter=bash|php Set the interpreter to be used for execution.
Must be either 'bash' or 'php'. Define the interpreter to be used to execute the previously defined command. The
interpreter should match the corresponding command or script.
--interval=<value> Set the interval for cron jobs to run.
Must be specified as a cron schedule expression. Defines the interval at which the cron job will be executed.
--timeout=<value> Timeout after which the process will be killed.
Common duration formats are supported (for example, '1h', '30m', '30s'). Defines the amount of time after which a
running cron job will be killed. If an email address is defined, an error message will be sent.
--url=<value> Set the URL to use when running a cron job.
Define a URL with protocol to which a request will be dispatched when the cron job is executed. For example:
'https://my-website.com/cron-job'. Not required if a command and interpreter is defined.
```

## `mw cronjob delete CRONJOB-ID`
Expand Down Expand Up @@ -248,3 +286,78 @@ FLAG DESCRIPTIONS
May contain a short ID or a full ID of a project; you can also use the "mw context set --project-id=<VALUE>" command
to persistently set a default project for all commands that accept this flag.
```

## `mw cronjob update CRONJOB-ID`

Update an existing cron job

```
USAGE
$ mw cronjob update CRONJOB-ID [-q] [--description <value>] [--interval <value>] [--email <value>] [--url <value>
| --command <value>] [--interpreter bash|php ] [--enable | --disable] [--timeout <value>]
ARGUMENTS
CRONJOB-ID ID of the cron job to be updated.
FLAGS
-q, --quiet suppress process output and only display a machine-readable summary.
--command=<value> Specify the file and arguments to be executed when the cron job is run.
--description=<value> Set cron job description.
--disable Disable the cron job.
--email=<value> Set the target email to which error messages will be sent.
--enable Enable the cron job.
--interpreter=<option> Set the interpreter to be used for execution.
<options: bash|php>
--interval=<value> Set the interval for cron jobs to run.
--timeout=<value> Timeout after which the process will be killed.
--url=<value> Set the URL to use when running a cron job.
DESCRIPTION
Update an existing cron job
FLAG DESCRIPTIONS
-q, --quiet suppress process output and only display a machine-readable summary.
This flag controls if you want to see the process output or only a summary. When using mw non-interactively (e.g. in
scripts), you can use this flag to easily get the IDs of created resources for further processing.
--command=<value> Specify the file and arguments to be executed when the cron job is run.
Specifies a file to be executed with the specified interpreter. Additional arguments can be appended to the command
to be passed to the script. Not required if a URL is given.
--description=<value> Set cron job description.
This will be displayed as the cron jobs 'name' of the cron job in mStudio.
--disable Disable the cron job.
Set the status of the cron job to active. Automatic execution will be enabled.
--email=<value> Set the target email to which error messages will be sent.
If a cron job fails, a detailed error message will be sent to this email address.
--enable Enable the cron job.
Set the status of the cron job to inactive. Automatic execution will be disabled.
--interpreter=bash|php Set the interpreter to be used for execution.
Must be either 'bash' or 'php'. Define the interpreter to be used to execute the previously defined command. The
interpreter should match the corresponding command or script.
--interval=<value> Set the interval for cron jobs to run.
Must be specified as a cron schedule expression. Defines the interval at which the cron job will be executed.
--timeout=<value> Timeout after which the process will be killed.
Common duration formats are supported (for example, '1h', '30m', '30s'). Defines the amount of time after which a
running cron job will be killed. If an email address is defined, an error message will be sent.
--url=<value> Set the URL to use when running a cron job.
Define a URL with protocol to which a request will be dispatched when the cron job is executed. For example:
'https://my-website.com/cron-job'. Not required if a command and interpreter is defined.
```
68 changes: 25 additions & 43 deletions src/commands/cronjob/create.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ import {
processFlags,
} from "../../rendering/process/process_flags.js";
import { ReactNode } from "react";
import { Flags } from "@oclif/core";
import { assertStatus } from "@mittwald/api-client-commons";
import { Success } from "../../rendering/react/components/Success.js";
import { Value } from "../../rendering/react/components/Value.js";
import { appInstallationFlags } from "../../lib/resources/app/flags.js";
import { cronjobFlagDefinitions } from "../../lib/resources/cronjob/flags.js";
import { buildCronjobDestination } from "../../lib/resources/cronjob/destination.js";
import Duration from "../../lib/units/Duration.js";
import { Flags } from "@oclif/core";

type Result = {
cronjobId: string;
Expand All @@ -20,47 +22,32 @@ export class Create extends ExecRenderBaseCommand<typeof Create, Result> {
static flags = {
...appInstallationFlags,
...processFlags,
description: Flags.string({
required: true,
summary: "Description of the cron job",
default: undefined,
}),
interval: Flags.string({
required: true,
summary: "Interval of the cron job, in standard UNIX cron syntax",
default: undefined,
}),
disable: Flags.boolean({
summary: "Disable the cron job after creation",
default: false,
}),
email: Flags.string({
required: false,
summary: "Email address to send cron job output to",
default: undefined,
description: cronjobFlagDefinitions.description({ required: true }),
interval: cronjobFlagDefinitions.interval({ required: true }),
email: cronjobFlagDefinitions.email(),
url: cronjobFlagDefinitions.url({
exactlyOne: ["url", "command"],
}),
url: Flags.string({
required: false,
summary:
"URL to call for the cron job; either this or `--command` is required.",
default: undefined,
exclusive: ["command"],
command: cronjobFlagDefinitions.command({
exactlyOne: ["url", "command"],
dependsOn: ["interpreter"],
}),
interpreter: Flags.string({
required: false,
summary: "Interpreter to use for the cron job",
default: "/bin/sh",
interpreter: cronjobFlagDefinitions.interpreter({
dependsOn: ["command"],
}),
command: Flags.string({
required: false,
summary:
"Command to execute for the cron job; either this or `--url` is required.",
default: undefined,
exclusive: ["url"],
disable: Flags.boolean({
summary: "Disable the cron job.",
description:
"When creating a cron job it is enabled by default. " +
"This flag can be used to set the status of the cron job to inactive when creating one. " +
"Automatic execution will then be disabled until enabled manually.",
}),
timeout: Duration.relativeFlag({
summary:
"timeout for the cron job; common duration formats are supported (for example, '1h', '30m', '30s')",
summary: "Timeout after which the process will be killed.",
description:
"Common duration formats are supported (for example, '1h', '30m', '30s'). " +
"Defines the amount of time after which a running cron job will be killed. " +
"If an email address is defined, an error message will be sent.",
default: Duration.fromString("1h"),
required: false,
}),
Expand All @@ -69,7 +56,6 @@ export class Create extends ExecRenderBaseCommand<typeof Create, Result> {
protected async exec(): Promise<Result> {
const p = makeProcessRenderer(this.flags, "Creating a new cron job");
const appInstallationId = await this.withAppInstallationId(Create);

const {
description,
interval,
Expand All @@ -81,10 +67,6 @@ export class Create extends ExecRenderBaseCommand<typeof Create, Result> {
timeout,
} = this.flags;

if (!url && !command) {
throw new Error("either `--url` or `--command` must be specified");
}

const { projectId } = await p.runStep("fetching project", async () => {
const r = await this.apiClient.app.getAppinstallation({
appInstallationId,
Expand All @@ -106,7 +88,7 @@ export class Create extends ExecRenderBaseCommand<typeof Create, Result> {
description,
interval,
email,
destination: url ? { url } : { interpreter, path: command },
destination: buildCronjobDestination(url, command, interpreter),
timeout: timeout.seconds,
},
});
Expand Down
117 changes: 117 additions & 0 deletions src/commands/cronjob/update.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import { ExecRenderBaseCommand } from "../../lib/basecommands/ExecRenderBaseCommand.js";
import { Args, Flags } from "@oclif/core";
import { ReactNode } from "react";
import {
makeProcessRenderer,
processFlags,
} from "../../rendering/process/process_flags.js";
import { Success } from "../../rendering/react/components/Success.js";
import assertSuccess from "../../lib/apiutil/assert_success.js";
import { cronjobFlagDefinitions } from "../../lib/resources/cronjob/flags.js";
import { buildCronjobDestination } from "../../lib/resources/cronjob/destination.js";
import Duration from "../../lib/units/Duration.js";

type UpdateResult = void;

export default class Update extends ExecRenderBaseCommand<
typeof Update,
UpdateResult
> {
static description = "Update an existing cron job";
static args = {
"cronjob-id": Args.string({
description: "ID of the cron job to be updated.",
required: true,
}),
};
static flags = {
...processFlags,
description: cronjobFlagDefinitions.description(),
interval: cronjobFlagDefinitions.interval(),
email: cronjobFlagDefinitions.email(),
url: cronjobFlagDefinitions.url({
exclusive: ["command"],
}),
command: cronjobFlagDefinitions.command({
exclusive: ["url"],
dependsOn: ["interpreter"],
}),
interpreter: cronjobFlagDefinitions.interpreter({
dependsOn: ["command"],
}),
enable: Flags.boolean({
exclusive: ["disable"],
summary: "Enable the cron job.",
description:
"Set the status of the cron job to inactive. Automatic execution will be disabled.",
}),
disable: Flags.boolean({
exclusive: ["enable"],
summary: "Disable the cron job.",
description:
"Set the status of the cron job to active. Automatic execution will be enabled.",
}),
timeout: Duration.relativeFlag({
summary: "Timeout after which the process will be killed.",
description:
"Common duration formats are supported (for example, '1h', '30m', '30s'). " +
"Defines the amount of time after which a running cron job will be killed. " +
"If an email address is defined, an error message will be sent.",
required: false,
}),
};

protected async exec(): Promise<void> {
const process = makeProcessRenderer(this.flags, "Updating cron job");
const { "cronjob-id": cronjobId } = this.args;
const currentCronjob = await this.apiClient.cronjob.getCronjob({
cronjobId,
});
assertSuccess(currentCronjob);

const {
description,
interval,
email,
timeout,
url,
interpreter,
command,
enable,
disable,
} = this.flags;

if (Object.keys(this.flags).length == 0) {
await process.complete(
<Success>Nothing to change. Have a good day!</Success>,
);
return;
}

await process.runStep("Updating cron job", async () => {
const response = await this.apiClient.cronjob.updateCronjob({
cronjobId,
data: {
destination:
url || command
? buildCronjobDestination(url, command, interpreter)
: undefined,
active: enable ? true : disable ? false : undefined,
description,
timeout: timeout?.seconds,
email,
interval,
},
});
assertSuccess(response);
});

await process.complete(
<Success>Your cron job has successfully been updated.</Success>,
);
}

protected render(): ReactNode {
return true;
}
}
Loading

0 comments on commit 35e6efa

Please sign in to comment.