Skip to content

Commit

Permalink
Merge pull request #1 from veqryn/github-actions
Browse files Browse the repository at this point in the history
GitHub actions
  • Loading branch information
veqryn authored Mar 18, 2024
2 parents 2765648 + 3204791 commit 2c530e5
Show file tree
Hide file tree
Showing 7 changed files with 285 additions and 31 deletions.
11 changes: 11 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates

version: 2
updates:
- package-ecosystem: "gomod" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "weekly"
51 changes: 51 additions & 0 deletions .github/workflows/build_and_test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# This workflow will build a golang project
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go

name: Tests

on:
push:
tags:
branches:
- main
pull_request:
branches:

# Declare default permissions as read only.
permissions: read-all

jobs:

build-and-test:
runs-on: ubuntu-latest
strategy:
matrix:
go-version: [ '1.21', '1.22' ]

steps:
- uses: actions/checkout@v4

- name: Set up Go ${{ matrix.go-version }}
uses: actions/setup-go@v4
with:
go-version: ${{ matrix.go-version }}

- name: Display Go version ${{ matrix.go-version }}
run: go version

- name: Install dependencies ${{ matrix.go-version }}
run: |
go get -t -u golang.org/x/tools/cmd/cover
go mod download
- name: Build ${{ matrix.go-version }}
run: go build -v ./...

- name: Test ${{ matrix.go-version }}
run: go test -v -race -coverprofile=coverage.out -covermode=atomic

- name: Upload coverage reports to Codecov ${{ matrix.go-version }}
uses: codecov/[email protected]
with:
token: ${{ secrets.CODECOV_TOKEN }}
slug: veqryn/slog-json
57 changes: 57 additions & 0 deletions .github/workflows/golangci-lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
name: golangci-lint
on:
push:
branches:
- main
pull_request:

permissions:
contents: read
# Optional: allow read access to pull request. Use with `only-new-issues` option.
pull-requests: read

jobs:
golangci:
name: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v4
with:
go-version: 'stable'
cache: false
- name: Github-action golangci-lint
uses: golangci/golangci-lint-action@v3
with:
# Require: The version of golangci-lint to use.
# When `install-mode` is `binary` (default) the value can be v1.2 or v1.2.3 or `latest` to use the latest version.
# When `install-mode` is `goinstall` the value can be v1.2.3, `latest`, or the hash of a commit.
version: latest

# Optional: working directory, useful for monorepos
# working-directory: somedir

# Optional: golangci-lint command line arguments.
#
# Note: By default, the `.golangci.yml` file should be at the root of the repository.
# The location of the configuration file can be changed by using `--config=`
# args: --timeout=30m --config=/my/path/.golangci.yml --issues-exit-code=0

# Optional: show only new issues if it's a pull request. The default value is `false`.
only-new-issues: true

# Optional: if set to true, then all caching functionality will be completely disabled,
# takes precedence over all other caching options.
# skip-cache: true

# Optional: if set to true, then the action won't cache or restore ~/go/pkg.
# skip-pkg-cache: true

# Optional: if set to true, then the action won't cache or restore ~/.cache/go-build.
# skip-build-cache: true

# Optional: The mode to install golangci-lint. It can be 'binary' or 'goinstall'.
# install-mode: "goinstall"

- name: Manual golangci-lint
run: golangci-lint run ./...
72 changes: 72 additions & 0 deletions .github/workflows/scorecard.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# This workflow uses actions that are not certified by GitHub. They are provided
# by a third-party and are governed by separate terms of service, privacy
# policy, and support documentation.

name: Scorecard supply-chain security
on:
# For Branch-Protection check. Only the default branch is supported. See
# https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection
branch_protection_rule:
# To guarantee Maintained check is occasionally updated. See
# https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained
#schedule:
#- cron: '38 15 * * 5'
push:
branches: [ "main" ]

# Declare default permissions as read only.
permissions: read-all

jobs:
analysis:
name: Scorecard analysis
runs-on: ubuntu-latest
permissions:
# Needed to upload the results to code-scanning dashboard.
security-events: write
# Needed to publish results and get a badge (see publish_results below).
id-token: write
# Uncomment the permissions below if installing in a private repository.
# contents: read
# actions: read

steps:
- name: "Checkout code"
uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # v3.1.0
with:
persist-credentials: false

- name: "Run analysis"
uses: ossf/scorecard-action@e38b1902ae4f44df626f11ba0734b14fb91f8f86 # v2.1.2
with:
results_file: results.sarif
results_format: sarif
# (Optional) "write" PAT token. Uncomment the `repo_token` line below if:
# - you want to enable the Branch-Protection check on a *public* repository, or
# - you are installing Scorecard on a *private* repository
# To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat.
# repo_token: ${{ secrets.SCORECARD_TOKEN }}

# Public repositories:
# - Publish results to OpenSSF REST API for easy access by consumers
# - Allows the repository to include the Scorecard badge.
# - See https://github.com/ossf/scorecard-action#publishing-results.
# For private repositories:
# - `publish_results` will always be set to `false`, regardless
# of the value entered here.
publish_results: true

# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
# format to the repository Actions tab.
- name: "Upload artifact"
uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0
with:
name: SARIF file
path: results.sarif
retention-days: 5

# Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@17573ee1cc1b9d061760f3a006fc4aac4f944fd5 # v2.2.4
with:
sarif_file: results.sarif
4 changes: 4 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
run:
tests: false
skip-dirs:
- internal/buffer
64 changes: 33 additions & 31 deletions handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,23 @@ type HandlerOptions struct {
JSONOptions jsontext.Options
}

var defaultJSONOptions = json.JoinOptions(
json.Deterministic(true),
json.DiscardUnknownMembers(false),
json.FormatNilMapAsNull(false),
json.FormatNilSliceAsNull(false),
json.MatchCaseInsensitiveNames(false),
json.StringifyNumbers(false),
json.RejectUnknownMembers(false),
jsontext.AllowDuplicateNames(true),
jsontext.AllowInvalidUTF8(true),
jsontext.EscapeForHTML(false),
jsontext.EscapeForJS(true),
jsontext.Multiline(false),
jsontext.SpaceAfterColon(false),
jsontext.SpaceAfterComma(true),
)

// Handler is a [log/slog.Handler] that writes Records to an [io.Writer] as
// line-delimited JSON objects.
type Handler struct {
Expand All @@ -107,22 +124,7 @@ func NewHandler(w io.Writer, opts *HandlerOptions) *Handler {
}
// Defaults
if opts.JSONOptions == nil {
opts.JSONOptions = json.JoinOptions(
json.Deterministic(true),
json.DiscardUnknownMembers(false),
json.FormatNilMapAsNull(false),
json.FormatNilSliceAsNull(false),
json.MatchCaseInsensitiveNames(false),
json.StringifyNumbers(false),
json.RejectUnknownMembers(false),
jsontext.AllowDuplicateNames(true),
jsontext.AllowInvalidUTF8(true),
jsontext.EscapeForHTML(false),
jsontext.EscapeForJS(true),
jsontext.Multiline(false),
jsontext.SpaceAfterColon(false),
jsontext.SpaceAfterComma(true),
)
opts.JSONOptions = defaultJSONOptions
}

// Warn about how to properly avoid duplicates (without throwing errors)
Expand Down Expand Up @@ -267,7 +269,7 @@ func (h *Handler) WithGroup(name string) slog.Handler {
func (h *Handler) Handle(_ context.Context, r slog.Record) error {
state := h.newHandleState(buffer.New(), true, "")
defer state.free()
state.buf.WriteByte('{')
_ = state.buf.WriteByte('{')

// Built-in attributes. They are not in a group.
stateGroups := state.groups
Expand Down Expand Up @@ -307,7 +309,7 @@ func (h *Handler) Handle(_ context.Context, r slog.Record) error {
}
state.groups = stateGroups // Restore groups passed to ReplaceAttrs.
state.appendNonBuiltIns(r)
state.buf.WriteByte('\n')
_ = state.buf.WriteByte('\n')

h.mu.Lock()
defer h.mu.Unlock()
Expand All @@ -332,8 +334,8 @@ func recordSource(r slog.Record) *slog.Source {
func (s *handleState) appendNonBuiltIns(r slog.Record) {
// preformatted Attrs
if pfa := s.h.preformattedAttrs; len(pfa) > 0 {
s.buf.WriteString(s.sep)
s.buf.Write(pfa)
_, _ = s.buf.WriteString(s.sep)
_, _ = s.buf.Write(pfa)
s.sep = s.h.attrSep
if pfa[len(pfa)-1] == '{' {
s.sep = ""
Expand Down Expand Up @@ -366,10 +368,10 @@ func (s *handleState) appendNonBuiltIns(r slog.Record) {

// Close all open groups.
for range s.h.groups[:nOpenGroups] {
s.buf.WriteByte('}')
_ = s.buf.WriteByte('}')
}
// Close the top-level object.
s.buf.WriteByte('}')
_ = s.buf.WriteByte('}')
}

// handleState holds state for a single call to Handler.handle.
Expand Down Expand Up @@ -422,7 +424,7 @@ func (s *handleState) openGroups() {
// with the given name.
func (s *handleState) openGroup(name string) {
s.appendKey(name)
s.buf.WriteByte('{')
_ = s.buf.WriteByte('{')
s.sep = ""

// Collect group names for ReplaceAttr.
Expand All @@ -433,7 +435,7 @@ func (s *handleState) openGroup(name string) {

// closeGroup ends the group with the given name.
func (s *handleState) closeGroup(name string) {
s.buf.WriteByte('}')
_ = s.buf.WriteByte('}')

s.sep = s.h.attrSep
if s.groups != nil {
Expand Down Expand Up @@ -535,16 +537,16 @@ func (s *handleState) appendError(err error) {
}

func (s *handleState) appendKey(key string) {
s.buf.WriteString(s.sep)
_, _ = s.buf.WriteString(s.sep)
s.appendString(key)
s.buf.WriteString(s.h.keySep)
_, _ = s.buf.WriteString(s.h.keySep)
s.sep = s.h.attrSep
}

func (s *handleState) appendString(str string) {
s.buf.WriteByte('"')
_ = s.buf.WriteByte('"')
*s.buf = appendEscapedJSONString(*s.buf, str)
s.buf.WriteByte('"')
_ = s.buf.WriteByte('"')
}

func (s *handleState) appendValue(v slog.Value) {
Expand Down Expand Up @@ -578,9 +580,9 @@ func appendJSONTime(s *handleState, t time.Time) {
// See golang.org/issue/4556#c15 for more discussion.
s.appendError(errors.New("time.Time year outside of range [0,9999]"))
}
s.buf.WriteByte('"')
_ = s.buf.WriteByte('"')
*s.buf = t.AppendFormat(*s.buf, time.RFC3339Nano)
s.buf.WriteByte('"')
_ = s.buf.WriteByte('"')
}

func appendJSONValue(s *handleState, v slog.Value) error {
Expand Down Expand Up @@ -635,7 +637,7 @@ func appendJSONMarshal(buf *buffer.Buffer, v any, opts jsontext.Options) error {
if err != nil {
return err
}
buf.Write(bs)
_, _ = buf.Write(bs)
return nil
}

Expand Down
Loading

0 comments on commit 2c530e5

Please sign in to comment.