• Cloud Source Repositoriesにおいたリポジトリをgo getする

    ※ この話はgo1.11.4と2019/01/01JST時点のCloud Source Repositoriesを前提としています。

    プライベートなリポジトリをGCPのCloud Source Repositoriesに置いている。

    GCPプロジェクトがmypj-xxxxxでリポジトリ名がcheckならリモートリポジトリのURLは https://source.developers.google.com/p/mypj-xxxxx/r/check という感じ。

    下記で説明されているようにgcloudを使った認証か.gitcookieを用いることでgitコマンドを使ってアクセスできるようになる。
    リポジトリのクローン作成

    で、このリポジトリをGo Modules利用でgo getしようとすると

    # 必要に応じてexport GO111MODULE=on
    $ go get source.developers.google.com/p/mypj-xxxxx/r/check
    go get source.developers.google.com/p/mypj-xxxxx/r/check: unrecognized import path "source.developers.google.com/p/mypj-xxxxx/r/check" (parse https://source.developers.google.com/p/mypj-xxxxx/r/check?go-get=1: no go-import meta tags ())
    

    という感じでエラーになってしまう。

    go getが指定されたURLのVCSを特定するためのmeta情報を得られないのが理由らしい。

    <!-- githubの例 -->
    <meta name="go-import" content="github.com/tckz/redmine-wiki_graphviz_plugin git https://github.com/tckz/redmine-wiki_graphviz_plugin.git">
    

    URLにVCS(git)を示す修飾子を付けることでgo getできるようになる。

    $ go get source.developers.google.com/p/mypj-xxxxx/r/check.git
    

    go getされる側

    // go.mod  
    module source.developers.google.com/p/mypj-xxxxx/r/check.git
    
    // check.go
    package check
    
    import "fmt"
    
    func MyFunc() {
        fmt.Println("MyFunc")
    }
    
    // some/func.go
    package some
    
    import "fmt"
    
    func CoolFunc() {
        fmt.Println("Cool")
    }
    

    go getする側

    // go.mod
    module source.developers.google.com/p/mypj-xxxxx/r/sample.git
      
    require source.developers.google.com/p/mypj-xxxxx/r/check.git v0.1.0
    
    // main.go
    package main
    
    import (
        "source.developers.google.com/p/mypj-xxxxx/r/check.git"
        "source.developers.google.com/p/mypj-xxxxx/r/check.git/some"
    )
    
    func main() {
        check.MyFunc()
        some.CoolFunc()
    }
    

    環境

    • macOS Mojave
    • go 1.11.4
  • redmineのプラグインを4.0に移行する

    2018/12/09にRedmine 4.0.0がリリースされた。
    使用しているRailsのバージョンが4から5になったということもあってプラグイン側でも対応が必要だった。

    https://github.com/tckz/redmine-wiki_graphviz_plugin
    このプラグインにおいては以下の2点だけで案外影響は少なかった。

    • before_filterbefore_actionに変更する。
    • render :text => xxxrender :plain => xxxに変更する。

    4.0雑感

    wiki編集のプレビューUIが変わってGithub issueのフォームのようにタブで切り替える方式になった。 下(プレビュー領域)までスクロールしなくていいのはいいけど
    https://github.com/tckz/redmine_wiki_preview_ext
    このプラグインでやってる「編集を続けながらプレビュー」するUIをどう差し込むか悩ましい。

    環境

  • SonarQubeでgoのテスト結果を集約する

    おおよそ以下のURLで説明されているとおり。
    https://docs.sonarqube.org/display/PLUG/SonarGo

    自分の環境ではsonar-scannerを使わずにgradle + sonarqube pluginを用いている。
    gradle wrapperをリポジトリに含めておけば、java以外の事前準備なしで実行できる(ネットにつながる前提で)。

    先にgo testしてカバレッジ/テスト結果をファイル出力しておき、SonarQubeに吸い上げる。

    build.gradle

    plugins {
        id "org.sonarqube" version "2.6.2"
    }
    
    sonarqube {
        properties {
            property "sonar.projectName", "PROJECT-NAME"
            property "sonar.projectVersion", "1.0.0"
    
            property "sonar.go.coverage.reportPaths", "reports/coverage.out"
            property "sonar.go.tests.reportPaths", "reports/test.json"
    
            property "sonar.sources", "."
            // Exclude code generated by stringer.
            property "sonar.exclusions", "**/*_test.go,**/*_string.go,**/vendor/**"
            property "sonar.tests", "."
            property "sonar.test.inclusions", "**/*_test.go"
            property "sonar.test.exclusions", "**/vendor/**"
        }
    }

    SonarQubeがgradleタスクを実行するlinuxと同じ環境(http://localhost:9000)で動いている前提。 stringer生成コードを無視する想定でsonar.exclusionsに「*_string.go」指定している。

    Makefile(抜粋)

    test:
    	go test -coverprofile=reports/coverage.out -json > reports/test.json
    

    カバレッジ/テスト結果の出力形式は以下のページを参照。
    https://docs.sonarqube.org/display/PLUG/Go+Coverage+Results+Import
    https://docs.sonarqube.org/display/PLUG/Unit+Tests+Results+Import

    テストとsonarqubeタスク実行

    $ make test
    $ ./gradlew sonar

    ルートパッケージにテストコードがあると以下のエラーが出て上手く拾ってくれない。デフォルトGOPATHの場合でも環境変数GOPATH=~/goを明示設定しておくと拾ってくれる。

    Failed to find test file for package github.com/tckz/go-split and test TestDecorateReaderNoCompression

    ディレクトリ階層(抜粋)

      ~/go <-- $GOPATH
          src/
            github.com/
              tckz/
                go-split/
                  Makefile
                  build.gradle
                  gradlew 
                  gradle/
                    wrapper/ <-- Gradle wrapper実体
                      ...省略
                  split_test.go <-- 非mainパッケージ
    

    環境

    • CentOS 7.5 x64
      • go 1.11.1
      • openjdk version 1.8.0_181
        • SonarQube Community Edition 7.3.0.15553
          • SonarGo 1.1.0 (build 1612)
      • GNU Make 3.82
  • gitoliteでhook

    入門Git

    素のgitと自作のhookスクリプトを用いて、リポジトリにpushがあったら 「jenkinsのジョブ起動、redmineのRepository.fetch_changesetsを実行・・・」ということをやっていた。

    特定ブランチへのnon fast-forwardなpush禁止をやりたくて、自作することも考えたのだけどgitoliteがやりたいことを網羅していたので移行した。
    http://gitolite.com/gitolite/index.html

    hook設定

    • gitoliteの管理ユーザ(sshユーザ)の~/.gitolite.rcを変更してhookを使えるようにする

      • LOCAL_CODEの部分にコメントで注意書きがあるのでよく読んだうえで。
      %RC = (
      (略)
          # コメント外す
          LOCAL_CODE                =>  "$rc{GL_ADMIN_BASE}/local",
      (略)
      ENABLE => [
      (略)
          # コメント外す
          'repo-specific-hooks',
      (略)
      ]
      
    • gitoliteの管理リポジトリをcheckoutした構造

      gitolite-admin/
        conf/
          gitolite.conf
        keydir/
          user.pub ...
        local/
          hooks/
            repo-specific/
              myhookname.post-receive*
      
    • gitolite.confに起動するhookと条件を設定 * 使っているhookはpost-receiveフック

      repo path/to/repo
        option hook.post-receive = myhookname.post-receive
        RW      =   @dev
      
    • 管理リポジトリにconfとhookスクリプトををpushすると配置されるはず。

      $HOME/.gitolite/
        local/
          hooks/
            repo-specific/
             myhookname.post-receive*
      

    umask

    読取り専用アクセス用にgit-daemonによるリポジトリ公開も行っている。 git-daemonユーザがgitoliteのユーザとは異なるため、gitoliteユーザのhome下の一部についてgroupに対するrxを付与している。

    gitoliteのデフォルトはumask 0077動作なので、この状態のままリポジトリを書き換えるとgit-daemonから見えないdir/fileが出来てしまう。~/.gitolite.rcのUMASK設定を変更して027にした。

    git-daemon経由でfetchすると一部のコミットやブランチが見えなくなってハマった。

    %RC = (
    (略)
                # groupの読み取り可能に
                UMASK                           =>  0027,
    

    環境

    • CentOS 5.11 x64
      • git 1.7.4.1
      • gitolite v3.6.3-10-g4be7ac5
  • redmineのwikiでTOC(目次)の位置を固定する

    経緯

    redmineのwikiで、ページ内のh1.h2.等見出しをまとめたページ内リンクを作ってくれる{{toc}}マクロがある。
    ※大体、右肩に表示したいことが多く{{>toc}}を用いている

    しかし、長いページをスクロールさせると目次がスクロールアウトして見えなくなり、ページ内リンクをクリックできなくて不便だと思っていた。 例えば何かの手順を流れに沿って並べてあるような場合に説明(セクション)を行ったり来たりしたい。
    見出しでセクション分けしていた内容を独立した別ページにするなどしてみたものの、数が多いと面倒だしリンク集部分を自前でメンテするのも大変。

    ということで、tocマクロによる目次をページがスクロールしても画面内に留めるredmine_wiki_fix_tocプラグイン。 https://github.com/tckz/redmine_wiki_fix_toc

    Feature

    • ページ内に右寄せのTOC{{>toc}}がある場合に、同TOCが元々表示されていた位置よりも下にスクロールしたとき、表示位置を固定(position: fixed)する。
      • 左寄せのTOCを画面内にfixすると文章にかぶってしまうので右寄せ限定
    スクロール前
    ↓↓↓ スクロールさせる ↓↓↓
    スクロール後

    補足

    • すべてのページにプラグイン独自のhtmlを差し込むためにview_layouts_base_body_bottomフックを用いる

      class ViewListener < Redmine::Hook::ViewListener
        def view_layouts_base_body_bottom(context)
          context[:controller].send(:render_to_string,
            :template => 'wiki_fix_toc/body_bottom',
            :layout => false,
            :locals => {:context => context})
        end
      end
      
    • 後はplugins/redmine_wiki_fix_toc/app/views/wiki_fix_toc/body_bottom.html.erbでTOCを見つけてイベントを貼り付けるコードを書く。

    環境

    • CentOS 7.1 x64
      • ruby 2.2.0p0 x64
        • redmine 3.1.1
    • Windows 10 Enterprise x64
      • Firefox Developer Edition 43.0a2 x64