diff --git a/lib/actions-oclif/apps.ts b/lib/actions-oclif/apps.ts index 00ece3c4..db58f48a 100644 --- a/lib/actions-oclif/apps.ts +++ b/lib/actions-oclif/apps.ts @@ -21,6 +21,7 @@ import { stripIndent } from 'common-tags'; import Command from '../command'; import * as cf from '../utils/common-flags'; import { getBalenaSdk, getVisuals } from '../utils/lazy'; +import { isV12 } from '../utils/version'; interface ExtendedApplication extends Application { device_count?: number; @@ -49,7 +50,9 @@ export default class AppsCmd extends Command { help: cf.help, verbose: flags.boolean({ char: 'v', - description: 'add extra columns in the tabular output (SLUG)', + description: isV12() + ? 'No-op since release v12.0.0' + : 'add extra columns in the tabular output (SLUG)', }), }; @@ -83,7 +86,7 @@ export default class AppsCmd extends Command { getVisuals().table.horizontal(applications, [ 'id', 'app_name', - options.verbose ? 'slug' : '', + options.verbose || isV12() ? 'slug' : '', 'device_type', 'online_devices', 'device_count', diff --git a/lib/actions-oclif/devices/supported.ts b/lib/actions-oclif/devices/supported.ts index 767745a9..b907c3a8 100644 --- a/lib/actions-oclif/devices/supported.ts +++ b/lib/actions-oclif/devices/supported.ts @@ -23,6 +23,7 @@ import Command from '../../command'; import * as cf from '../../utils/common-flags'; import { getBalenaSdk, getVisuals } from '../../utils/lazy'; import { CommandHelp } from '../../utils/oclif-utils'; +import { isV12 } from '../../utils/version'; interface FlagsDef { discontinued: boolean; @@ -77,28 +78,30 @@ export default class DevicesSupportedCmd extends Command { public async run() { const { flags: options } = this.parse(DevicesSupportedCmd); - let deviceTypes: Array> = await getBalenaSdk().models.config.getDeviceTypes(); - if (!options.discontinued) { - deviceTypes = deviceTypes.filter(dt => dt.state !== 'DISCONTINUED'); - } - const fields = ['slug', 'name']; - if (options.verbose) { - fields.splice(1, 0, 'aliases', 'arch', 'state'); - deviceTypes = deviceTypes.map(d => { + let deviceTypes: Array> = await getBalenaSdk() + .models.config.getDeviceTypes() + .map(d => { if (d.aliases && d.aliases.length) { + // remove aliases that are equal to the slug d.aliases = d.aliases.filter((alias: string) => alias !== d.slug); if (!options.json) { // stringify the aliases array with commas and spaces d.aliases = [d.aliases.join(', ')]; } } else { + // ensure it is always an array (for the benefit of JSON output) d.aliases = []; } return d; }); + if (!options.discontinued) { + deviceTypes = deviceTypes.filter(dt => dt.state !== 'DISCONTINUED'); } + const fields = options.verbose + ? ['slug', 'aliases', 'arch', 'state', 'name'] + : isV12() + ? ['slug', 'aliases', 'arch', 'name'] + : ['slug', 'name']; deviceTypes = _.sortBy( deviceTypes.map(d => _.pick(d, fields) as Partial), fields, diff --git a/lib/utils/compose_ts.ts b/lib/utils/compose_ts.ts index 687c29b7..d75fc8ca 100644 --- a/lib/utils/compose_ts.ts +++ b/lib/utils/compose_ts.ts @@ -562,10 +562,15 @@ export async function validateProjectDirectory( checkCompose(path.join(opts.projectPath, '..')), ]); if (!hasCompose && hasParentCompose) { - Logger.getLogger().logWarn(stripIndent` - "docker-compose.y[a]ml" file found in parent directory: please check - that the correct folder was specified. (Suppress with '--noparent-check'.) - `); + const { isV12 } = await import('./version'); + const msg = stripIndent` + "docker-compose.y[a]ml" file found in parent directory: please check that + the correct source folder was specified. (Suppress with '--noparent-check'.)`; + if (isV12()) { + throw new ExpectedError(`Error: ${msg}`); + } else { + Logger.getLogger().logWarn(msg); + } } } } diff --git a/tests/commands/device/supported.spec.ts b/tests/commands/device/supported.spec.ts index b3153849..19d91e66 100644 --- a/tests/commands/device/supported.spec.ts +++ b/tests/commands/device/supported.spec.ts @@ -17,6 +17,7 @@ import { expect } from 'chai'; +import { isV12 } from '../../../build/utils/version'; import { BalenaAPIMock } from '../../balena-api-mock'; import { cleanOutput, runCommand } from '../../helpers'; @@ -52,7 +53,9 @@ describe('balena devices supported', function() { const lines = cleanOutput(out); - expect(lines[0].replace(/ +/g, ' ')).to.equal('SLUG NAME'); + expect(lines[0].replace(/ +/g, ' ')).to.equal( + isV12() ? 'SLUG ALIASES ARCH NAME' : 'SLUG NAME', + ); expect(lines).to.have.lengthOf.at.least(2); // Discontinued devices should be filtered out from results diff --git a/tests/commands/push.spec.ts b/tests/commands/push.spec.ts index a0b8485a..390bca74 100644 --- a/tests/commands/push.spec.ts +++ b/tests/commands/push.spec.ts @@ -22,6 +22,7 @@ import { expect } from 'chai'; import { fs } from 'mz'; import * as path from 'path'; +import { isV12 } from '../../build/utils/version'; import { BalenaAPIMock } from '../balena-api-mock'; import { BuilderMock, builderResponsePath } from '../builder-mock'; import { expectStreamNoCRLF, testPushBuildStream } from '../docker-build'; @@ -230,14 +231,23 @@ describe('balena push', function() { '.balena/balena.yml': { fileSize: 12, type: 'file' }, '.dockerignore': { fileSize: 438, type: 'file' }, '.gitignore': { fileSize: 20, type: 'file' }, - '.git/bar.txt': { fileSize: 4, type: 'file' }, '.git/foo.txt': { fileSize: 4, type: 'file' }, 'c.txt': { fileSize: 1, type: 'file' }, Dockerfile: { fileSize: 13, type: 'file' }, 'src/.balena/balena.yml': { fileSize: 16, type: 'file' }, 'src/.gitignore': { fileSize: 10, type: 'file' }, 'vendor/.git/vendor-git-contents': { fileSize: 20, type: 'file' }, + ...(isV12() + ? { + 'a.txt': { fileSize: 1, type: 'file' }, + 'src/src-a.txt': { fileSize: 5, type: 'file' }, + 'src/src-c.txt': { fileSize: 5, type: 'file' }, + } + : { + '.git/bar.txt': { fileSize: 4, type: 'file' }, + }), }; + const regSecretsPath = await addRegSecretsEntries(expectedFiles); const responseFilename = 'build-POST-v3.json'; const responseBody = await fs.readFile( @@ -245,14 +255,18 @@ describe('balena push', function() { 'utf8', ); const expectedResponseLines = [ - '[Warn] Using file ignore patterns from:', - `[Warn] ${path.join(projectPath, '.dockerignore')}`, - `[Warn] ${path.join(projectPath, '.gitignore')}`, - `[Warn] ${path.join(projectPath, 'src', '.gitignore')}`, - '[Warn] balena CLI currently uses gitgnore and dockerignore files, but an upcoming major', - '[Warn] version release will disregard gitignore files and use a dockerignore file only.', - '[Warn] Use the --nogitignore (-G) option to enable the new behavior already now and', - "[Warn] suppress this warning. For more information, see 'balena help push'.", + ...(!isV12() + ? [ + '[Warn] Using file ignore patterns from:', + `[Warn] ${path.join(projectPath, '.dockerignore')}`, + `[Warn] ${path.join(projectPath, '.gitignore')}`, + `[Warn] ${path.join(projectPath, 'src', '.gitignore')}`, + '[Warn] balena CLI currently uses gitgnore and dockerignore files, but an upcoming major', + '[Warn] version release will disregard gitignore files and use a dockerignore file only.', + '[Warn] Use the --nogitignore (-G) option to enable the new behavior already now and', + "[Warn] suppress this warning. For more information, see 'balena help push'.", + ] + : []), ...commonResponseLines[responseFilename], ]; @@ -486,13 +500,18 @@ describe('balena push: project validation', function() { 'basic', 'service1', ); - const expectedErrorLines = [ - 'The --nolive flag is only valid when pushing to a local mode device', - ]; - const expectedOutputLines = [ - '[Warn] "docker-compose.y[a]ml" file found in parent directory: please check', - "[Warn] that the correct folder was specified. (Suppress with '--noparent-check'.)", - ]; + const expectedErrorLines = isV12() + ? [ + 'Error: "docker-compose.y[a]ml" file found in parent directory: please check that', + "the correct source folder was specified. (Suppress with '--noparent-check'.)", + ] + : ['The --nolive flag is only valid when pushing to a local mode device']; + const expectedOutputLines = isV12() + ? [] + : [ + '[Warn] "docker-compose.y[a]ml" file found in parent directory: please check that', + "[Warn] the correct source folder was specified. (Suppress with '--noparent-check'.)", + ]; const { out, err } = await runCommand( `push testApp --source ${projectPath} --nolive`,