0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ホットスポットプロファイルの可視化を GitHub Actions で GitHub Pages にデプロイしたメモ

Last updated at Posted at 2024-12-01

概要

前回はホットスポットプロファイルの可視化を行った。
既にGitHubPagesがあるので、GitHubActionsを使ってデプロイする。

デプロイしたページ

ソースコード

ディレクトリ構造

GitHub Pagesの作成にはastroを使っている。
今回は、astroをビルドしたフォルダにGitHub Actionsを使ってhotspot.jsonを追加する仕組みとする。

- docs
  - astro
    - dist ← astroをビルドして生成されるフォルダ。このフォルダをGitHub Pagesとしてデプロイする
      - crimes-scene-hotspots ← publicからコピーされたディレクトリ
        - index.html 
+       - hotspots.json ← github actionsで生成するJSONファイル
    - public
      - crimes-scene-hotspots
        - index.html 

ソースコード

GitHub Actions

hotspotプロファイルの作成を除いた部分は割愛している。

.github/workflows/github-pages.yml
# 省略
env:
  BUILD_PATH: './docs/astro' 
jobs:
  build:
    name: Build
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          # デフォルトでは 1 に設定されており、最新のコミット履歴しか参照できない
          # 0 に変更することで、リポジトリの完全なコミット履歴を参照できるようになる
          fetch-depth: 0    
      # 省略 
      - name: Build with Astro
        run: |
          npm run astro build \
            --site "${{ steps.pages.outputs.origin }}" \
            --base "${{ steps.pages.outputs.base_path }}"
        working-directory: ${{ env.BUILD_PATH }}
      
      - name: Set up JDK 21
        uses: actions/setup-java@v4.5.0
        with:
          distribution: 'temurin'
          java-version: '21'

      - name: Download Code Maat
        run: wget https://github.com/adamtornhill/code-maat/releases/download/v1.0.4/code-maat-1.0.4-standalone.jar
        working-directory: ./docs/code-maat

      - name: create git log 
        run: git log --all --numstat --date=short --pretty=format:'--%h--%ad--%aN' --no-renames --after=2023-01-01 > ./logfile.log
        working-directory: ./docs/code-maat

      - name: Run Code Maat
        run: java -jar code-maat-1.0.4-standalone.jar -l logfile.log -c git2 -c git2 -a revisions > ./revisions.csv
        working-directory: ./docs/code-maat

      - name: Run Cloc
        run: docker run --rm -v .:/tmp aldanial/cloc --unix --by-file --csv --quiet --timeout 10 --vcs=git --exclude-dir=docs,.vscode,.github --not-match-f=\.json --report-file=./docs/code-maat/complexity.csv

      - uses: actions/setup-python@v5
        with:
          python-version: '3.13' 

      - run: python csv_as_enclosure_json.py --structure complexity.csv --weights revisions.csv > ../astro/dist/crime-scene-hotspots/hotspots.json
        working-directory: ./docs/code-maat
    # 省略
      - name: Upload artifact
        uses: actions/upload-pages-artifact@v3
        with:
          path: ${{ env.BUILD_PATH }}/dist
  deploy:
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    needs: build
    runs-on: ubuntu-latest
    name: Deploy
    steps:
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v4

ホットスポットの可視化

crime-scene-hotspots.html を参考に、 d3をv3からv7にマイグレーションしたものを使用する。

docs/astro/crime-scene-hotspots/index.html
<!DOCTYPE html>
<meta charset="utf-8" />
<style>

  .node {
    cursor: pointer;
  }

  .node:hover {
    stroke: #000;
    stroke-width: 1.5px;
  }

  .node--root {
    stroke: #777;
    stroke-width: 2px;
  }

  .node--leaf {
    fill: white;
    stroke: #777;
    stroke-width: 1px;
  }

  .label {
    font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;
    text-anchor: middle;
    fill: white;
    text-shadow: 0 1px 0 #000, 1px 0 0 #000, -1px 0 0 #000, 0 -1px 0 #000;
  }

  .label,
  .node--root,
  .node--leaf {
    pointer-events: none;
  }
</style>
<body>
  <script type="module">
    import * as d3 from "https://cdn.jsdelivr.net/npm/d3@7/+esm";
  
    const margin = 10,
      outerDiameter = 960,
      innerDiameter = outerDiameter - margin - margin;
  
    const x = d3.scaleLinear().range([0, innerDiameter]);
    const y = d3.scaleLinear().range([0, innerDiameter]);
    const color = d3.scaleLinear()
      .domain([-1, 5])
      .range(['hsl(185,60%,99%)', 'hsl(187,40%,70%)'])
      .interpolate(d3.interpolateHcl);
  
    const pack = d3.pack()
      .padding(2)
      .size([innerDiameter, innerDiameter]);
  
    const svg = d3
      .select('body')
      .append('svg')
      .attr('width', outerDiameter)
      .attr('height', outerDiameter)
      .append('g')
      .attr('transform', 'translate(' + margin + ',' + margin + ')');
  
    const d3Json = await d3.json('hotspots.json');
    const root = d3.hierarchy(d3Json).sum(d => d.size);
    const nodes = pack(root).descendants();
    let focus = root;
  
    svg
      .append('g')
      .selectAll('circle')
      .data(nodes)
      .enter()
      .append('circle')
      .attr('class', function (d) {
        return d.parent
          ? d.children
            ? 'node'
            : 'node node--leaf'
          : 'node node--root';
      })
      .attr('transform', function (d) {
        return 'translate(' + d.x + ',' + d.y + ')';
      })
      .attr('r', function (d) {
        return d.r;
      })
      .style('fill', function (d) {
        return d.weight > 0.0
          ? 'darkred'
          : d.children
          ? color(d.depth)
          : 'WhiteSmoke';
      })
      .style('fill-opacity', function (d) {
        return d.weight;
      })
      .on('click', function (event, d) {
        return zoom(event, focus === d ? root : d);
      });
  
    svg
      .append('g')
      .selectAll('text')
      .data(nodes)
      .enter()
      .append('text')
      .attr('class', 'label')
      .attr('transform', function (d) {
        return `translate(${d.x}, ${d.y})`;
      })
      .style('fill-opacity', function (d) {
        return d.parent === root ? 1 : 0;
      })
      .style('display', function (d) {
        return d.parent === root ? null : 'none';
      })
      .text(function (d) {
        return d.data.name;
      });
  
    d3.select(window).on('click', function (event) {
      zoom(event, root);
    });
  
    function zoom(event, d) {
      const focus0 = focus;
      focus = d;
  
      const k = innerDiameter / d.r / 2;
      x.domain([d.x - d.r, d.x + d.r]);
      y.domain([d.y - d.r, d.y + d.r]);
      event.stopPropagation();
  
      const transition = svg
        .selectAll("text,circle")
        .transition()
        .duration(event.altKey ? 7500 : 750)
        .attr("transform", function (d) {
          return `translate(${x(d.x)}, ${y(d.y)})`;
        });
  
      transition.filter("circle").attr("r", function (d) {
        return k * d.r;
      });
  
      transition
        .filter("text")
        .filter(function (d) {
          return d.parent === focus || d.parent === focus0;
        })
        .style("fill-opacity", function (d) {
          return d.parent === focus ? 1 : 0;
        })
        .on("start", function (d) {
          if (d.parent === focus) this.style.display = "inline";
        })
        .on("end", function (d) {
          if (d.parent !== focus) this.style.display = "none";
        });
    }
  
    d3.select(self.frameElement).style("height", outerDiameter + "px");
  </script>
</body>

参考

GitHubPagesに開発ドキュメントをデプロイする総集編
ホットスポットプロファイルの可視化を試してみたメモ
GitHub Actionsでコミット履歴を参照する

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?