【GitHub Actions】composite 向け Windows runner + bash shell で使えるコマンド

> GitHub の Actions で、よく使うワークフローを `bash` シェルで汎用化させたい。
>
> つまり、<ruby>俺様 Action をバシッとキメたい<rt>Custom Action を Bash で作りたい</rt></ruby>。たとえそれが Windows ランナーであっても。

GitHub の Custom Action には大きく 3 種類あります。`Docker`, `JavaScript` と `composite` です。

しかし、Windows, macOS, Linux の <ruby>`platform`<rt>プラットフォーム</rt></ruby> でも動く Custom Action を作りたい場合、`Docker` タイプは[使えません](https://docs.github.com/en/actions/creating-actions/about-custom-actions#types-of-actions)。`Docker` タイプはプラットフォームが Linux 専用のタイプだからです。

とはいえ、`JavaScript` タイプだと `Node.js` のローカル環境構築や `npm` の管理が面倒です。

残る **[composite](https://docs.github.com/en/actions/creating-actions/creating-a-composite-action) タイプはシェルのスクリプトで記載できるため、汎用のシェル・スクリプトとして完結させられそう**です。

しかし、Linux や macOS ならデフォルトで `bash` シェルで書けるところ、Windows の場合のみ `PowerShell` で書かないといけないのが辛いのです。

## TL; DR <sub><sup><sub><sup>（今北産業）</sup></sub></sup></sub>

1. ランナーが Windows でも、`shell: bash` を指定するとシェルに `bash` が使える。（`git-bash`）
1. これを極めるとワークフローを Win/macOS/Linux 互換の Action として汎用化できる。（`composite` として使える）
    - サンプル：[actions/cache@v2](https://github.com/marketplace/actions/cache) のキャッシュ ID 用に[指定したファイルのハッシュ値を出力するアクション](https://github.com/KEINOS/gh-action-hash-for-cache)
1. `bash` 構文が使えるものの、**全ての `bash` コマンドに互換があるというわけではない**し、POSIX に準拠しているわけでもなさそうである。どんなコマンドが使えるのか。

## TS; DR <sub><sup>（Windows runner の bash シェルで使える共通コマンドが知りたい）</sup></sub>

```yaml
jobs:
  my_test_job:
    strategy:
      matrix:
        platform: [ubuntu-latest, macos-latest, windows-latest]

    runs-on: ${{ matrix.platform }}

    steps:
      - run: |
          if [ "${{ runner.os }}" == "Windows" ]; then
            : # ここに win ならではの処理。とりま使えるコマンドを ls してみる。
            ls /usr/bin
          elif [ "${{ runner.os }}" == "macOS" ]; then
            : # ここに mac ならではの処理。
            echo "This is macOS"
          fi 
          : # ここに win, mac, linux の共通スクリプトを bash で書ける
          echo "This is mac or win or linux"
        shell: bash
```
```bash:/usr/bin以下の一覧onWindows
[.exe
addgnupghome
applygnupgdefaults
arch.exe
astextplain
autopoint
awk.exe
b2sum.exe
backup
base32.exe
base64.exe
basename.exe
basenc.exe
bash.exe
bashbug
bunzip2.exe
bzcat.exe
bzcmp
bzdiff
bzegrep
bzfgrep
bzgrep
bzip2.exe
bzip2recover.exe
bzless
bzmore
c_rehash
captoinfo.exe
cat.exe
chattr.exe
chcon.exe
chgrp.exe
chmod.exe
chown.exe
chroot.exe
cksum.exe
clear.exe
cmp.exe
column.exe
comm.exe
core_perl
cp.exe
csplit.exe
cut.exe
cygcheck.exe
cygpath.exe
cygwin-console-helper.exe
d2u.exe
dash.exe
date.exe
dd.exe
df.exe
diff.exe
diff3.exe
dir.exe
dircolors.exe
dirmngr-client.exe
dirmngr.exe
dirname.exe
docx2txt
docx2txt.pl
dos2unix.exe
du.exe
dumpsexp.exe
echo.exe
egrep
env.exe
envsubst.exe
ex.exe
expand.exe
expr.exe
factor.exe
false.exe
fgrep
fido2-assert.exe
fido2-cred.exe
fido2-token.exe
file.exe
find.exe
findssl.sh
fmt.exe
fold.exe
funzip.exe
gapplication.exe
gawk-5.0.0.exe
gawk.exe
gdbus.exe
gencat.exe
getconf.exe
getemojis
getfacl.exe
getopt.exe
gettext.exe
gettext.sh
gettextize
gio-querymodules.exe
git-flow
git-flow-bugfix
git-flow-config
git-flow-feature
git-flow-hotfix
git-flow-init
git-flow-log
git-flow-release
git-flow-support
git-flow-version
gitflow-common
gitflow-shFlags
gkill.exe
glib-compile-schemas.exe
gobject-query.exe
gpg-agent.exe
gpg-connect-agent.exe
gpg-error.exe
gpg-wks-server.exe
gpg.exe
gpgconf.exe
gpgparsemail.exe
gpgscm.exe
gpgsm.exe
gpgsplit.exe
gpgtar.exe
gpgv.exe
grep.exe
groups.exe
gsettings.exe
gunzip
gzexe
gzip.exe
head.exe
hmac256.exe
hostid.exe
hostname.exe
iconv.exe
id.exe
infocmp.exe
infotocap.exe
install.exe
join.exe
kbxutil.exe
kill.exe
ldd.exe
ldh.exe
less.exe
lessecho.exe
lesskey.exe
link.exe
ln.exe
locale.exe
locate.exe
logname.exe
ls.exe
lsattr.exe
mac2unix.exe
md5sum.exe
minidumper.exe
mintheme
mintty.exe
mkdir.exe
mkfifo.exe
mkgroup.exe
mknod.exe
mkpasswd.exe
mktemp.exe
mount.exe
mpicalc.exe
msgattrib.exe
msgcat.exe
msgcmp.exe
msgcomm.exe
msgconv.exe
msgen.exe
msgexec.exe
msgfilter.exe
msgfmt.exe
msggrep.exe
msginit.exe
msgmerge.exe
msgunfmt.exe
msguniq.exe
msys-2.0.dll
msys-apr-1-0.dll
msys-aprutil-1-0.dll
msys-asn1-8.dll
msys-assuan-0.dll
msys-bz2-1.dll
msys-cbor-0.8.dll
msys-com_err-1.dll
msys-crypt-0.dll
msys-crypto-1.1.dll
msys-edit-0.dll
msys-expat-1.dll
msys-ffi-7.dll
msys-fido2-1.dll
msys-gcc_s-seh-1.dll
msys-gcrypt-20.dll
msys-gettextlib-0-19-8-1.dll
msys-gettextsrc-0-19-8-1.dll
msys-gio-2.0-0.dll
msys-glib-2.0-0.dll
msys-gmodule-2.0-0.dll
msys-gmp-10.dll
msys-gnutls-30.dll
msys-gobject-2.0-0.dll
msys-gpg-error-0.dll
msys-gssapi-3.dll
msys-hcrypto-4.dll
msys-heimbase-1.dll
msys-heimntlm-0.dll
msys-hogweed-6.dll
msys-hx509-5.dll
msys-iconv-2.dll
msys-idn2-0.dll
msys-intl-8.dll
msys-kafs-0.dll
msys-krb5-26.dll
msys-ksba-8.dll
msys-lz4-1.dll
msys-magic-1.dll
msys-mpfr-6.dll
msys-ncursesw6.dll
msys-nettle-8.dll
msys-npth-0.dll
msys-p11-kit-0.dll
msys-pcre-1.dll
msys-perl5_34.dll
msys-psl-5.dll
msys-readline8.dll
msys-roken-18.dll
msys-sasl2-3.dll
msys-serf-1-0.dll
msys-smartcols-1.dll
msys-sqlite3-0.dll
msys-ssl-1.1.dll
msys-svn_client-1-0.dll
msys-svn_delta-1-0.dll
msys-svn_diff-1-0.dll
msys-svn_fs-1-0.dll
msys-svn_fs_fs-1-0.dll
msys-svn_fs_util-1-0.dll
msys-svn_fs_x-1-0.dll
msys-svn_ra-1-0.dll
msys-svn_ra_local-1-0.dll
msys-svn_ra_serf-1-0.dll
msys-svn_ra_svn-1-0.dll
msys-svn_repos-1-0.dll
msys-svn_subr-1-0.dll
msys-svn_swig_perl-1-0.dll
msys-svn_wc-1-0.dll
msys-tasn1-6.dll
msys-ticw6.dll
msys-unistring-2.dll
msys-uuid-1.dll
msys-wind-0.dll
msys-z.dll
mv.exe
nano.exe
nettle-hash.exe
nettle-lfib-stream.exe
nettle-pbkdf2.exe
ngettext.exe
nice.exe
nl.exe
nohup.exe
notepad
nproc.exe
numfmt.exe
od.exe
openssl.exe
p11-kit.exe
passwd.exe
paste.exe
patch.exe
pathchk.exe
perl.exe
perl5.34.0.exe
pinentry-w32.exe
pinentry.exe
pinky.exe
pkcs1-conv.exe
pldd.exe
pluginviewer.exe
pr.exe
printenv.exe
printf.exe
ps.exe
psl-make-dafsa
psl.exe
ptx.exe
pwd.exe
readlink.exe
realpath.exe
rebase.exe
rebaseall
recode-sr-latin.exe
regtool.exe
reset.exe
restore
rm.exe
rmdir.exe
rnano.exe
runcon.exe
rview.exe
rvim.exe
scp.exe
sdiff.exe
sed.exe
seq.exe
setfacl.exe
setmetamode.exe
sexp-conv.exe
sftp.exe
sh.exe
sha1sum.exe
sha224sum.exe
sha256sum.exe
sha384sum.exe
sha512sum.exe
shred.exe
shuf.exe
sleep.exe
sort.exe
split.exe
ssh-add.exe
ssh-agent.exe
ssh-copy-id
ssh-keygen.exe
ssh-keyscan.exe
ssh-pageant.exe
ssh.exe
sshd.exe
ssp.exe
start
stat.exe
stdbuf.exe
strace.exe
stty.exe
sum.exe
sync.exe
tabs.exe
tac.exe
tail.exe
tar.exe
tee.exe
test.exe
tic.exe
tig.exe
timeout.exe
toe.exe
touch.exe
tput.exe
tr.exe
true.exe
truncate.exe
trust.exe
tset.exe
tsort.exe
tty.exe
tzset.exe
u2d.exe
umount.exe
uname.exe
uncompress
unexpand.exe
uniq.exe
unix2dos.exe
unix2mac.exe
unlink.exe
unzip.exe
unzipsfx.exe
update-ca-trust
updatedb
users.exe
vdir.exe
vendor_perl
vi
view.exe
vim.exe
vimdiff.exe
vimtutor
watchgnupg.exe
wc.exe
which.exe
who.exe
whoami.exe
winpty-agent.exe
winpty-debugserver.exe
winpty.dll
winpty.exe
wordpad
xargs.exe
xgettext.exe
xxd.exe
yat2m.exe
yes.exe
zcat
zcmp
zdiff
zegrep
zfgrep
zforce
zgrep
zipgrep
zipinfo.exe
zless
zmore
znew
```

<!--

## TS; DR

**GitHub Actions のワークフローを汎用的に使いたい**場合、そのワークフローを個別の専用リポジトリのルートに `action.yml` として置くと、別のプロジェクトのリポジトリからでも使えるようになります。わざわざ [GitHub Marketplace](https://github.com/marketplace?type=actions) に公開する必要はありません。

```yaml:jobs.<job>.steps.uses
# 従来 Actions（ユーザー actions の管理下で公開 = GitHub Marketplace で公開）
- uses: actions/my-published-oresama-action@v2
# 俺様 Actions（俺様管理下のリポジトリ名にするだけ）
- uses: KEINOS/my-repo-name-of-the-action@main
```

そして、自作 GitHub Actions（Custrom Actions）を作る場合、以下の [3 種類があります](https://docs.github.com/en/actions/creating-actions/about-custom-actions#types-of-actions)。

1. `Docker` ベースの Action
1. `JavaScript` ベースの Action
1. `composite` ベースの Action

いずれのパターンであっても、その Action が呼び出されると、チェックアウトされた環境（現在のリポジトリのルートをカレント・ディレクトリにした状態）で実行されます。

例えば Docker の場合は、コンテナにリポジトリをマウントして、カレントをマウント先に変更した状態で `Entrypoint` を実行します。

`JavaScript` の場合は、Node.js 環境にチェックアウトされ、`main:` で指定されたスクリプトが実行されます。

そして、その実行結果のステータスが `0`（ゼロ）の場合、つまり `exit 0` で終了した場合はアクションは正常と見なされ、次のステップに進みます。

つまり、JavaScript でなく `composite` を使って俺様 Actions を書いて使いたい場合に便利。

```yaml
on:
  push:
    branches: [ main ]

jobs:
  myjob:
    strategy:
      matrix:
        platform: [ubuntu-latest, macos-latest, windows-latest]

    runs-on: ${{ matrix.platform }}

    steps:
      - uses: actions/checkout@v2

      # このアクションは bar 公開変数に hoge を代入します。
      - id: foo
        uses: KEINOS/my-repo-name-of-the-action@main

      - run: |
          echo "${{ steps.foo.outputs.bar }}"
          : # Output: hoge
        shell: bash
```

-->