App Center CLI is a command line interface to interact with the App Center services. It's intended for use by mobile developers and people building scripts that need to interact with App Center (for example, local CI configurations).
App Center cli is written using Node.js version 18 and TypeScript. Wrappers over the App Center HTTP API are generated using the AutoRest code generator. And the usual plethora of npm modules.
We use mocha for a test runner / framework. Chai is the assertion library. Sinon is the general mocking library, and nock is used to record and playback mock http traffic.
Install the latest version of Node 18 from here.
Also have a working git installation. The code is available from this repo.
The repo is set up so that once you've got node and the repo, everything you need to do will work. However, it is convenient to install some tools globally in addition.
If you need multiple versions of node on your machine at the same time, consider a node version manager. For Mac or Linux, try nvm. For Windows machines, nodist works well.
Make sure you have selected the correct version of node from nvm
- you
can check this by running nvm ls
from a terminal for example.
The TypeScript compilation can be run via the npm run build
command.
gulp is used as a task runner under the hood, but should not be called directly. Use the npm scripts listed below.
By default, to run the CLI you need to compile the typescript explicitly first. The ts-node
command line tool will let you run
.ts
files directly from the command line. Install it with npm install -g ts-node
.
The latest ts-node
required installation in local dev to work
correctly.
If you want to regenerate the HTTP client code from a non-Windows machine, you'll need mono installed and on your path. see the Mono download page for downloads and installation instructions.
If you are running on a Mac and have to use sudo
to install global npm modules (for example, npm install -g typescript
),
then please check out this tutorial.
After installing node and cloning the repo, do:
npm install
npm run build
To run the test suite, do:
npm test
If you're using node directly, do:
npm run build
node dist/index.js <command...> <args...>
If you've installed ts-node
as mentioned above, you can skip the build step and do:
ts-node src/index.ts <command...> <args...>
In the code you'll find debug logs such as the following:
debug(`Failed to get list of application versions - ${inspect(error)}`);
Those are not visible even with --debug
enabled. To see these logs, pass on the DEBUG
environment variable. Example:
DEBUG="appcenter-cli:*" appcenter
More precise filtering can be enabled, as for example:
DEBUG="appcenter-cli:commands:*" appcenter apps list
There are a bunch of scripts in package.json file. Here's what they are and what they do:
Script command | What it does |
---|---|
npm run build |
Runs the linter, compiles the typescript into javascript, creates dist directory |
npm run test |
Runs the linter, runs the test suite. Can also be run with npm test |
npm run watch-test |
Runs a watcher on the test file that will rerun tests automatically on save |
npm run clean |
Cleans up any compilation output |
npm run autorest |
Regenerate the HTTP client libraries. Downloads required tools as part of this process |
npm run lint |
Runs the linter over the codebase |
npm run compile |
Compiles the typescript into javasctipy, creates dist directory |
There will be more over time.
The gulpfile.js file contains the following targets that can be called manually if you desire
Target | npm script | What it does |
---|---|---|
default |
Runs the build task |
|
build:raw |
build |
Runs the build (build-ts, copy-assets, copy-generated-clients) |
build-sourcemaps |
Creates sourcemap files for the compiled TypeScript to aid in debugging | |
build-ts-sourcemaps |
Runs TypeScript compiler to output sourcemap files | |
build-ts |
Runs TypeScript compiler using settings in tsconfig.json | |
clean |
clean |
Deletes the dist folder |
clean-sourcemaps |
Deletes generated source map files from dist directory | |
copy-assets |
Copies .txt files from src to dist (category descriptions) | |
copy-generated-client |
Copies the generated HTTP client code to dist | |
prepublish |
prepublish |
Runs the clean and build:raw tasks before publishing to npm |
Debugging configurations are stored in launch.json file. Here're what they are and what they do:
Target | What it does |
---|---|
Launch with sourcemaps |
Build sourcemaps, attach a debugger when testing an App Center CLI command |
Launch without building sourcemaps |
Attach a debugger when testing an App Center CLI command |
Use promises for async operations. Use async
/await
in TypeScript for handling typical promises.
If you've got a bunch of related code, export the library as a whole in a single import using an index.ts
file.
For example, the profile
library includes files environment.ts
and profile.ts
, but users of the module
just needs to do import { stuff } from "../util/profile"
Don't overuse objects or inheritance. In many cases global functions or modules can do just as well and be easier to consume.
Created by the npm run build
command, contains the compiled-to-javascript code.
This is where the source code for the CLI lives.
The implementation of each command is in this directory. Each category (distribute, build, app, etc) will be a subdirectory of this directory. Each command lives in an individual source file with the same name as the command.
For example:
Command | Source File |
---|---|
appcenter login |
src/commands/login.ts |
appcenter profile configure |
src/commands/profile/configure.ts |
appcenter apps list |
src/commands/apps/list.ts |
The command line parser and dispatcher uses the directory structure and file names to determine which code to run, so the naming conventions are important.
In addition, place a category.txt
file in your category directory. The contents of
this file will be displayed by the help system when getting help for the category.
If you have shared code across commands in your category, you can add a directory named lib
in your category's directory and
put that code there. The command line dispatcher will explicitly ignore this directory and not try to accidentally run your
utility code from the command line.
This contains framework and utility code used across all the commands. See readme files in each directory for specific details of each one. (Working on these.)
Http client wrappers and utility code for handling HTTP communication with Bifrost.
Autorest-generated client code for talking to Bifrost.
The command line parser and dispatching code, along with base class and decorators for implementing commands.
Central point for all user I/O done by commands. Use interaction.prompt
to get input from a user, and
interaction.out
to output various forms of results.
Commands should use these rather than directly using console.log
because the interaction library handles output formats
(the --format
switch) and the --quiet
switch transparently to the command author.
Code for storing and retrieving information about the current logged in user.
Support files for build and packaging.
Test code lives here. For new tests create a subdirectory structure corresponding to the src
folder. Test code will be
automatically run if you name the file <testname>-test.ts
or <testname>-test.js
. We recommend using TypeScript for
you tests to keep things consistent across the entire codebase.
Tests that call the appcenter-cli from PowerShell to execute against an App Center internal test environment live here. Files called *Tests.ps1 run automatically. The Pester test runner runs the tests.
You can run theses tests against your own account, keeping in mind they will log on to your account and perform destructive operations. Consider using a dedicated testing account. Run the tests by creating a user API token for App Center and using it to call Invoke-FunctionalTests.ps1. To run against the production version of App Center, pass Environment
as prod
.
To get consistent user experience among commands for all beacons, the command line argument names should follow the following conventions.
-
All argument names: lower-case nouns, separated by dash "-".
Examples:
--app-path
--dsym-dir
--debug
-
Arguments that describe application: the first noun is "app".
Examples:
--app
--app-path
-
Arguments that point to directories: the last noun is "dir".
Examples:
--tests-dir
--build-dir
--dsym-dir
-
Arguments that point to a single file: the last noun is "path".
Examples:
--manifest-path
--app-path
We follow the standard GitHub flow. Each person working on the cli should create their own fork of the repo. Work in your own repo (preferably on a feature branch). When ready, send a pull request to the master Microsoft/MobileCenter-cli repo against the master branch. After review, the pull request will be merged.
PR submitters should include a description of the change they would like to include in the changelog. Each time a PR is merged and the next version of the CLI is released, the first paragraph in the PR description will be copied into the changelog.
A good description should include:
- Friendly description of the fixes/changes made
- Details of the change
An example of a good description is: "Distribute your app via the CLI: Users can now create & manage your distribution groups, upload your release and distribute it"
This package is published on npmjs.org, using manual steps (to be automated further). TBD. We'll need builds for a Mac installer, Windows MSI, and at least one format of Linux package.