Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: add cronjob update #465

Merged
merged 30 commits into from
Sep 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
cfd3eea
simplify process
niristius Aug 1, 2024
1324697
Merge branch 'master' into feature/cronjob-update
martin-helmich Aug 22, 2024
1b7c620
chore: re-generate README
martin-helmich Aug 22, 2024
b4002a7
implement "inferred" type for cronjob update
niristius Aug 26, 2024
a463948
reduce duplication by defining cronjob flags centrally. currently bro…
niristius Aug 27, 2024
76b3211
centralize flags through Flag definitions and build payload aggregati…
niristius Aug 27, 2024
a2a5ec9
chore: re-generate README
niristius Aug 27, 2024
f63b8a2
Set useful summaries and descriptions for helptext generation.
niristius Aug 27, 2024
780ba66
Merge remote-tracking branch 'origin/feature/cronjob-update' into fea…
niristius Aug 27, 2024
a80471a
chore: re-generate README
niristius Aug 27, 2024
9488423
Merge remote-tracking branch 'origin/master' into feature/cronjob-update
niristius Aug 27, 2024
51d6b92
Merge remote-tracking branch 'origin/feature/cronjob-update' into fea…
niristius Aug 27, 2024
6001358
Merge branch 'master' into feature/cronjob-update
niristius Aug 28, 2024
2e98a63
split active flag into enable and disable where applicable map interp…
niristius Aug 29, 2024
83930ce
Merge remote-tracking branch 'origin/master' into feature/cronjob-update
martin-helmich Aug 29, 2024
d578838
chore: re-generate README
martin-helmich Aug 29, 2024
5045de2
handle url/command/flag overlap through flags, modularize destination…
niristius Aug 30, 2024
04cdad2
chore: re-generate README
niristius Aug 30, 2024
9887cf1
Merge branch 'master' into feature/cronjob-update
niristius Sep 3, 2024
549f1d9
reimplement Duration for timeout and throw speaking error when limit …
niristius Sep 3, 2024
17039cb
Merge branch 'master' into feature/cronjob-update
niristius Sep 3, 2024
1f304f5
chore: re-generate README
niristius Sep 3, 2024
e8855e3
remove now redundant flag
niristius Sep 3, 2024
0845dc6
Merge remote-tracking branch 'origin/feature/cronjob-update' into fea…
niristius Sep 3, 2024
a56f629
Update src/commands/cronjob/update.tsx
niristius Sep 4, 2024
87520e0
move destination parse error into the buildCronjobDestination functio…
niristius Sep 4, 2024
75f7088
Merge remote-tracking branch 'origin/feature/cronjob-update' into fea…
niristius Sep 4, 2024
32f66fc
Merge branch 'master' into feature/cronjob-update
niristius Sep 4, 2024
010c140
optimize code and remove timeout value check
niristius Sep 4, 2024
402b77c
Merge branch 'master' into feature/cronjob-update
niristius Sep 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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