Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .github/workflows/dependency-review.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
# This workflow is managed by gh actions-lock.

name: dependency-review

on:
Expand Down
2 changes: 0 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
# This workflow is managed by gh actions-lock.

name: Release

on:
Expand Down
2 changes: 0 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
# This workflow is managed by gh actions-lock.

name: test

on:
Expand Down
3 changes: 0 additions & 3 deletions cmd/gh-actions-lock/selfrepository_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"sync/atomic"
"testing"

"github.com/github/gh-actions-lock/internal/workflowfile"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
Expand Down Expand Up @@ -51,7 +50,6 @@ jobs:
gotWorkflow, err := os.ReadFile(workflowPath)
require.NoError(t, err)
assert.Equal(t, workflow, gotWorkflow)
assert.NotContains(t, string(gotWorkflow), workflowfile.SentinelComment)

lockPath := filepath.Join(dir, ".github", "workflows", "actions.lock")
if lockContent, readErr := os.ReadFile(lockPath); readErr == nil {
Expand Down Expand Up @@ -92,7 +90,6 @@ jobs:
gotWorkflow, readErr := os.ReadFile(workflowPath)
require.NoError(t, readErr)
assert.Equal(t, workflow, gotWorkflow)
assert.NotContains(t, string(gotWorkflow), workflowfile.SentinelComment)
lockPath := filepath.Join(dir, ".github", "workflows", "actions.lock")
_, readErr = os.Stat(lockPath)
assert.ErrorIs(t, readErr, os.ErrNotExist)
Expand Down
4 changes: 1 addition & 3 deletions internal/pin/commit.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,16 +100,14 @@ func rewriteWorkflow(wp WorkflowPlan) error {
}
}

content = workflowfile.EnsureSentinel(content)
if bytes.Equal(content, wf.Content) {
return nil
}
return os.WriteFile(wp.Path, content, 0o644)
}

// rewriteSelfActionFiles applies each workflow's rewrites to the in-repo
// action files it reaches via `$/…`. No sentinel comment: these are action
// definitions, not managed workflows.
// action files it reaches via `$/…`.
func rewriteSelfActionFiles(plans []WorkflowPlan) error {
merged := make(map[string]map[string]string)
for _, wp := range plans {
Expand Down
9 changes: 7 additions & 2 deletions internal/pin/commit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,11 +113,12 @@ func TestCommitRemovesDependenciesDroppedFromWorkflow(t *testing.T) {
dir := t.TempDir()
workflowPath := filepath.Join(".github", "workflows", "ci.yml")
require.NoError(t, os.MkdirAll(filepath.Join(dir, filepath.Dir(workflowPath)), 0o755))
require.NoError(t, os.WriteFile(filepath.Join(dir, workflowPath), []byte(`on: push
workflow := []byte(`on: push
jobs:
lint:
uses: owner/reusable/.github/workflows/lint.yml@main
`), 0o644))
`)
require.NoError(t, os.WriteFile(filepath.Join(dir, workflowPath), workflow, 0o644))
t.Chdir(dir)

store, err := lockfile.LoadState(dir, fakeMeta{})
Expand All @@ -144,6 +145,10 @@ jobs:
}
require.NoError(t, Commit(context.Background(), rec, store, nil))

gotWorkflow, err := os.ReadFile(filepath.Join(dir, workflowPath))
require.NoError(t, err)
assert.Equal(t, workflow, gotWorkflow)

got, err := os.ReadFile(filepath.Join(dir, ".github", "workflows", "actions.lock"))
require.NoError(t, err)
assert.Contains(t, string(got), "actions/checkout@v7")
Expand Down
3 changes: 1 addition & 2 deletions internal/pin/plan.go
Original file line number Diff line number Diff line change
Expand Up @@ -272,8 +272,7 @@ func planWorkflow(ctx context.Context, wr checks.WorkflowReport, opts PlanOption
SelfActionFiles: wr.SelfActionFiles,
})
} else if len(wplans) == 0 {
// No rewrites and no plan entry yet — still include the workflow
// so EnsureSentinel can be applied during commit.
// Keep the workflow in the plan so its lockfile entry is updated.
wplans = append(wplans, WorkflowPlan{Path: wr.Path, SelfActionFiles: wr.SelfActionFiles})
}

Expand Down
26 changes: 0 additions & 26 deletions internal/workflowfile/rewrite.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package workflowfile

import (
"bytes"
"fmt"
"os"
"path/filepath"
Expand All @@ -10,31 +9,6 @@ import (
"gopkg.in/yaml.v3"
)

// SentinelComment is prepended to workflow files managed by gh actions-lock
// so users can tell at a glance that the file's action refs are locked.
const SentinelComment = "# This workflow is managed by gh actions-lock."

// EnsureSentinel prepends the sentinel comment to the workflow content if it
// is not already present at the top of the file. The comment is placed before
// any existing content with a blank line separating it from the YAML body.
func EnsureSentinel(content []byte) []byte {
if bytes.HasPrefix(content, []byte(SentinelComment)) {
return content
}

var buf bytes.Buffer
buf.WriteString(SentinelComment)
buf.WriteByte('\n')

// If the file doesn't start with a comment or blank line, add a
// separator so the sentinel stands apart from the YAML body.
if len(content) > 0 && content[0] != '#' && content[0] != '\n' {
buf.WriteByte('\n')
}
buf.Write(content)
return buf.Bytes()
}

// RewriteActionRefs rewrites targeted uses: refs in the original workflow
// content while preserving the surrounding formatting and comments.
func (f *File) RewriteActionRefs(replacements map[string]string) ([]byte, int, error) {
Expand Down
41 changes: 0 additions & 41 deletions internal/workflowfile/rewrite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,47 +9,6 @@ import (
"github.com/stretchr/testify/require"
)

func TestEnsureSentinel(t *testing.T) {
tests := []struct {
name string
input string
want string
}{
{
name: "adds sentinel to plain workflow",
input: "name: ci\non: push\n",
want: SentinelComment + "\n\nname: ci\non: push\n",
},
{
name: "adds sentinel before existing comment",
input: "# my workflow\nname: ci\n",
want: SentinelComment + "\n# my workflow\nname: ci\n",
},
{
name: "idempotent when sentinel already present",
input: SentinelComment + "\n\nname: ci\n",
want: SentinelComment + "\n\nname: ci\n",
},
{
name: "empty content",
input: "",
want: SentinelComment + "\n",
},
{
name: "sentinel buried in file still prepends",
input: "name: ci\n# This workflow is managed by gh actions-lock.\non: push\n",
want: SentinelComment + "\n\nname: ci\n# This workflow is managed by gh actions-lock.\non: push\n",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := EnsureSentinel([]byte(tt.input))
assert.Equal(t, tt.want, string(got))
})
}
}

func TestSubpathRewriteLookup(t *testing.T) {
replacements := map[string]string{
"actions/cache@27d5ce7": "actions/cache@v5.0.5",
Expand Down
4 changes: 0 additions & 4 deletions test/integration/run.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@
# Minimal workflow YAML that uses a single action.
def simple_workflow(name:, action:)
<<~YAML
# This workflow is managed by gh actions-lock.

name: #{name}
on: workflow_dispatch
jobs:
Expand All @@ -39,8 +37,6 @@ def simple_workflow(name:, action:)
def multi_action_workflow(name:, actions:)
steps = actions.map { |a| " - uses: #{a}" }.join("\n")
<<~YAML
# This workflow is managed by gh actions-lock.

name: #{name}
on: workflow_dispatch
jobs:
Expand Down
Loading