如果存在自动生成的文件,则自动更新Go语言中的包

如果想要在Golang中自动更新软件包,我认为dependabot和renovate可能是选择之一。

只要存在gRPC等生成的文件,由于各种麻烦,我会将所做的记录下来。

学科

Dependabot是GitHub官方提供的机器人,可以自动进行软件包更新。

通过使用安全更新程序,Dependabot可以通过发出拉取请求来修复存在漏洞的依赖关系。

 

非常感激,但是有一个难题是,当dependabot开始运行并生成pull request时,会自动运行go mod tidy。这会自动在go.mod文件中添加所需的包并删除不必要的包,但在存在自动生成文件时,可能会出现问题。

具体来说,仅自动生成的文件调用的包将从go.mod中删除。因此,自动生成文件的代码将无法运行,Lint等操作将失败。

应对方法

Renovate的计划(并不顺利)

我会觉得只要自动运行go mod tidy就好了。

在Renovate中,可以进行比Dependabot更具自定义性的自动软件包更新。此外,如果未指定,它不会运行go mod tidy,因此在这种情况下也是一个不错的选择。

我决定亲自尝试一下,但在自动测试执行时。

go: updates to go.mod needed; to update it:
	go mod tidy

被责怪了。。

Renovate会在renovate.json文件中进行翻新操作。

    "postUpdateOptions": [
        "gomodTidy"
    ],

通过添加对 `go mod tidy` 的附言可以实现,但是Renovate的 `go mod tidy` 似乎有时会从 `go.sum` 中丢失包的校验和。(并且这个问题似乎没有得到解决的计划)

 

因此,在这种情况下,似乎没有使用Renovate的选项。

成功添加dependabot.go。

当我调查起来时,发现这次的问题本身并没有被报告,但是在dependabot上却存在有一个问题。

 

这种方法是在自动生成文件的目录中准备一个dependabot.go文件,并导入所有用于自动生成文件的包。

生成dependabot.go

由于检查所有生成的文件非常麻烦,所以(不知为何我用Python编写了它),我会把dependabot.go生成代码放在这里。

安装

为了识别import部分,我们将使用AST。有一个名为goast的包可以用于将AST的json转储,所以我们需要安装它。

go install github.com/m-mizutani/goast/cmd/goast@latest

接下来,我们将安装Python3。没有必需的外部软件包。

创建generate_dependabotgo.py

import subprocess
import json
import glob
import os


def get_package_from_dic(dic):
    if 'Kind' in dic.keys() and dic['Kind']=='ImportSpec':
        return dic['Node']['Path']['Value']
    else:
        return None


def get_imported_packages(go_file):
    cmd = f"goast dump '{go_file}'"

    ast_result = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True).stdout

    dics = [json.loads(l) for l in ast_result.replace('\n}\n{\n', '}\t{').replace('\n', '').replace('\t', '\n').splitlines()]
    
    return set([get_package_from_dic(d) for d in dics if get_package_from_dic(d)])   


def gen_dependabotgofile(dir_path):
    all_packages = []

    if dir_path[-1] == '/':
        dir_path = dir_path[:-1]

    basename = os.path.basename(dir_path)
    go_paths = glob.glob(f'{dir_path}/*.go', recursive=True)
    
    if len(go_paths) == 0:
        Exception(f'dir_path: {dir_path} が適切ではありません')

    for go_path in go_paths:
        all_packages.extend(get_imported_packages(go_path))

    import_txt = ''

    import_txt += f'package {basename}\n'
    import_txt += '\n'
    import_txt += 'import (\n'

    for package in sorted(set(all_packages)):
        import_txt += f'\t_ {package}\n'

    import_txt += ')\n'
    print(import_txt)
    
    with open(f'{dir_path}/dependabot.go', mode='w') as f:
        f.write(import_txt)

def goformat(dir_path):
    subprocess.run(f'goimports -w "{dir_path}/dependabot.go"', shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
        

auto_generated_gofile_dirs = [
    # 自動生成ファイルの作られるディレクトリ達
]

for dir_path in auto_generated_gofile_dirs:
    print(dir_path)
    gen_dependabotgofile(dir_path)
    goformat(dir_path)

制作程序

在本地运行

    修改generate_dependabotgo.py中的auto_generated_gofile_dirs参数,生成gRPC等自动生成的文件,然后运行python generate_dependabotgo.py。

我认为生成的dependabot.go文件将是这样的。请确保dependabot.go被git跟踪,并不要忘记在.gitignore中进行相应设置。

package account

import (
	_ "bytes"
	_ "context"
	_ "errors"
	_ "fmt"
	_ "net"
	_ "net/mail"
	_ "net/url"
	_ "reflect"
	_ "regexp"
	_ "sort"
	_ "strings"
	_ "sync"
	_ "time"
	_ "unicode/utf8"

	_ "google.golang.org/grpc"
	_ "google.golang.org/grpc/codes"
	_ "google.golang.org/grpc/status"
	_ "google.golang.org/protobuf/reflect/protoreflect"
	_ "google.golang.org/protobuf/runtime/protoimpl"
	_ "google.golang.org/protobuf/types/known/anypb"
)

只需一个选项,将以下内容以原生中文重新表述:
确认dependabot.go是否正常工作。

    1. 删除所有自动生成的文件

 

    1. 执行go mod tidy

 

    1. 重新生成自动生成的文件

 

    运行测试和lint以确认是否有错误

通过dependabot.go配置,自动包更新问题已得到解决。

广告
将在 10 秒后关闭
bannerAds