dackdive's blog

新米webエンジニアによる技術ブログ。JavaScript(React), Salesforce, Python など

Node.js製CLIフレームワークoclifを試す

はじめに

Heroku が oclif という CLI フレームワークオープンソースとして公開したという記事を読みました。

Heroku CLISalesforce DX のベースにもなっているらしい。
どんなもんか触ってみます。

(oclif は (The) Open CLI Framework の略のようです。読み方がわからない。。。)


oclif の特徴

手を動かす前に、どういった特徴があるのか公式ドキュメントに目を通してみます。
Features · oclif: The Open CLI Framework

  • Super Speed
    • コマンド実行時のオーバーヘッド(?)がほとんどなく、また依存パッケージもほとんどない
    • 実行されるコマンドだけ require されるので、たくさんのコマンドからなる巨大 CLI でも単一コマンドの CLI と速度が変わらない
  • CLI Generator
    • コマンド一発で scaffold が生成できる generator がある
  • Testing Helpers
    • テストが書きやすい。 stdout/stderr を簡単にモックできる
    • generator がテストの scaffold も自動生成する
  • Auto-documentation
    • --help オプションで表示するヘルプテキストが自動生成される
    • ↑は CLI が publish されるときに README にも自動的に記載される(※最後で軽く触れる)
  • (未確認)Plugins
  • (未確認)Hooks
    • コマンド実行時などのライフサイクルイベントや独自にカスタムイベントを定義し、そこにフックする処理を書ける
  • TypeScript
    • TypeScript と JavaScript 両方をサポート
    • oclif 自体も TypeScript で書かれている
  • Coming soon: man pages, Autocomplete

テストしやすく、ドキュメントが自動生成されるのはいいですね。


Single-command と Multi-command

oclif で作成できる CLI には大きく分けて 2 種類あります。
Single-command とは lscurl のように、コマンド自体は1つで引数やオプションを取るものです。
Multi-command とは githeroku のように、後にサブコマンドが続くものです。


試してみる

今回は、自分が過去に Node.js で作った parse-salesforce-object という CLI に oclif を導入してみます。
Salesforce 開発で使うメタデータファイル(XML)をパースしてよしなに表示してくれるという、ごくごく一部の方にしか需要がないやつです)
この CLI は先ほどの分類で言うと Single-command です。


generator で CLI のひな形(scaffold)作成

Quickstart を参考に、generator を使って必要なファイルを生成します。

$ npx oclif single [コマンド名]

を実行すると途中で色々聞かれるので適宜入力します。

$ npx oclif single parse-salesforce-object
npx: 293個のパッケージを17.261秒でインストールしました。

     _-----_     ╭──────────────────────────╮
    |       |    │      Time to build a     │
    |--(o)--|    │  single-command CLI with │
   `---------´   │   oclif! Version: 1.7.9
    ( _´U`_ )    ╰──────────────────────────╯
    /___A___\   /
     |  ~  |
   __'.___.'__
 ´   `  |° ´ Y `

? npm package name parse-salesforce-object
? command bin name the CLI will export parse-salesforce-object
? description
? author Shingo Yamazaki @zaki-yama
? version 0.0.5
? license MIT
? node version supported >=8.0.0
? github owner of repository (https://github.com/OWNER/repo) zaki-yama
? github name of repository (https://github.com/owner/REPO) parse-salesforce-object
? optional components to include
❯◉ yarn (npm alternative)
 ◉ mocha (testing framework)
 ◉ typescript (static typing for javascript)
 ◉ tslint (static analysis tool for typescript)
 ◯ semantic-release (automated version management)

最後のオプションで yarn, mocha, TypeScript を使うかどうかは好みです。

インストールが完了すると、 [コマンド名]ディレクトリが作成され、その下に必要なファイルが揃っています。
npm install (or yarn )も実行されているため、必要なパッケージもインストール済みです。

$ tree -I node_modules parse-salesforce-object
parse-salesforce-object
├── README.md
├── appveyor.yml
├── bin
│   ├── run
│   └── run.cmd
├── package.json
├── src
│   └── index.ts
├── test
│   ├── helpers
│   │   └── init.js
│   ├── index.test.ts
│   ├── mocha.opts
│   └── tsconfig.json
├── tsconfig.json
├── tslint.json
└── yarn.lock

bin/run を実行するとコマンドを実行できます。

$ cd parse-salesforce-object
$ ./bin/run
hello world from /Users/yamazaki/workspace/nodejs/parse-salesforce-object/src/index.ts!


コマンドファイルの構成

src/index.ts がコマンド本体です。中身を見てみます。
((1) ~ (3) は便宜的にこちらで番号を振りました)

import {Command, flags} from '@oclif/command'

class ParseSalesforceObject extends Command {
  // (3)
  static description = 'describe the command here'

  // (3)
  static examples = [
    `$ parse-salesforce-object
hello world from ./src/parse-salesforce-object.ts!
`,
  ]

  // (2)
  static flags = {
    // add --version flag to show CLI version
    version: flags.version({char: 'v'}),
    // add --help flag to show CLI version
    help: flags.help({char: 'h'}),

    // flag with a value (-n, --name=VALUE)
    name: flags.string({char: 'n', description: 'name to print'}),
    force: flags.boolean({char: 'f'}),
  }

  // (2)
  static args = [{name: 'file'}]

  // (1)
  async run() {
    const {args, flags} = this.parse(ParseSalesforceObject)

    const name = flags.name || 'world'
    this.log(`hello ${name} from ${__filename}!`)
    if (args.file && flags.force) {
      this.log(`you input --force and --file: ${args.file}`)
    }
  }
}

export = ParseSalesforceObject
  • (1) コマンドの実処理は run() メソッドに記述します
  • (2) 引数やオプション(flags)はこのように static 変数として定義します。この後ここをカスタマイズしてみます
  • (3) description, examples も同様に static 変数として定義すると、ヘルプテキストに反映されます

最後の (3) について、実際にコマンドを --help オプションつきで実行すると

$ ./bin/run --help
describe the command here

USAGE
  $ parse-salesforce-object [FILE]

OPTIONS
  -f, --force
  -h, --help       show CLI help
  -n, --name=name  name to print
  -v, --version    show CLI version

EXAMPLE
  $ parse-salesforce-object
  hello world from ./src/parse-salesforce-object.ts!

のように、description および examples に記述した文字列がヘルプの先頭と EXAMPLE セクションに記載されているのがわかります。


引数を処理する

さて、ここからひな形をベースに元の CLI としての機能を実装していきます。
まずは引数の処理から。
参考:Command Arguments · oclif: The Open CLI Framework

元の CLI では

const argv = require('minimist')(process.argv.slice(2));
const filePath = argv._[0];

...

if (!filePath) {
  console.log(chalk.red('ERROR: You must specify a path to .object file.'));
  process.exit(1);
}

fs.readFile(filePath, (err, data) => {
  ...
});

のように、とあるファイルへのパスを必須の引数として受け取るようになっていました。
またその処理のために minimist というライブラリを使っていました。

oclif だと以下のように書けます。

class ParseSalesforceObject extends Command {

  ...

  static args = [{
    name: 'path',
    description: 'path to .object file',
    required: true,
  }]

  async run() {
    const {args, flags} = this.parse(ParseSalesforceObject)

    fs.readFile(args.path, (err, data) => {
      ...
    })
  }

引数には { name: 'foo' } という形で名前を付けておくことができ、run() メソッド内で(パース後に) args.foo でアクセスできます。

その他のオプションは https://oclif.io/docs/args.html を参照するといいです。
必須かどうかもオプションで指定できるようになったので判定処理が不要になりました。

# 引数なしで実行するとエラーになる
$ ./bin/run
 ›   Error: Missing 1 required arg:
 ›   path  path to .object file
 ›   See more help with --help


フラグ(オプション)を処理する

続いて、いくつかのフラグを受け取れるようにします。
フラグとは -f foo--file=foo のようなものを指します。
参考:Command Flags · oclif: The Open CLI Framework

フラグは version と help 以外は

static flags = {
  force: flags.boolean({char: 'f'}),
  file: flags.string(),
}

のように、

  • 引数を受け取るもの: flags.string()
  • 引数を受け取らず、boolean として使うもの: flags.boolean()

の 2 種類あります。

また両者に共通して、{char: 'f'} のように char オプションを指定すると短縮形も扱えるようになります。

その他のオプションは https://oclif.io/docs/flags.html を参照します。

元の CLI には、-f xxx または --format=xxx オプションで出力フォーマットを指定でき、その選択肢は markdown, csv, soql のいずれかとなっていたので

format: flags.string({
  char: 'f',
  description: 'output format',
  options: ['markdown', 'csv', 'soql'],
  default: 'markdown',
}),

のように optionsdefault を利用しました。便利。

# -f で許可されているフォーマット以外を指定するとエラー
$ ./bin/run objects/Expense__c.object -f foo 
 ›   Error: Expected --format=foo to be one of: markdown, csv, soql
 ›   See more help with --help


ヘルプを出力してみる

引数やオプションを一通り定義した後で、 --help によりヘルプを表示してみます。

$ ./bin/run --help
USAGE
  $ parse-salesforce-object PATH

ARGUMENTS
  PATH  path to .object file

OPTIONS
  -f, --format=markdown|csv|soql  [default: markdown] output format
  -h, --help                      show CLI help
  -n, --namespace=namespace       namespace prefix (for SOQL format)
  -v, --version                   show CLI version

EXAMPLE
  $ parse-salesforce-object src/objects/Expense__c.object
  | label       | fullName      | type     | required |
  | ----------- | ------------- | -------- | -------- |
  | Amount      | Amount__c     | Number   | false    |
  | Client      | Client__c     | Text     | false    |
  | Date        | Date__c       | DateTime | false    |
  | Reimbursed? | Reimbursed__c | Checkbox | null     |

ARGUMENTS および OPTIONS のセクションのところが、定義した引数・フラグの内容から自動生成されました。


GitHub

今回 oclif での置き換えを試した CLIリポジトリはここにあります。

PR は https://github.com/zaki-yama/parse-salesforce-object/pull/6


まとめと TODO

今回は oclif の導入手順と基本構成についてなんとなくわかったという程度ですが、個人的には

  • npx oclif single/multi foo で scaffold から始められるのは楽
  • 引数やオプションからヘルプ自動生成は便利

といった点が、フレームワークというだけあって良いなと思いました。
また将来的に Autocomplete もサポートしてくれるのは期待したい。

テストを書くところや Plugins、Hooks については試せてないので、今後の TODO ということで。


おまけ:Auto-documentation について

Features#Auto-documentation には

This information is also automatically placed in the README whenever the npm package of the CLI is published. See the multi-command CLI example

と記載がありますが、自動生成したヘルプを README に埋め込む方法はドキュメントに記載がありませんでした。
リンクされてるリポジトリを見ると oclif-dev という CLI を使ってる っぽいので、これかな...?


あわせて読みたい

Salesforce のエンジニアブログにも記事があった。

Vim+ALEでファイル保存時にPrettierを実行する

メモ。
Prettier という JavaScript のフォーマッターをファイル保存時に自動的に実行する、というのを Vim でやりたい。
特に自分は ESLint や Flow のチェックに ALE というプラグインを使っているため
(参考:VimでESLintとFlowを使うためにNeomakeからALEに乗り換える - Qiita
Prettier も同じように ALE で設定できないのか調べた。

すると、ちゃんと Prettier の公式ドキュメントに ALE での設定方法が載ってた。

Prettier 単体で使う場合は上記を読むのが一番早いが、自分は ESLint と併用するために prettier-eslint-cli)を使っているのでその前提で手順を記載する。


設定手順

Vim

ALE の設定として以下を追加する。

let g:ale_fixers = {}
let g:ale_fixers['javascript'] = ['prettier-eslint']

" ファイル保存時に実行
let g:ale_fix_on_save = 1

" ローカルの設定ファイルを考慮する
let g:ale_javascript_prettier_use_local_config = 1

プラグイン管理に dein.vim を使っており、toml で管理している場合は以下のようになる

# rc/dein.toml

[[plugins]]
repo = 'w0rp/ale'
hook_add = '''
let g:ale_statusline_format = ['E%d', 'W%d', 'OK']

nmap <silent> <C-w>j <Plug>(ale_next_wrap)
nmap <silent> <C-w>k <Plug>(ale_previous_wrap)

let g:ale_fixers = {}
let g:ale_fixers['javascript'] = ['prettier-eslint']

" ファイル保存時に実行
let g:ale_fix_on_save = 1

" ローカルの設定ファイルを考慮する
let g:ale_javascript_prettier_use_local_config = 1
'''

let g:ale_fixers['javascript'] = ['prettier-eslint'] の部分、prettier 単体では ['prettier'] でいいが ESLint と併用している場合は prettier-eslint-cli を使うため上記の設定になる。


プロジェクト側

prettier-eslint-cli をインストールしておくだけ。

$ yarn add -D prettier-eslint-cli


様子

f:id:dackdive:20180330013445g:plain

あんまり早くない。。。
非同期で行われるためそこまで気にならないかもしれないけど。
VSCode とかでもこんなもんなんだろうか。


GitHub

以上を反映した Redux アプリ用テンプレートリポジトリがこちらです。
Prettier 導入の Issue は https://github.com/zaki-yama/redux-express-template/issues/16


リファレンス

冒頭の Prettier のドキュメントのほか、ALE の README でも fixer については記載があった。
https://github.com/w0rp/ale#2ii-fixing

[Salesforce]ApexでPermissionSetの"PermissionsXXX"項目の一覧を取得

ちょいメモ。

参考:PermissionSet | SOAP API 開発者ガイド | Salesforce Developers

f:id:dackdive:20180324030725p:plain

Permissions... から始まる項目がいくつかあるらしいので、Apex で項目一覧を取得してみる。

調べ方

以下を開発者コンソールの Execute Anonymous で実行。ログをダウンロードして USER_DEBUG だけ抽出。

Map<String, Schema.SObjectField> M = Schema.SObjectType.PermissionSet.fields.getMap();

SObjectType t = Schema.getGlobalDescribe().get('PermissionSet');
Map<String,Schema.SObjectField> fields = t.getDescribe().fields.getMap();

for (Schema.SObjectField field : fields.values()) {
    Schema.DescribeFieldResult dfr = field.getDescribe();
    if (dfr.getName().contains('Permissions')) {
        System.debug(dfr.getName() + ' | ' + dfr.getLabel());
    }
}

結果

API 参照名 ラベル
PermissionsEmailSingle メールの送信
PermissionsEmailMass 一括メール送信
PermissionsEditTask ToDo の編集
PermissionsEditEvent 行動の編集
PermissionsExportReport レポートのエクスポート
PermissionsImportPersonal 個人データのインポート
PermissionsDataExport ウィークリーデータのエクスポート
PermissionsManageUsers ユーザの管理
PermissionsEditPublicFilters 公開リストビューの管理
PermissionsEditPublicTemplates 公開テンプレートの管理
PermissionsModifyAllData すべてのデータの編集
PermissionsManageCases ケースの管理
PermissionsMassInlineEdit リストからの一括編集
PermissionsEditKnowledge 記事の管理
PermissionsManageKnowledge Salesforce ナレッジの管理
PermissionsManageSolutions 公開ソリューションの管理
PermissionsCustomizeApplication アプリケーションのカスタマイズ
PermissionsEditReadonlyFields 参照のみ項目の編集
PermissionsRunReports レポート実行
PermissionsViewSetup 設定・定義を参照する
PermissionsTransferAnyEntity 所有権の移行
PermissionsNewReportBuilder レポートビルダー
PermissionsActivateContract 契約の有効化
PermissionsActivateOrder 注文の有効化
PermissionsImportLeads リードのインポート
PermissionsManageLeads リードの管理
PermissionsTransferAnyLead リード所有者の移行
PermissionsViewAllData すべてのデータの参照
PermissionsEditPublicDocuments 公開ドキュメントの管理
PermissionsViewEncryptedData 暗号化されたデータの参照
PermissionsEditBrandTemplates レターヘッドの管理
PermissionsEditHtmlTemplates HTML テンプレートの編集
PermissionsChatterInternalUser Chatter 内部ユーザ
PermissionsManageTranslation 翻訳の管理
PermissionsDeleteActivatedContract 有効契約の削除
PermissionsChatterInviteExternalUsers Chatter に顧客を招待する
PermissionsSendSitRequests 登録情報照会要求の送信
PermissionsManageRemoteAccess 接続アプリケーションを管理する
PermissionsCanUseNewDashboardBuilder ドラッグアンドドロップ ダッシュボードビルダー
PermissionsManageCategories カテゴリの管理
PermissionsConvertLeads リードの取引の開始
PermissionsPasswordNeverExpires パスワード無期限
PermissionsUseTeamReassignWizards チーム再割り当てウィザードの使用
PermissionsEditActivatedOrders 有効化された注文の編集
PermissionsInstallPackaging AppExchange パッケージのダウンロード
PermissionsPublishPackaging AppExchange パッケージのアップロード
PermissionsChatterOwnGroups 新規 Chatter グループの作成および所有
PermissionsEditOppLineItemUnitPrice 商談商品の販売価格の編集
PermissionsCreatePackaging AppExchange パッケージの作成
PermissionsBulkApiHardDelete Bulk API の物理削除
PermissionsSolutionImport ソリューションのインポート
PermissionsManageCallCenters コールセンターの管理
PermissionsManageSynonyms シノニムの管理
PermissionsViewContent ポータルのコンテンツの参照
PermissionsManageEmailClientConfig メールクライアント設定の管理
PermissionsEnableNotifications アウトバウンドメッセージの送信
PermissionsManageDataIntegrations データインテグレーションの管理
PermissionsDistributeFromPersWksp コンテンツ配信の作成
PermissionsViewDataCategories データカテゴリの表示
PermissionsManageDataCategories データカテゴリの管理
PermissionsAuthorApex Apex 開発
PermissionsManageMobile モバイル設定を管理する
PermissionsApiEnabled API の有効化
PermissionsManageCustomReportTypes カスタムレポートタイプの管理
PermissionsEditCaseComments ケースコメントの編集
PermissionsTransferAnyCase ケース所有者の移行
PermissionsContentAdministrator Salesforce CRM Content の管理
PermissionsCreateWorkspaces ライブラリの作成
PermissionsManageContentPermissions コンテンツ権限の管理
PermissionsManageContentProperties コンテンツプロパティの管理
PermissionsManageContentTypes ファイルのレコードタイプおよびレイアウトの管理
PermissionsManageExchangeConfig Lightning Sync を管理
PermissionsManageAnalyticSnapshots レポート作成スナップショットを管理
PermissionsScheduleReports レポートのスケジュール
PermissionsManageBusinessHourHolidays 営業時間の休日の管理
PermissionsManageDynamicDashboards 動的ダッシュボードの管理
PermissionsCustomSidebarOnAllPages すべてのページにカスタムサイドバーを表示
PermissionsManageInteraction フローの管理
PermissionsViewMyTeamsDashboards 私のチームのダッシュボードの参照
PermissionsModerateChatter Chatter のモデレート
PermissionsResetPasswords ユーザパスワードのリセットおよびユーザのロック解除
PermissionsFlowUFLRequired フローユーザ機能ライセンスが必要
PermissionsCanInsertFeedSystemFields Chatter フィードにシステム項目値を挿入
PermissionsManageKnowledgeImportExport ナレッジ記事のインポート/エクスポートの管理
PermissionsEmailTemplateManagement メールテンプレートの管理
PermissionsEmailAdministration メール管理
PermissionsManageChatterMessages Chatter メッセージとダイレクトメッセージを管理
PermissionsAllowEmailIC メールベースの ID 検証オプション
PermissionsChatterFileLink 公開リンクの作成
PermissionsForceTwoFactor ユーザインターフェースログインの 2 要素認証
PermissionsViewEventLogFiles イベントログファイルを参照
PermissionsManageNetworks コミュニティを作成および設定
PermissionsManageAuthProviders 認証プロバイダの管理
PermissionsRunFlow フローを実行
PermissionsCreateCustomizeDashboards ダッシュボードの作成とカスタマイズ
PermissionsCreateDashboardFolders ダッシュボードフォルダを作成
PermissionsViewPublicDashboards 公開フォルダのダッシュボードを参照
PermissionsManageDashbdsInPubFolders 公開フォルダのダッシュボードを管理
PermissionsCreateCustomizeReports レポートの作成とカスタマイズ
PermissionsCreateReportFolders レポートフォルダを作成
PermissionsViewPublicReports 公開フォルダのレポートを参照
PermissionsManageReportsInPubFolders 公開フォルダのレポートを管理
PermissionsEditMyDashboards 私のダッシュボードを編集
PermissionsEditMyReports 私のレポートを編集
PermissionsViewAllUsers すべてのユーザの参照
PermissionsAllowUniversalSearch Knowledge One
PermissionsConnectOrgToEnvironmentHub 環境ハブに組織を接続
PermissionsWorkCalibrationUser Work.com 調整を有効化
PermissionsCreateCustomizeFilters リストビューを作成およびカスタマイズ
PermissionsWorkDotComUserPerm Work.com を有効化
PermissionsGovernNetworks コミュニティを管理する
PermissionsSalesConsole セールスコンソール
PermissionsTwoFactorApi API ログインの 2 要素認証
PermissionsDeleteTopics トピックを削除
PermissionsEditTopics トピックを編集
PermissionsCreateTopics トピックを作成
PermissionsAssignTopics トピックを割り当てる
PermissionsIdentityEnabled Identity 機能を使用
PermissionsIdentityConnect Identity Connect を使用
PermissionsAllowViewKnowledge ナレッジの参照を許可
PermissionsContentWorkspaces ライブラリへのアクセス
PermissionsManageSearchPromotionRules 昇格済み検索語の管理
PermissionsCustomMobileAppsAccess カスタムモバイルアプリケーションにアクセス
PermissionsViewHelpLink ヘルプリンクを参照
PermissionsManageProfilesPermissionsets プロファイルおよび権限セットを管理
PermissionsAssignPermissionSets 権限セットの割り当て
PermissionsManageRoles ロールを管理
PermissionsManageIpAddresses IP アドレスを管理
PermissionsManageSharing 共有を管理
PermissionsManageInternalUsers 内部ユーザを管理
PermissionsManagePasswordPolicies パスワードポリシーを管理
PermissionsManageLoginAccessPolicies ログインアクセスポリシーを管理
PermissionsManageCustomPermissions カスタム権限を管理
PermissionsCanVerifyComment Chatter の質問への回答の確認
PermissionsManageUnlistedGroups 「リストに記載しない」グループを管理
PermissionsModifySecureAgents セキュアエージェントを変更
PermissionsManageTwoFactor API で 2 要素認証を管理
PermissionsChatterForSharePoint Chatter For SharePoint へのアクセス
PermissionsLightningExperienceUser Lightning Experience ユーザ
PermissionsConfigCustomRecs カスタムおすすめの設定
PermissionsSubmitMacrosAllowed ユーザが元に戻せないマクロを管理
PermissionsBulkMacrosAllowed 複数のレコードに対してマクロを実行
PermissionsShareInternalArticles 内部のナレッジ記事を外部と共有
PermissionsManageSessionPermissionSets セッション権限セットの有効化を管理
PermissionsSendAnnouncementEmails お知らせメールを送信
PermissionsChatterEditOwnPost 自分の投稿を編集
PermissionsChatterEditOwnRecordPost 自分の所有レコードへの投稿を編集
PermissionsImportCustomObjects カスタムオブジェクトのインポート
PermissionsDelegatedTwoFactor ユーザインターフェースで 2 要素認証を管理
PermissionsChatterComposeUiCodesnippet UI からのコードスニペットの挿入を許可
PermissionsSelectFilesFromSalesforce Salesforce からファイルを選択
PermissionsModerateNetworkUsers コミュニティユーザモデレート
PermissionsMergeTopics トピックのマージ
PermissionsSubscribeToLightningReports レポートを登録
PermissionsManagePvtRptsAndDashbds すべての非公開レポートおよびダッシュボードを管理
PermissionsAllowLightningLogin Lightning Login ユーザ
PermissionsCampaignInfluence2 キャンペーンインフルエンス
PermissionsViewDataAssessment データ評価の参照アクセス権
PermissionsRemoveDirectMessageMembers ダイレクトメッセージから人を削除
PermissionsCanApproveFeedPost フィード投稿とコメントを承認可能
PermissionsAddDirectMessageMembers ダイレクトメッセージに人を追加
PermissionsAllowViewEditConvertedLeads 取引開始済みのリードを表示および編集
PermissionsShowCompanyNameAsUserBadge コミュニティロールとして会社名を表示
PermissionsAccessCMC コミュニティ管理にアクセス
PermissionsViewHealthCheck 状態チェックを表示
PermissionsManageHealthCheck 状態チェックを管理
PermissionsPackaging2 第二世代パッケージの作成と更新
PermissionsManageCertificates 証明書を管理
PermissionsCreateReportInLightning レポートビルダー (Lightning Experience)
PermissionsPreventClassicExperience Salesforce Classic に切り替えるオプションを非表示
PermissionsHideReadByList [表示先] リストを非表示
PermissionsListEmailSend リストメールの送信を許可
PermissionsFeedPinning フィードでの投稿の固定
PermissionsChangeDashboardColors ダッシュボードの色を変更
PermissionsIotUser IoT ユーザ
PermissionsUseWebLink カスタマイズしたアクションへのアクセスを許可
PermissionsViewAllActivities すべての活動を表示
PermissionsSubscribeReportToOtherUsers レポートを登録: 受信者を追加
PermissionsLightningConsoleAllowedForUser Lightning コンソールユーザ
PermissionsSubscribeReportsRunAsUser レポートを登録: 実行ユーザを設定
PermissionsSubscribeToLightningDashboards ダッシュボードへの登録
PermissionsApexRestServices Apex REST サービス
PermissionsEnableCommunityAppLauncher コミュニティでアプリケーションランチャーを表示
PermissionsManageSurveys アンケートを管理
PermissionsViewRoles ロールおよびロール階層を表示

いっぱいある。

[Salesforce]代理承認者機能の使い方

まとまってるドキュメントが見つからなかったのでメモ。


代理承認者とは

  • Salesforce の承認プロセス機能において、承認者の代わりに申請を承認/却下できる人を設定できる機能
  • ユーザに対して一人だけ代理承認者を設定しておくことができる
  • また承認プロセスの各承認ステップごとに代理承認者による承認を許可するかどうかが設定できる

承認プロセスそのものについては以下の Trailhead モジュールをやるといい。


設定手順

ユーザ設定より代理承認者を設定する

代理承認者を設定したいユーザのユーザ設定画面を開き、下の方の「承認者の設定」セクションに移動する。
「代理承認者」項目に代理承認者にしたいユーザを検索してセットする。

f:id:dackdive:20180317025929p:plain:w320

また、代理承認者自身のユーザ設定で、「承認申請メールを受信」項目を「自分が承認者である場合のみ」から「承認者または代理承認者である場合」に変更しておくとよい。理由は後述。

f:id:dackdive:20180317025925p:plain:w320


承認プロセス設定より、承認ステップで代理承認を許可する

今度は承認プロセスの設定画面を開き、任意の承認ステップの編集画面を開く。

f:id:dackdive:20180317031300p:plain

ステップ 3/3 で、一番下に「代理承認者もこの申請を承認可能にする」という項目があるのでチェックする。

f:id:dackdive:20180317031303p:plain


結果

自分が代理承認者になっている承認ステップに申請が回ってきたとき、承認者同様にメールが届く。
メールの件名には「(◯◯の代理承認者)」と書かれているよう。

f:id:dackdive:20180317032513p:plain


制限事項

自身が代理承認可能な申請は今のところ「未承認申請一覧」には表示されない。メール以外に確認する手段がないのでつらい。
これについてはずいぶん前から Idea に投稿されてるよう。

また、以下のヘルプ記事ではメール以外のワークアラウンドも紹介されてる(英語)。

Why can't a delegated approver see anything in the Items to approve list?

どうやら「レコードが現在承認プロセスの申請中かどうか」を表すチェックボックス項目をオブジェクトに追加し、それを条件にリストビューを作るという方法らしい。
チェックボックスの ON/OFF は承認プロセスの開始時や最終承認/却下時のアクションとして項目自動更新により自動的に制御できる。

が、これは別に「自身が代理承認になっているものリスト」ではないし、もっと言うと自分が承認者じゃないやつも含まれるのでは。。。

(2018/3/23追記)

と思ったら、標準レポートに「代理承認申請一覧」というのがあった。。。

f:id:dackdive:20180323234404p:plain

これで一覧表示できます。

f:id:dackdive:20180326143254p:plain

※ただし、標準フォルダは LEX では表示されないため、コピーする必要あり
(参考:レポートおよびダッシュボード: Lightning Experience で使用できない機能とその新機能


「代理承認者」に設定する以外に、他人の申請を承認/却下する方法

「代理承認者」はユーザにつき一人しか指定できない。もう少し柔軟に代理承認可能なユーザを増やすにはどうするか。

代理承認ではないが、申請を行うオブジェクトに対して「すべての編集」権限があれば任意の申請を承認/却下することができる。
(「すべてのデータの編集」権限もそう)

参考:承認の管理に関する考慮事項

管理者権限
次の権限のいずれかを持つユーザは承認管理者とみなされます。

  • 指定のオブジェクトに対するオブジェクトレベルでの「すべての編集」権限
  • 「すべてのデータの編集」ユーザ権限

承認管理者には次の権限があります。

  • 承認プロセスの一環としてではなく、未承認申請を承認または却下
  • 承認がロックされたレコードの編集


わかっていないこと

  • 承認者としてキューやグループを指定したときにどういう挙動になるのか

electron-react-boilerplateでCSSフレームワーク(Lightning Design System)をインストールするとエラー

Chatter Desktop という Electron アプリ を作っていて真っ先にハマったところのメモ。

Lightning Design System という CSS フレームワークを入れようとしたところ、以下のエラーとなった。

$ git clone --depth=1 https://github.com/chentsulin/electron-react-boilerplate.git your-project-name
$ cd your-project-name
$ yarn
$ yarn add @salesforce-ux/design-system
...
ERROR in dll renderer
Module not found: Error: Can't resolve '@salesforce-ux/design-system' in '/Users/yamazaki/workspace/electron/electron-react-boilerplate'
 @ dll renderer

ERROR in ./node_modules/bootstrap/dist/js/bootstrap.js
Module not found: Error: Can't resolve 'jquery' in '/Users/yamazaki/workspace/electron/electron-react-boilerplate/node_modules/bootstrap/dist/js'
 @ ./node_modules/bootstrap/dist/js/bootstrap.js 7:81-98
 @ dll renderer

ERROR in ./node_modules/bootstrap/dist/js/bootstrap.js
Module not found: Error: Can't resolve 'popper.js' in '/Users/yamazaki/workspace/electron/electron-react-boilerplate/node_modules/bootstrap/dist/js'
 @ ./node_modules/bootstrap/dist/js/bootstrap.js 7:100-120
 @ dll renderer
npm ERR! code ELIFECYCLE
npm ERR! errno 2
npm ERR! electron-react-boilerplate@0.13.2 build-dll: `cross-env NODE_ENV=development node --trace-warnings -r babel-register ./node_modules/webpack/bin/webpack --config webpack.config.renderer.dev.dll.js --colors`
npm ERR! Exit status 2
npm ERR!
npm ERR! Failed at the electron-react-boilerplate@0.13.2 build-dll script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/yamazaki/.npm/_logs/2018-03-04T21_19_46_858Z-debug.log
error Command failed with exit code 2.
info Visit https://yarnpkg.com/en/docs/cli/add for documentation about this command.

https://github.com/chentsulin/electron-react-boilerplate/blob/master/package.json#L23
どうやら postinstall スクリプトが走っており、この中で build-dll という DLL ファイルの生成処理をやろうとして失敗しているよう。

また build-dllwebpack.config.renderer.dev.dll.js を見て webpack によるビルドを行っているので、設定ファイルの中身を見る。そうすると

https://github.com/chentsulin/electron-react-boilerplate/blob/master/webpack.config.renderer.dev.dll.js#L175-L181

entry: {
  renderer: (
    Object
      .keys(dependencies || {})
      .filter(dependency => dependency !== 'font-awesome')
  )
},

ここで、元から入っていた font-awesome については明示的にビルド対象から外しているようだ。
なので手動で

entry: {
  renderer: (
    Object
      .keys(dependencies || {})
      .filter(dependency => {
        // also ignore installed CSS library
        return dependency !== 'font-awesome' && dependency !== '@salesforce-ux/design-system';
      })
  )
},

というふうにインストールする CSS フレームワークをビルド対象から除外してやると、ビルドに成功するようになった。

が、正しい手順なのかがよくわからず、Issue で質問してみることにした。


おまけ: webpack.config.renderer.dev.dll.js がやっていること

開発時のビルドパフォーマンス向上のために webpack.DLLPlugin というのを使っている。
DLLPlugin についてはきちんと理解したわけではないが、外部ライブラリなど毎回毎回ビルドする必要がないモジュールを DLL バンドルという形で別ファイルに切り出し、require() 時に読み込むらしい。
こちらの記事が非常に参考になった。

LDSとdesign-system-reactをBabel&webpackな環境に導入する

メモ。
ちょっと前から Lightning Design System(LDS)の React 実装が公式から出てます。

Lightning Design System for React

で、ようやく入れてみようとドキュメントを頼りにやってみたところ色々手こずったので、手順をまとめておきます。


はじめに

design-system-react の設定に関するドキュメントは、以下のように点在しています。

  1. Getting Started
  2. リポジトリREADME#Usage
  3. リポジトリdocs/webpack.md (Usage with Webpack)

1 が一番参考にしたドキュメント。webpack.config.js の設定例なども載っています。基本はここを見ながらやりました。
ここに書かれてる内容は private repo で管理してるらしい) 2 は 1 と被る部分もあり、ただ Icon の設定に関してはここにしか記載されてません。
また 1, 2 は design-system-react のインストール手順であり、これだけだと LDS はインストールされず、スタイルがあたりません。
LDS を webpack から使えるようにするための情報が 3 に載っています。

以下では、設定手順を大きく「1. design-system-react の設定」と「2. LDS の設定」に分けて記載します。


サンプルコード

Redux & Express でのアプリのひな形リポジトリに導入したときの PR です。

ディレクトリ構成

クライアント側のファイルは public というディレクトリに配置するような構成になっています。

- public
  - assets
    - lds --- LDS はここに展開
    - bundle.js --- ビルド後のファイル
  - components --- React & Redux の
  - containers
  - ...
  - index.js --- エントリーポイント
  - index.html
- package.json
- webpack.config.base.babel.js
- webpack.config.dev.babel.js
- webpack.config.prod.babel.js


1. design-system-react の設定

まずは design-system-react のインストールから設定までの手順。主に先ほどの 1. Getting Started を参考にします。

インストール

npm でインストールできます。

$ npm install @salesforce-ux/design-system @salesforce/design-system-react


webpack の設定

Getting Started のページに webpack.config.js の設定例があるので、それを参考に設定していきます。

 // webpack.config.babel.js (抜粋)
 export default {
   context: path.resolve(path.join(__dirname, 'public')),
   entry: [
     './index',
   ],
+  resolve: {
+    extensions: ['.js', '.jsx'],
+  },
   output: {
     filename: 'bundle.js',
     path: path.resolve(path.join(__dirname, 'public', 'assets')),
     publicPath: '/assets/',
   },
   module: {
     rules: [
       {
-        test: /\.js$/,
-        exclude: /node_modules/,
+        test: /\.jsx?$/,
+        include: [
+          path.resolve(path.join(__dirname, 'public')),
+          path.resolve(path.join(__dirname, 'node_modules/@salesforce/design-system-react')),
+        ],
         use: 'babel-loader',
       },
       {
         ...

(ファイル全体は こちら を参照)

ポイントとしては

  • design-system-react のファイルは .jsx なので、 .jsx もビルドできるように resolve.extensions および babel-loader を適用する正規表現を修正
  • 元々 node_modules 以下はすべて babe-loader の対象外としていたが、design-system-react は対象に含めるよう修正

です。

また、この記事を書いた時点ではドキュメントの方では

path.join(__dirname, 'node_modules/design-system-react')

というように @salesforce が入ってなかったんですが、入れるのが正しいです。
Issue で報告したのでそのうち直るはず。


Babel の設定

.babelrc を修正します。
これには @salesforce/babel-preset-design-system-react という preset を使えとドキュメントにはありますが、中身

https://github.com/salesforce/design-system-react/blob/master/preset/index.js

を見てみると

  • babel-preset-env
  • babel-preset-react
  • babel-plugin-transform-object-rest-spread
  • babel-plugin-transform-class-properties
  • babel-plugin-transform-export-extensions

を指定しているだけなので、既に設定されている .babelrc の内容に合わせて必要な preset/plugin を個別に追加するという対応でもいいのかもしれません。
(実際自分のリポジトリでも babel-plugin-transform-export-extensions 以外は使っていた)

今回は素直にこの preset を使うようにします。

$ npm install -D @salesforce/babel-preset-design-system-react
// .babelrc
{
  "presets": ["@salesforce/babel-preset-design-system-react"]
}


使う

このような形で import して使います。

// components/App.js
import React, { Component } from 'react';
import Button from '@salesforce/design-system-react/components/button';

export default class App extends Component {
  render() {
    return (
      <Button
        iconName="download"
        iconPosition="left"
        label="Neutral Icon"
      />
    );
  }
}


2. LDS の設定

さて、今度は LDS を読み込むための設定をします。
これは docs/webpack.md がある程度参考になります。


インストール
$ npm install @salesforce-ux/design-system style-loader css-loader file-loader

必要になる loader も一緒にインストールしときます。


webpack の設定
 // webpack.config.babel.js
 ...
 export default {
   ...
   module: {
     rules: [
       ...
+      {
+        test: /\.min\.css$/,
+        use: ['style-loader', 'css-loader'],
+      },
+      {
+        test: /\.(eot|svg|ttf|woff|woff2)$/,
+        loader: 'file-loader',
+        options: {
+          name: '[name].[ext]',
+          outputPath: 'lds/',
+        },
+      },
       ...


postinstall 時の処理

次に、npm install 後に LDS を静的リソース配信用のディレクトリ(ここでは public/assets/lds/)にコピーしておきます。
ドキュメントでは postinstall.js スクリプトを作ってシンボリックリンクを貼る処理をやっているようですが、単にコピーするだけなら package.json 内に記述しても十分だと思います。

 // package.json
 {
   "scripts": {
+    "postinstall": "rm -rf public/assets/lds && cp -r node_modules/@salesforce-ux/design-system/assets public/assets/lds",
   ...
 }


読み込み

アプリのエントリーポイントで

 // public/index.js
 import { render } from 'react-dom';
 import { AppContainer } from 'react-hot-loader';
 
+import '@salesforce-ux/design-system/assets/styles/salesforce-lightning-design-system.min.css';
+
 import configureStore from './store/configureStore';
 import App from './containers/App';
 ...

とすれば OK です。


3. Icon パスの設定

最後にもう一点だけ。Icon を使う場合、アプリのルートで <IconSettings> コンポーネントを使い、パスを正しく設定しておく必要があります。

README#icon-usageSLDS React | Icon Settings あたりに記載があります。

 // public/index.js
 import { AppContainer } from 'react-hot-loader';
 
 import '@salesforce-ux/design-system/assets/styles/salesforce-lightning-design-system.min.css';
+import IconSettings from '@salesforce/design-system-react/components/icon-settings';
 
 import configureStore from './store/configureStore';
 import App from './containers/App';
 
 import './styles/index.scss';
 
 const store = configureStore();
 
 const rootEl = document.getElementById('root');
+const LDS_ROOT = 'assets/lds';
 
 render(
   <AppContainer>
     <Provider store={store}>
-      <App />
+      <IconSettings
+        standardSprite={`${LDS_ROOT}/icons/standard-sprite/svg/symbols.svg`}
+        utilitySprite={`${LDS_ROOT}/icons/utility-sprite/svg/symbols.svg`}
+        actionSprite={`${LDS_ROOT}/icons/action-sprite/svg/symbols.svg`}
+        doctypeSprite={`${LDS_ROOT}/icons/doctype-sprite/svg/symbols.svg`}
+        customSprite={`${LDS_ROOT}/icons/custom-sprite/svg/symbols.svg`}
+      >
+        <App />
+      </IconSettings>
     </Provider>
   </AppContainer>,
   rootEl,
 );

ここに関してはよくわかってないことが 2 点あって、

1) <IconSettings> には iconPath を指定する方法と、xxxSprite というアイコンの種類ごとのパスを指定する方法とあるんですが、webpack を使ってると後者を推奨してるようです。

Individual sprites If you are using webpack it is advised to use the sprite properties {actionSprite, standardSprite...} to specify the individual sprite paths so that webpack can easily re-write the paths.

この PR で追加されたようで、そこでも webpack のためにということが書かれていますが詳しいことはよくわからず。

2) xxxSprite の指定のしかたとして、Example にあるように

import actionSprite from '@salesforce-ux/design-system/assets/icons/action-sprite/svg/symbols.svg';

のようにすればいいのかなと思ったんですが、なぜかうまくいかず。。。
結局 postinstall でコピーした方のパスを指定してうまくいったのでそうしています。


結果

f:id:dackdive:20180206041536p:plain

<Button> だけですが、無事に LDS のスタイルがあたった状態でコンポーネントが描画できていることが確認できました。アイコンも表示されています。


おわりに

書いてみるとなんてことないんですが、 @salesforce がちょいちょい抜けてたりとドキュメントの整備が追いついてないみたいで結構ハマりました。。。
とりあえず使えるところまでできてよかった。


トラブルシューティング

遭遇したエラー達。

ERROR in ./node_modules/@salesforce/design-system-react/components/button/index.jsx
Module parse failed: Unexpected token (228:3)
You may need an appropriate loader to handle this file type.
ERROR in ./public/components/App.js
Module not found: Error: Can't resolve '@salesforce/design-system-react/components/button' in '/Users/yamazaki/workspace/react/redux-express-template/public/components'

→ webpack の設定不備。 .jsx がビルド対象になっていない、 node_modules/@salesforce/design-system-react が include されていない、などなど。

/Users/yamazaki/workspace/react/redux-express-template/node_modules/webpack/lib/webpack.js:19
                throw new WebpackOptionsValidationError(webpackOptionsValidationErrors);
        ^
WebpackOptionsValidationError: Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
 - configuration.resolve.extensions[0] should not be empty.
   -> A non-empty string
    at webpack (/Users/yamazaki/workspace/react/redux-express-template/node_modules/webpack/lib/webpack.js:19:9)
    at Object.<anonymous> (/Users/yamazaki/workspace/react/redux-express-template/app.js:13:20)
    at Module._compile (module.js:643:30)
    at babelWatchLoader (/Users/yamazaki/workspace/react/redux-express-template/node_modules/babel-watch/runner.js:50:13)
    at Object.require.extensions.(anonymous function) [as .js] (/Users/yamazaki/workspace/react/redux-express-template/node_modules/babel-watch/runner.js:61:7)
    at Module.load (module.js:556:32)
    at tryModuleLoad (module.js:499:12)
    at Function.Module._load (module.js:491:3)
    at Function.Module.runMain (module.js:684:10)
    at process.on (/Users/yamazaki/workspace/react/redux-express-template/node_modules/babel-watch/runner.js:108:21)

→ webpack の resolve.exntensions に空文字 ['', '.js', '.jsx'] は webpack 2 系以降 NG になったぽい。使うなら'*'

第26回 Tokyo Atlassian ユーザーグループ に行ってきたメモ #augj

行ってきました。

途中参加かつ懇親会は都合がつかず、セッション2つ聞いて帰ってきました。

Confluenence/Jiraパフォーマンスチューニングポイント by 大中浩行

間に合わず。資料が公開されてたので貼っときます。

パフォーマンスと聞いてオンプレ版のことだろうと決めつけてたらやっぱりオンプレ版でした(弊社は Cloud 版)


Confluenceで組織を活性化させたかった話 by 南原 錦善

SES 主力の会社で Confluence Server を使って組織改善にチャレンジしたお話

  • 株式会社ヒューマンネットワーク
    • エンジニア 75 名、営業、管理部 20 名
    • SES の常駐業務が主力
  • 客先常駐なのでエンジニアはバラバラ
  • 定時後帰社、社内活動 -> 社内への働きに対して大きなパワーが必要。効率化することが重要な課題
  • 課題
    • 社内の活動の情報共有がしづらい (元desknets)
    • スキル情報を見る機会がない
    • 議事録、社内ルール、広報がワード、エクセル、PDF
    • やってる感が出ない(家で勉強してたとしても評価できないし、アピールの場がない)
  • 導入までの3つの壁
    1. 社内の反対
      • 変化に対する抵抗
      • 費用対効果の不明さによる懸念
      • 自腹で導入し、良さをアピール
    2. ユーザ管理
      • AD 連携ができるけどうまくいかない→諦め
    3. 使い方指導
  • 利用状況を Google Analytics で取得
  • DBから更新数、いいね数の取得
  • 運用のポイントというか意識したポイント
    1. 使用方法に制限をかけない
    2. 毎日みんなの投稿に目を通しリアクションする
    3. フォロワー(サクラ)を作る
  • 生きた情報は生きた組織を作る!


印象に残った話
  • 費用対効果を説明するの面倒だから 1000円/月・10人分のライセンスを自腹で購入
  • Paiza の問題のリンク集を作り、新人に問題を解かせた。また回答も Confluence に書かせた
    • Java のコードを見るとコメントしたくてたまらない人達が集まってきた
  • ポジティブな気持ちになれる偉人の名言を毎日投稿する人が出てきた

といったエピソードがありました。

弊社も Confluence に情報をまとめるのはだいぶ浸透してきたけど、開発というか業務にないことでも自由に発信するというのはできてないなー。


Making Software for the Software Makers "AtlassianはJIRAをどう使っているか" by Jason Wong

Jira Software プリシパルプロダクトマネージャーの Jason さんからの話。
Atlassian のチーム例 5 つを紹介。
Jira を徹底的に使いこなすための実践的 Tips というより、それぞれのチームで Jira をどう使っているかを通じて Atlassian のカルチャーみたいなものを感じることができて面白かったです。

  • 世界中どこを探してもまったく同じチームはない。だから Jira Software の使い方もチームによって異なる
  • アトラシアンの 5 つのチームの話
  • 世界12箇所、20+ Jira インスタンス、337 プロジェクト、468 カスタムワークフロー
1. 時間的に厳しいアジャイル
  • Identity CloudX チーム
  • Jira に登録しつつ物理カンバン

  • 見積り前提 -> NO!

    • 見積りより調査 早めにスパイクし始めよう!
    • QA 発表会
      • スプリントが終わったときにどんなソフトになっていてほしいか、スプリントの前に実施
  • 改善をし続ける社内文化を支えるために新しい習慣を作ります
    • アジャイルスラム(大勢の人の前に立って経験したことを話す)
      • 詩人会の由来から
    • ウォールボード
    • 仕事と楽しみのバランス
2. 大量の experiment を行うシステム
  • Atlassian 製品の実験的な取り組みを行うチーム?
  • 会社から大量のIdeaがくる。さばききれない
  • 自動化
    • optimizely, jira software, confluence をつなげるマイクロサービスMars
  • 情報を一つの場所にまとめるサービスやプロセスを作るのはとても大切
    • Jira + Confluence
      • Jira を仕事のステータスより、仕事の文脈や背景や結果を詳しく共有できる
3. 端から端まで、開発の見通し
  • Jira Software チーム(Jason さんが所属してるチーム)
  • デザイン・開発・マーケ・プロダクトなどさまざまなチームごとにプロジェクト
    • 使い方もさまざま
  • PM は様々な仕事をトラッキングするため Confluence のページでテーブル作った -> 情報がすぐ古くなる
  • -> クロスプロジェクトボードを作る!
  • 「ボードを歩く」Boardwalk
4.
  • SRE チーム
  • IMA というマイクロサービス作った
    • HOT チケットができると Hipchat にルームができる
    • Bluejeans も
    • StatusPage: https://ja.atlassian.com/software/statuspage
    • 各サービスへのリンクを Jira の課題に集約(自動的に記載される)
5. 開発情報のボード
  • Fusion Team (Jira Software と開発ツールの連携を作る)
  • ブランチの進行と Jira のステータスを重ね合わせると状況がよくわかる
  • development[pullrequests].all > 0
  • カードの色と組み合わせて視覚的に
印象に残った話

1 つめのチームに関しては、物理カンバンを使っていて、タスクのふせんをなぜか一本の道のようにつなげてボードにしていたチームの話。
道は途中で枝分かれしたり合流したりで、要所要所になぜかポケモンが。
またポケモンボール型のマグネットも用意されていて、タスク消化していってポケモンのところまで到達したらポケモンボール使ってポケモン GET!
→ちょっとした達成感のお祝いでみんなでコーヒー飲んだりする
みたいな話をされてました。

f:id:dackdive:20180306104701p:plain

また 2, 4 のチームにあるように、Atlassian では製品間をマイクロサービスでつなげて自動化を進めてるらしい。
StatusPage なんてサービスもやってたのか。

5 については、 JQL の development[xxx] というプロパティすら知らなかったんですが、やってみるとたしかにできました。
Bitbucket などと連携した状態で

development[pullrequests].open > 0

などとすると、「ひもづく PR でオープン状態のものがあるチケット」のような条件指定ができます。

f:id:dackdive:20180203013956p:plain

お話では、キャプチャのようにかんばんのカードの色の条件にこれを使っていて、Jira のステータスとソースコードの状況に乖離がないかを可視化してるとのことでした。

また、3 のチームの話に出てくる Boardwalk ってのがどういった目的で、どれくらいの頻度でやるのかいまいち理解できてなかったんですが
懇親会の冒頭にお話を伺うことができました。

  • 毎回のスプリント期間中に定期的に実施する。スプリントの真ん中あたりに設定してる
    • 前半はプランニング、後半はふりかえりがあるし
  • バックロググルーミングと似てるんだけど、「バックロググルーミングのような細かい話まではしないかな」とのこと
  • そのストーリーを「なぜやるか」というところを、デザイン・開発・マーケみんな集まったところで共有する
    • やる目的を共有し、全員が共感した状態で作らないとモチベーション上がらない

だいたいこんなような回答だったかと。
ググると Jason さんの記事が出てきますね。

また Jason さんからは他にも

  • かんばんはデジタル(Jira)で管理してるところもアナログ(物理)で管理してるところも、あるいは併用してるところもある。傾向として若者が多いところだと物理かんばんが多い
  • Face to Face のコミュニケーションってやっぱり大事。Jira や Confluence 上でもメンションつけてやり取りはたしかにできるけど。メンションつきで長文で重要な情報が頻繁にやり取りするようだと顔を突き合わせての対話が足りてないという兆しなんじゃないか

といった面白い話が聞けました。

総じて、対話によるコミュニケーションや、計画通りやるだけじゃなく仕事に楽しさを持たせるっていうのを大事にしてるんだなと感じました。