LoginSignup
12
7

More than 3 years have passed since last update.

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

Posted at

はじめに

Rustでコードを書いて、WASMにしてnpmのパッケージにするとなると、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

上のような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

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

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.*/

さっき作った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 }}

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から見えたりはしないですよね?確認してないけど。

成果

に上がっている。

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

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

12
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
7