Help us understand the problem. What is going on with this article?

rust+npm+wasm-packなrepoをGithub Actionsで自動テスト&デプロイできるようにしてみた

はじめに

Rustでコードを書いて、WASMにしてnpmのパッケージにするとなると、wasm-packを使うのが一般的らしい。

https://github.com/rustwasm/wasm-pack

ところがいろいろなツールを使うために自動テスト&デプロイには一工夫がいる。

最初の試み(結局やめた): Docker + Circle CIでの自動化

最初に自動化を試みたころ、ちょうどDockerの勉強をしていたので、Dockerが使いたかった。あとCircle CIを使い始めた頃だったのでそれを選んだ。

Docker Imageの作成

最初の試み(失敗): Alpine Linuxベースで作る

FROM    alpine:3.10
RUN apk add --no-cache zlib-dev openssl-dev git bash rust cargo nodejs npm && \
        npm update -g npm && \
        cargo install wasm-pack && \
# https://rustwasm.github.io/wasm-pack/book/prerequisites/non-rustup-setups.html
        wget https://static.rust-lang.org/dist/rust-std-1.34.2-wasm32-unknown-unknown.tar.gz && \
        tar -xf rust-std-1.34.2-wasm32-unknown-unknown.tar.gz && \
        mv rust-std-1.34.2-wasm32-unknown-unknown/rust-std-wasm32-unknown-unknown/lib/rustlib/wasm32-unknown-unknown /usr/lib/rustlib/ && \
        rm -r rust-std-1.34.2-wasm32-unknown-unknown && rm rust-std-1.34.2-wasm32-unknown-unknown.tar.gz
#  INFO 2019-09-09T16:55:21Z: wasm_pack::command: Running build command...
#  INFO 2019-09-09T16:55:21Z: wasm_pack::command::build: Checking rustc version...
#  INFO 2019-09-09T16:55:21Z: wasm_pack::command::build: rustc version is 34.
#  INFO 2019-09-09T16:55:21Z: wasm_pack::command::build: Checking crate configuration...
#  INFO 2019-09-09T16:55:21Z: wasm_pack::command::build: Crate is correctly configured.
#  INFO 2019-09-09T16:55:21Z: wasm_pack::command::build: Checking for wasm-target...
# [INFO]: Checking for the Wasm target...
#  INFO 2019-09-09T16:55:21Z: wasm_pack::build::wasm_target: Looking for wasm32-unknown-unknown in "/usr/lib/rustlib"
#  INFO 2019-09-09T16:55:21Z: wasm_pack::build::wasm_target: Found wasm32-unknown-unknown in "/usr/lib/rustlib"
#  INFO 2019-09-09T16:55:21Z: wasm_pack::command::build: Checking for wasm-target was successful.
#  INFO 2019-09-09T16:55:21Z: wasm_pack::command::build: Building wasm...
# [INFO]: Compiling to Wasm...
#  INFO 2019-09-09T16:55:21Z: wasm_pack::child: Running "cargo" "build" "--lib" "--target" "wasm32-unknown-unknown"
# [2019-09-09T16:55:21Z INFO  cargo::util::rustc] failed to read rustc info cache: failed to read `/markdown_img_url_editor/markdown_img_url_editor_rust/target/.rustc_info.json`
# [2019-09-09T16:55:21Z INFO  cargo::util::rustc] rustc info cache miss
# [2019-09-09T16:55:21Z INFO  cargo::util::rustc] rustc info cache miss
# [2019-09-09T16:55:21Z INFO  cargo::util::rustc] rustc info cache miss
# [2019-09-09T16:55:21Z INFO  cargo::util::rustc] rustc info cache miss
# [2019-09-09T16:55:21Z WARN  cargo::util::rustc] failed to update rustc info cache: failed to write `/markdown_img_url_editor/markdown_img_url_editor_rust/target/.rustc_info.json`
# error: failed to run `rustc` to learn about target-specific information

# Caused by:
#   process didn't exit successfully: `rustc - --crate-name ___ --print=file-names --target wasm32-unknown-unknown --crate-type bin --crate-type rlib --crate-type dylib --crate-type cdylib --crate-type staticlib --crate-type proc-macro` (exit code: 1)
# --- stderr
# error: Could not create LLVM TargetMachine for triple: wasm32-unknown-unknown: No available targets are compatible with triple "wasm32-unknown-unknown"
ENV PATH $PATH:/root/.cargo/bin

https://github.com/yumetodo/BuildContainers/blob/8011ab2426779f6e5fcefa08ffdf57482b0ce2ca/rust-1.34.2-wasm-node-10/Dockerfile

上のようなDocker Fileを作ったのだが、コメントで書いたようなエラーが出てうまくいかなかった

次の試み: OfficialのRustイメージベース

FROM rust
RUN curl -sL https://deb.nodesource.com/setup_10.x | bash - && apt-get install -y nodejs && rm -rf /var/lib/apt/lists/* && \
        curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh

https://github.com/yumetodo/BuildContainers/blob/8011ab2426779f6e5fcefa08ffdf57482b0ce2ca/rust-latest-wasm-lts/Dockerfile

これは一応うまく行った。

Cirlce CIの設定

version: 2.1
executors:
    default:
        docker:
            - image: yumetodo/buildcontainers:rust-latest-wasm-lts
        working_directory: ~/repo
commands:
    tool_install:
        steps:
            - run: npm i -g can-npm-publish
    cargo_restore_cache:
        steps:
            - run:
                name: Calculate dependencies
                command: cargo generate-lockfile
                working_directory: markdown_img_url_editor_rust
            - restore_cache:
                keys:
                  - v4-cargo-cache-{{ arch }}-{{ checksum "Cargo.lock" }}
    cargo_save_cache:
        steps:
            - save_cache:
                paths:
                  - /usr/local/cargo/registry
                  - target/debug/.fingerprint
                  - target/debug/build
                  - target/debug/deps
                  - target/release/.fingerprint
                  - target/release/build
                  - target/release/deps
                key: v4-cargo-cache-{{ arch }}-{{ checksum "Cargo.lock" }}
jobs:
    test:
        executor: default
        steps:
            - checkout
            - cargo_restore_cache
            - run: cargo test
            - run: wasm-pack build
            - cargo_save_cache
    publish:
        executor: default
        steps:
            - tool_install
            - checkout
            - run: wasm-pack build --release --target nodejs
            - run: echo //registry.npmjs.org/:_authToken=${NPM_TOKEN} > ~/.npmrc
            - run:
                command: |
                    if can-npm-publish --verbose pkg; then
                        wasm-pack publish
                    else
                        echo "publish skipped"
                    fi
workflows:
    version: 2
    publishflow:
        jobs:
            - test
            - publish:
                context: npm
                requires:
                    - test
                filters:
                    tags:
                        only: /^v.*/

https://github.com/yumetodo/markdown_img_url_editor_rust/blob/bbf656c6ed9874b77a23508dce6432da8a1bc4a7/.circleci/config.yml

さっき作ったDocker Imageを指定してこんな感じに設定したらうまく動いた。

次の試み: Github Actionsをつかう

しかしよく考えてほしい。node.jsは頻繁に新しいバージョンがでるし、rustもそれなりにバージョンアップが来る。wasm-packだって更新が来る。そのたびにImage作って更新していくと考えるとかなりだるい。

そもそもDockerを使うべきじゃなかった気がしてくる。

そこで目をつけたのがGithub Actionsだ。これはUbuntuの上で走る(いや他のも選べるし、更にその上でDocker動かすとかもできるけど)。

ちょっとまえにcpprefjp(C++のリファレンスサイト)にかんたんなチェックをするCIをGithub Actionsで組んだばかりだったので、勝手がわかってるのも大きい。
https://github.com/cpprefjp/site/pull/737

name: Test and Release

on:
  [push]

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2
    - name: Cache cargo registry
      uses: actions/cache@v1
      with:
        path: ~/.cargo/registry
        key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
    - name: Cache cargo index
      uses: actions/cache@v1
      with:
        path: ~/.cargo/git
        key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }}
    - name: Cache cargo build
      uses: actions/cache@v1
      with:
        path: target
        key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('**/Cargo.lock') }}
    - name: Run tests
      run: cargo test --verbose
    - name: Use Node.js ${{ matrix.node-version }}
      uses: actions/setup-node@v1
      with:
        node-version: 12.x
        registry-url: 'https://registry.npmjs.org'
    - name: install wasm-pack
      run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
    - run: wasm-pack build --release --target nodejs
    - name: wasm-pack publish when possible
      run: |
        if npx can-npm-publish --verbose pkg; then
            wasm-pack publish
        else
            echo "publish skipped"
        fi
      env:
        NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

https://github.com/yumetodo/markdown_img_url_editor_rust/blob/aeb43c0d46439c24c665848183cece9599c71695/.github/workflows/release.yml

Cargoのキャッシュ設定は
https://github.com/actions/cache/blob/master/examples.md#rust---cargo
のものを拝借した。

Github ActionsのRustの設定例
https://github.com/actions/starter-workflows/blob/e5a3a0e11268f84ad0ff6569a47e197cc8e1f758/ci/rust.yml
を見てみたところ、どうも何もしなくてもcargoは使えるらしい。どのバージョンとかは面倒くさいので調べてないが、まあ動いているのでいい。

npm publishする時

    - run: npm publish
      env:
        NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

のようにするのだが、wasm-pack publishする先行事例が見つからなくて不安だった。結果動いたのでよい。

あと、PRからのビルドのときはpublish周りはいらないので
https://github.com/yumetodo/markdown_img_url_editor_rust/blob/aeb43c0d46439c24c665848183cece9599c71695/.github/workflows/test.yml#L1
省略版を作った。

ところでsecrets.NPM_TOKENってPRから見えたりはしないですよね?確認してないけど。

成果

https://www.npmjs.com/package/markdown_img_url_editor_rust

に上がっている。

ちなみにこのパッケージは何かというと

というような依存関係になっている。

yumetodo
ありきたりなC++erです。最近C++書いていません(あれっ
http://yumetodo.hateblo.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした