Skip to content

Commit

Permalink
feat: implement basic function
Browse files Browse the repository at this point in the history
  • Loading branch information
suzuki-shunsuke committed Jan 22, 2023
1 parent 3e8794b commit 6745cfb
Show file tree
Hide file tree
Showing 23 changed files with 608 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/displaying-a-sponsor-button-in-your-repository
github:
- suzuki-shunsuke
20 changes: 20 additions & 0 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
name: Release
on:
push:
tags: [v*]
permissions: {}
env:
AQUA_POLICY_CONFIG: ${{ github.workspace }}/aqua-policy.yaml
jobs:
release:
uses: suzuki-shunsuke/go-release-workflow/.github/workflows/release.yaml@8e0d6d2a7171206b9d95b3b59fe74f8333b1be1b # v0.1.0
with:
homebrew: true
secrets:
gh_app_id: ${{ secrets.APP_ID }}
gh_app_private_key: ${{ secrets.APP_PRIVATE_KEY }}
permissions:
contents: write
id-token: write
actions: read
22 changes: 22 additions & 0 deletions .github/workflows/renovate-config-validator.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: renovate-config-validator

permissions: {}

on:
pull_request:
branches:
- main
paths:
- .github/workflows/renovate-config-validator.yaml
- renovate.json5
push:
branches:
- main
paths:
- .github/workflows/renovate-config-validator.yaml
- renovate.json5

jobs:
renovate-config-validator:
uses: suzuki-shunsuke/renovate-config-validator-workflow/.github/workflows/validate.yaml@37f3b320ff7dd6fbf4fa25ce9e704ed817437a4c # v0.1.0
permissions: {}
16 changes: 16 additions & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
name: test
env:
AQUA_POLICY_CONFIG: ${{ github.workspace }}/aqua-policy.yaml
on:
push:
branches: [main]
pull_request:
branches: [main]
permissions: {}
jobs:
test:
uses: suzuki-shunsuke/go-test-workflow/.github/workflows/test.yaml@ce331bee1ba303d4aef68ff262d3c6ad389b3fa1 # v0.2.0
permissions:
pull-requests: write
contents: read
28 changes: 28 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
linters:
enable-all: true
disable:
- golint # WARN [runner] The linter 'golint' is deprecated (since v1.41.0) due to: The repository of the linter has been archived by the owner. Replaced by revive.
- maligned # WARN [runner] The linter 'maligned' is deprecated (since v1.38.0) due to: The repository of the linter has been archived by the owner. Replaced by govet 'fieldalignment'.
- interfacer # WARN [runner] The linter 'interfacer' is deprecated (since v1.38.0) due to: The repository of the linter has been archived by the owner.
- scopelint # WARN [runner] The linter 'scopelint' is deprecated (since v1.39.0) due to: The repository of the linter has been deprecated by the owner. Replaced by exportloopref.
- tagliatelle
- wsl
- goerr113
- nlreturn
- lll
- godot
- exhaustivestruct
- varnamelen
- ireturn
# TODO
- dupl
- wrapcheck
- testpackage
- godox
- nestif
- funlen
- gocognit
- gocyclo
- exhaustruct
- execinquery
81 changes: 81 additions & 0 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
project_name: ghalint

env:
- GO111MODULE=on

before:
hooks:
- go mod tidy

builds:
- main: ./cmd/ghalint
binary: ghalint
env:
- CGO_ENABLED=0
goos:
- windows
- darwin
- linux
goarch:
- amd64
- arm64

signs:
- cmd: cosign
artifacts: checksum
signature: ${artifact}.sig
certificate: ${artifact}.pem
output: true
env:
- COSIGN_EXPERIMENTAL=1
args:
- sign-blob
- --output-signature
- ${signature}
- --output-certificate
- ${certificate}
- --oidc-provider
- github
- ${artifact}

archives:
- name_template: '{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}'

release:
prerelease: true # we update release note manually before releasing
header: |
[Pull Requests](https://github.com/suzuki-shunsuke/ghalint/pulls?q=is%3Apr+milestone%3A{{.Tag}}) | [Issues](https://github.com/suzuki-shunsuke/ghalint/issues?q=is%3Aissue+milestone%3A{{.Tag}}) | https://github.com/suzuki-shunsuke/ghalint/compare/{{.PreviousTag}}...{{.Tag}}
brews:
-
# NOTE: make sure the url_template, the token and given repo (github or gitlab) owner and name are from the
# same kind. We will probably unify this in the next major version like it is done with scoop.

# GitHub/GitLab repository to push the formula to
tap:
owner: suzuki-shunsuke
name: homebrew-ghalint
token: "{{ .Env.HOMEBREW_TAP_GITHUB_TOKEN }}"
# The project name and current git tag are used in the format string.
commit_msg_template: "Brew formula update for {{ .ProjectName }} version {{ .Tag }}"
# Your app's homepage.
# Default is empty.
homepage: https://github.com/suzuki-shunsuke/ghalint

# Template of your app's description.
# Default is empty.
description: GitHub Actions linter
license: MIT

# Setting this will prevent goreleaser to actually try to commit the updated
# formula - instead, the formula file will be stored on the dist folder only,
# leaving the responsibility of publishing it to the user.
# If set to auto, the release will not be uploaded to the homebrew tap
# in case there is an indicator for prerelease in the tag e.g. v1.0.0-rc1
# Default is false.
skip_upload: auto

# So you can `brew test` your formula.
# Default is empty.
test: |
system "#{bin}/ghalint --version"
5 changes: 5 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Contributing

Please read the following document.

- https://github.com/suzuki-shunsuke/oss-contribution-guide
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,28 @@
# ghalint

GitHub Actions linter

## Policies

- `job_permissions`: All jobs should have `permissions`
- Why: For least privilege
- `workflow_secrets`: Workflow should not set secrets to environment variables
- How to fix: set secrets to jobs
- Why: To limit the scope of secrets

## How to use

```console
$ ghalint run
```

## Why not `actionlint`?

- We don't think ghalint can replace `actionlint`
- We use both `actionlint` and `ghalint`
- `ghalint` doesn't support features that `actionlint` supports
- We develop `ghalint` to support our policies that `actionlint` doesn't cover

## LICENSE

[MIT](LICENSE)
7 changes: 7 additions & 0 deletions aqua-policy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# aqua - CLI Version Manager
# https://github.com/aquaproj/aqua
registries:
- type: standard
ref: semver(">= 3.0.0")
packages:
- registry: standard
10 changes: 10 additions & 0 deletions aqua.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# aqua - CLI Version Manager
# https://github.com/aquaproj/aqua
registries:
- type: standard
ref: v3.120.1 # renovate: depName=aquaproj/aqua-registry
packages:
- name: suzuki-shunsuke/cmdx@v1.6.1
- name: reviewdog/reviewdog@v0.14.1
- name: golangci/golangci-lint@v1.49.0
- name: sigstore/cosign@v1.13.1
33 changes: 33 additions & 0 deletions cmd/ghalint/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package main

import (
"context"
"log"
"os"
"os/signal"

"github.com/suzuki-shunsuke/ghalint/pkg/cli"
)

var (
version = ""
commit = "" //nolint:gochecknoglobals
date = "" //nolint:gochecknoglobals
)

func main() {
if err := core(); err != nil {
log.Fatal(err)
}
}

func core() error {
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
defer stop()
app := cli.New(&cli.LDFlags{
Version: version,
Commit: commit,
Date: date,
})
return app.RunContext(ctx, os.Args)
}
19 changes: 19 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
module github.com/suzuki-shunsuke/ghalint

go 1.19

require (
github.com/mattn/go-colorable v0.1.13
github.com/sirupsen/logrus v1.9.0
github.com/urfave/cli/v2 v2.23.7
gopkg.in/yaml.v3 v3.0.1
)

require (
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/mattn/go-isatty v0.0.16 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/stretchr/testify v1.8.0 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
golang.org/x/sys v0.3.0 // indirect
)
34 changes: 34 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/urfave/cli/v2 v2.23.7 h1:YHDQ46s3VghFHFf1DdF+Sh7H4RqhcM+t0TmZRJx4oJY=
github.com/urfave/cli/v2 v2.23.7/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
49 changes: 49 additions & 0 deletions pkg/cli/app.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package cli

import (
"github.com/urfave/cli/v2"
)

type LDFlags struct {
Version string
Commit string
Date string
}

func (flags *LDFlags) AppVersion() string {
return flags.Version + " (" + flags.Commit + ")"
}

type Runner struct {
flags *LDFlags
}

func New(flags *LDFlags) *cli.App {
app := cli.NewApp()
app.Name = "ghalint"
app.Usage = "GitHub Actions linter"
app.Version = flags.AppVersion()
app.Flags = []cli.Flag{
// &cli.StringFlag{Name: "log-level", Usage: "log level"},
}
runner := &Runner{
flags: flags,
}
app.Commands = []*cli.Command{
{
Name: "run",
Usage: "lint GitHub Actions Workflows",
Action: runner.Run,
Flags: []cli.Flag{},
},
{
Name: "version",
Usage: "Show version",
Action: func(ctx *cli.Context) error {
cli.ShowVersion(ctx)
return nil
},
},
}
return app
}
28 changes: 28 additions & 0 deletions pkg/cli/job_permissions_policy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package cli

import (
"context"
"errors"

"github.com/sirupsen/logrus"
)

type JobPermissionsPolicy struct{}

func (policy *JobPermissionsPolicy) Name() string {
return "job_permissions"
}

func (policy *JobPermissionsPolicy) Apply(ctx context.Context, logE *logrus.Entry, wf *Workflow) error {
failed := false
for jobName, job := range wf.Jobs {
if job.Permissions == nil {
failed = true
logE.WithField("job_name", jobName).Error("job should have permissions")
}
}
if failed {
return errors.New("workflow violates policies")
}
return nil
}
Loading

0 comments on commit 6745cfb

Please sign in to comment.