📋

asciidocをgithub actionsを用いてgithub pagesにdeployする

2024/07/14に公開

Spring REST Docsを用いて作成されたasciidocをGithub actionsを使いGithub pagesにdeployしたいと思います。

準備物

今回はSpring REST Docs、Asciidoc、Github actionsとGithub Pagesを使用します。

  1. Java 21
  2. Gradle
  3. Spring Boot 3.3.2
  4. Asciidoc
  5. Githubのアカウント
  6. 飲み物 🍺

何故Gradle?

今回 gradle を使う理由としてはビルドの速さです。最低10倍から最高100倍まで早いとの記事もあります。
SpringチームがMavenからGradleに変更した理由でもあります。

Github Pages を設定する

Repository > Settings > Pages > Build and deployment > Source で Github Actions を選択してください。

Gradle に asciidoc の設定を入れます

今回は groovy ではなく kotlin を使います。 理由としてはどんどんKotlin + Springが増えつつありkotlinでの書き方の勉強のため使いました。

build.gradle.kt

plugins {
    java
    id("org.springframework.boot") version "3.3.0"
    id("io.spring.dependency-management") version "1.1.5"
    id("org.asciidoctor.jvm.convert") version "3.3.2" // 追加

}

group = "jp.falsystack"
version = "0.0.1-SNAPSHOT"

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(21)
    }
}

configurations {
    compileOnly {
        extendsFrom(configurations.annotationProcessor.get())
    }
}

repositories {
    mavenCentral()
}

val asciidoctorExt: Configuration by configurations.creating // configuration 追加

dependencies {
    implementation("org.springframework.boot:spring-boot-starter-web")
    implementation("org.springframework.boot:spring-boot-starter-data-jpa")
    implementation("org.springframework.boot:spring-boot-starter-validation")

    // rest docs
    testImplementation("org.springframework.restdocs:spring-restdocs-mockmvc")
    asciidoctorExt("org.springframework.restdocs:spring-restdocs-asciidoctor")

    compileOnly("org.projectlombok:lombok")
    runtimeOnly("com.h2database:h2")
    annotationProcessor("org.projectlombok:lombok")
    testImplementation("org.springframework.boot:spring-boot-starter-test")
    testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}

tasks.withType<Test> {
    useJUnitPlatform()
}

// sinppetsDir 追加
val snippetsDir by extra {
    file("build/generated-snippets")
}

tasks {

    // test Task snippetsDir 追加
    test {
        outputs.dir(snippetsDir)
        useJUnitPlatform()
    }

    // asciidoctor Task 追加
    asciidoctor {
        inputs.dir(snippetsDir)
        configurations("asciidoctorExt")
        dependsOn(test)
    }

    // bootJar Settings
    bootJar {
        dependsOn(asciidoctor)
        from("build/docs/asciidoc") {
            into("static/docs")
        }
    }

    // 生成された asciidoc index.html を src/man/resources/static/docs にコピー
    register<Copy>("copyAsciidoctor") {
        dependsOn(asciidoctor)
        from(file("$layout.buildDirectory/docs/asciidoc"))
        into(file("src/main/resources/static/docs"))
    }

    // ビルドを実行する時 copyAsciidoctor が動いてからビルドするように設定
    build {
        dependsOn("copyAsciidoctor")
    }
}

index.adoc を作っておく

index.adoc

= TOPU Service
:toc: left

== Recruitments

// Create Recruitments
=== Create Recruitments

==== HTTP Request

include::{snippets}/post-recruitments/http-request.adoc[]

...省略

基本的に Spring REST Docs を用いて テストを書いてビルドするとbuild/generated-snippets の中に snippet が生成されます。

これらを src/docs/asciidoc/ の中に index.adoc ファイルを作って snippetsindex.adoc の中に入れ込むと asciidoctor がビルドする時に index.html を生成してくれます。

Github の workflows を書きます

Github actionsを用いてプロジェクトをビルドます。

ビルドする時生成されたAPI明細(asciidoc)をGithub pagesに Deploy します。

0. Trigger

紹介するためのworkflowなので push する時に actions が動くようにします。

on:
  push:
  workflow_dispatch:

1.ビルドする

プロジェクトをビルドしてビルドする時生成された asciidoc(index.html) を次のjobで使うために upload します

build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-java@v4
        with:
          java-version: '21'
          distribution: 'corretto'

      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0

      - name: Build with Gradle
        run: ./gradlew build

      - name: Upload build artifacts
        uses: actions/upload-artifact@v4
        with:
          name: Package
          path: build/docs/asciidoc

2.Github Pages に Deploy します

Upload した index.html を Download します。
Download した index.html をそのまま Github Pages に Deploy します。

何故 index.html ?

Github Pagesはエントリーポイントとしてindex.htmlを探します。

  deploy-docs:
    runs-on: ubuntu-latest
    needs: build
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    steps:
      - name: Download build artifacts
        uses: actions/download-artifact@v4
        with:
          name: Package

      - name: List files in build/libs (for Debugging)
        run: ls -la .

      - name: Configure Pages
        uses: actions/configure-pages@v5

      - name: Upload Pages artifact
        uses: actions/upload-pages-artifact@v3
        with:
          path: .

      - name: Deploy to Pages
        uses: actions/deploy-pages@v4
        id: deployment
workflows全文確認
name: topu

on:
  push:
  workflow_dispatch:

permissions:
  id-token: write
  contents: read
  pages: write

concurrency:
  group: "pages"
  cancel-in-progress: false

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-java@v4
        with:
          java-version: '21'
          distribution: 'corretto'

      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0

      - name: Build with Gradle
        run: ./gradlew build

      - name: Upload build artifacts
        uses: actions/upload-artifact@v4
        with:
          name: Package
          path: build/docs/asciidoc

  deploy-docs:
    runs-on: ubuntu-latest
    needs: build
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    steps:
      - name: Download build artifacts
        uses: actions/download-artifact@v4
        with:
          name: Package

      - name: List files in build/libs (debugging)
        run: ls -la .

      - name: Configure Pages
        uses: actions/configure-pages@v5

      - name: Upload Pages artifact
        uses: actions/upload-pages-artifact@v3
        with:
          path: .

      - name: Deploy to Pages
        uses: actions/deploy-pages@v4
        id: deployment

確認する

Githubに入り Code > Deployments でご確認できます。

結果

  • 自動化されたAPI文書の生成ができるようになりました
  • 文書が実際のテストコードから(テストがPASSされたことが前提)生成されるため、文書とコードとの相違が発生する可能性が低くなります
  • 必要であればasciidocではなくopenapiにもできます
  • ci/cdパイプラインを用いて文書を生成して配布しているため、文書の最新化を測れるし文書化の負荷が減ります

以上です。

Discussion