Merge pull request #1470 from balena-io/1064-release-tags-by-commit

Support managing tags using release commit hashes
This commit is contained in:
Thodoris Greasidis
2019-10-16 14:11:40 +03:00
committed by GitHub
3 changed files with 91 additions and 37 deletions

View File

@ -743,6 +743,7 @@ Example:
$ balena tags --application MyApp $ balena tags --application MyApp
$ balena tags --device 7cf02a6 $ balena tags --device 7cf02a6
$ balena tags --release 1234 $ balena tags --release 1234
$ balena tags --release b376b0e544e9429483b656490e5b9443b4349bd6
### Options ### Options
@ -771,8 +772,10 @@ Examples:
$ balena tag set mySimpleTag --application MyApp $ balena tag set mySimpleTag --application MyApp
$ balena tag set myCompositeTag myTagValue --application MyApp $ balena tag set myCompositeTag myTagValue --application MyApp
$ balena tag set myCompositeTag myTagValue --device 7cf02a6 $ balena tag set myCompositeTag myTagValue --device 7cf02a6
$ balena tag set myCompositeTag "my tag value with whitespaces" --device 7cf02a6
$ balena tag set myCompositeTag myTagValue --release 1234 $ balena tag set myCompositeTag myTagValue --release 1234
$ balena tag set myCompositeTag "my tag value with whitespaces" --release 1234 $ balena tag set myCompositeTag --release 1234
$ balena tag set myCompositeTag --release b376b0e544e9429483b656490e5b9443b4349bd6
### Options ### Options
@ -797,6 +800,7 @@ Examples:
$ balena tag rm myTagKey --application MyApp $ balena tag rm myTagKey --application MyApp
$ balena tag rm myTagKey --device 7cf02a6 $ balena tag rm myTagKey --device 7cf02a6
$ balena tag rm myTagKey --release 1234 $ balena tag rm myTagKey --release 1234
$ balena tag rm myTagKey --release b376b0e544e9429483b656490e5b9443b4349bd6
### Options ### Options

View File

@ -17,7 +17,10 @@ limitations under the License.
import { ApplicationTag, DeviceTag, ReleaseTag } from 'balena-sdk'; import { ApplicationTag, DeviceTag, ReleaseTag } from 'balena-sdk';
import { CommandDefinition } from 'capitano'; import { CommandDefinition } from 'capitano';
import { stripIndent } from 'common-tags'; import { stripIndent } from 'common-tags';
import { normalizeUuidProp } from '../utils/normalization'; import {
disambiguateReleaseParam,
normalizeUuidProp,
} from '../utils/normalization';
import * as commandOptions from './command-options'; import * as commandOptions from './command-options';
export const list: CommandDefinition< export const list: CommandDefinition<
@ -25,7 +28,8 @@ export const list: CommandDefinition<
{ {
application?: string; application?: string;
device?: string; device?: string;
release?: number; release?: number | string;
release_raw?: string;
} }
> = { > = {
signature: 'tags', signature: 'tags',
@ -41,6 +45,7 @@ export const list: CommandDefinition<
$ balena tags --application MyApp $ balena tags --application MyApp
$ balena tags --device 7cf02a6 $ balena tags --device 7cf02a6
$ balena tags --release 1234 $ balena tags --release 1234
$ balena tags --release b376b0e544e9429483b656490e5b9443b4349bd6
`, `,
options: [ options: [
commandOptions.optionalApplication, commandOptions.optionalApplication,
@ -57,13 +62,14 @@ export const list: CommandDefinition<
const { exitWithExpectedError } = await import('../utils/patterns'); const { exitWithExpectedError } = await import('../utils/patterns');
return Bluebird.try<ApplicationTag[] | DeviceTag[] | ReleaseTag[]>(() => { return Bluebird.try<ApplicationTag[] | DeviceTag[] | ReleaseTag[]>(
async () => {
const wrongParametersError = stripIndent` const wrongParametersError = stripIndent`
To list resource tags, you must provide exactly one of: To list resource tags, you must provide exactly one of:
* An application, with --application <appname> * An application, with --application <appname>
* A device, with --device <uuid> * A device, with --device <uuid>
* A release, with --release <id> * A release, with --release <id or commit>
See the help page for examples: See the help page for examples:
@ -86,12 +92,18 @@ export const list: CommandDefinition<
return balena.models.device.tags.getAllByDevice(options.device); return balena.models.device.tags.getAllByDevice(options.device);
} }
if (options.release) { if (options.release) {
return balena.models.release.tags.getAllByRelease(options.release); const releaseParam = await disambiguateReleaseParam(
balena,
options.release,
options.release_raw,
);
return balena.models.release.tags.getAllByRelease(releaseParam);
} }
// return never, so that TS typings are happy // return never, so that TS typings are happy
return exitWithExpectedError(wrongParametersError); return exitWithExpectedError(wrongParametersError);
}) },
)
.tap(function(environmentVariables) { .tap(function(environmentVariables) {
if (_.isEmpty(environmentVariables)) { if (_.isEmpty(environmentVariables)) {
exitWithExpectedError('No tags found'); exitWithExpectedError('No tags found');
@ -117,7 +129,8 @@ export const set: CommandDefinition<
{ {
application?: string; application?: string;
device?: string; device?: string;
release?: number; release?: number | string;
release_raw: string;
} }
> = { > = {
signature: 'tag set <tagKey> [value]', signature: 'tag set <tagKey> [value]',
@ -134,8 +147,10 @@ export const set: CommandDefinition<
$ balena tag set mySimpleTag --application MyApp $ balena tag set mySimpleTag --application MyApp
$ balena tag set myCompositeTag myTagValue --application MyApp $ balena tag set myCompositeTag myTagValue --application MyApp
$ balena tag set myCompositeTag myTagValue --device 7cf02a6 $ balena tag set myCompositeTag myTagValue --device 7cf02a6
$ balena tag set myCompositeTag "my tag value with whitespaces" --device 7cf02a6
$ balena tag set myCompositeTag myTagValue --release 1234 $ balena tag set myCompositeTag myTagValue --release 1234
$ balena tag set myCompositeTag "my tag value with whitespaces" --release 1234 $ balena tag set myCompositeTag --release 1234
$ balena tag set myCompositeTag --release b376b0e544e9429483b656490e5b9443b4349bd6
`, `,
options: [ options: [
commandOptions.optionalApplication, commandOptions.optionalApplication,
@ -151,7 +166,7 @@ export const set: CommandDefinition<
const { exitWithExpectedError } = await import('../utils/patterns'); const { exitWithExpectedError } = await import('../utils/patterns');
return Bluebird.try(() => { return Bluebird.try(async () => {
if (_.isEmpty(params.tagKey)) { if (_.isEmpty(params.tagKey)) {
return exitWithExpectedError('No tag key was provided'); return exitWithExpectedError('No tag key was provided');
} }
@ -165,7 +180,7 @@ export const set: CommandDefinition<
* An application, with --application <appname> * An application, with --application <appname>
* A device, with --device <uuid> * A device, with --device <uuid>
* A release, with --release <id> * A release, with --release <id or commit>
See the help page for examples: See the help page for examples:
@ -192,8 +207,14 @@ export const set: CommandDefinition<
); );
} }
if (options.release) { if (options.release) {
return balena.models.release.tags.set( const releaseParam = await disambiguateReleaseParam(
balena,
options.release, options.release,
options.release_raw,
);
return balena.models.release.tags.set(
releaseParam,
params.tagKey, params.tagKey,
params.value, params.value,
); );
@ -209,7 +230,8 @@ export const remove: CommandDefinition<
{ {
application?: string; application?: string;
device?: string; device?: string;
release?: number; release?: number | string;
release_raw?: string;
} }
> = { > = {
signature: 'tag rm <tagKey>', signature: 'tag rm <tagKey>',
@ -222,6 +244,7 @@ export const remove: CommandDefinition<
$ balena tag rm myTagKey --application MyApp $ balena tag rm myTagKey --application MyApp
$ balena tag rm myTagKey --device 7cf02a6 $ balena tag rm myTagKey --device 7cf02a6
$ balena tag rm myTagKey --release 1234 $ balena tag rm myTagKey --release 1234
$ balena tag rm myTagKey --release b376b0e544e9429483b656490e5b9443b4349bd6
`, `,
options: [ options: [
commandOptions.optionalApplication, commandOptions.optionalApplication,
@ -235,7 +258,7 @@ export const remove: CommandDefinition<
const balena = (await import('balena-sdk')).fromSharedOptions(); const balena = (await import('balena-sdk')).fromSharedOptions();
const { exitWithExpectedError } = await import('../utils/patterns'); const { exitWithExpectedError } = await import('../utils/patterns');
return Bluebird.try(() => { return Bluebird.try(async () => {
if (_.isEmpty(params.tagKey)) { if (_.isEmpty(params.tagKey)) {
return exitWithExpectedError('No tag key was provided'); return exitWithExpectedError('No tag key was provided');
} }
@ -249,7 +272,7 @@ export const remove: CommandDefinition<
* An application, with --application <appname> * An application, with --application <appname>
* A device, with --device <uuid> * A device, with --device <uuid>
* A release, with --release <id> * A release, with --release <id or commit>
See the help page for examples: See the help page for examples:
@ -267,10 +290,13 @@ export const remove: CommandDefinition<
return balena.models.device.tags.remove(options.device, params.tagKey); return balena.models.device.tags.remove(options.device, params.tagKey);
} }
if (options.release) { if (options.release) {
return balena.models.release.tags.remove( const releaseParam = await disambiguateReleaseParam(
balena,
options.release, options.release,
params.tagKey, options.release_raw,
); );
return balena.models.release.tags.remove(releaseParam, params.tagKey);
} }
}).nodeify(done); }).nodeify(done);
}, },

View File

@ -14,6 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import { BalenaSDK } from 'balena-sdk';
import _ = require('lodash'); import _ = require('lodash');
export function normalizeUuidProp( export function normalizeUuidProp(
@ -25,3 +26,26 @@ export function normalizeUuidProp(
params[propName + '_raw'] || _.toString(params[propName]); params[propName + '_raw'] || _.toString(params[propName]);
} }
} }
export async function disambiguateReleaseParam(
balena: BalenaSDK,
param: string | number,
paramRaw: string | undefined,
) {
// the user has passed an argument that was parsed as a string
if (!_.isNumber(param)) {
return param;
}
// check whether the argument was indeed an ID
return balena.models.release
.get(param, { $select: 'id' })
.catch(error => {
// we couldn't find a release by id,
// try whether it was a commit with all numeric digits
return balena.models.release
.get(paramRaw || _.toString(param), { $select: 'id' })
.catchThrow(error);
})
.then(({ id }) => id);
};