Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
15e389f7b8 |
@@ -33,5 +33,5 @@ jobs:
|
|||||||
# report success from cache.
|
# report success from cache.
|
||||||
run: git rev-parse HEAD > .ci-fingerprint
|
run: git rev-parse HEAD > .ci-fingerprint
|
||||||
|
|
||||||
- name: Build Docker image (runs make fmt-check, golangci-lint, make test, make build)
|
- name: Build Docker image (runs make check)
|
||||||
run: script/cibuild
|
run: script/cibuild
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ before deploying one.
|
|||||||
### Prerequisites
|
### Prerequisites
|
||||||
|
|
||||||
- Go 1.26.1+ (the version in `go.mod`)
|
- Go 1.26.1+ (the version in `go.mod`)
|
||||||
- Docker (for `make lint` and so for `make check`, for the browser test in
|
- Docker (for linting, for the browser test, for the test stage of the
|
||||||
`make test-browser`, for the CI gate, and for containerized deployment)
|
CI gate, and for containerized deployment)
|
||||||
|
|
||||||
golangci-lint is not a prerequisite and must not be installed on the
|
golangci-lint is not a prerequisite and must not be installed on the
|
||||||
host: `script/bootstrap` does not install it, and `make lint` runs the
|
host: `script/bootstrap` does not install it, and `make lint` runs the
|
||||||
@@ -3361,9 +3361,8 @@ linked, which is what lets it run on the Alpine runtime image.
|
|||||||
inside the image, so a build that succeeds is a repo that is formatted,
|
inside the image, so a build that succeeds is a repo that is formatted,
|
||||||
linted, tested and compiled. `script/lint` also uses Docker
|
linted, tested and compiled. `script/lint` also uses Docker
|
||||||
(`Dockerfile.lint`, see Linting above), so `make lint` and `make check`
|
(`Dockerfile.lint`, see Linting above), so `make lint` and `make check`
|
||||||
run the same pinned linter version the gate does; of the steps
|
run the same pinned linter version the gate does; only `script/test`
|
||||||
`make check` runs, only `script/test` and `script/fmt-check` run on the
|
and `script/fmt-check` run on the host.
|
||||||
host.
|
|
||||||
|
|
||||||
#### CI gate honesty
|
#### CI gate honesty
|
||||||
|
|
||||||
|
|||||||
@@ -1911,13 +1911,9 @@ func (h *Handlers) HandleTargetToggle() http.HandlerFunc {
|
|||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only the active column: saving the whole row would
|
tgt.Active = !tgt.Active
|
||||||
// write back the name and settings read above over an
|
|
||||||
// edit saved since.
|
|
||||||
active := !tgt.Active
|
|
||||||
|
|
||||||
return active, h.db.DB().Model(&tgt).
|
return tgt.Active, h.db.DB().Save(&tgt).Error
|
||||||
Update("active", active).Error
|
|
||||||
},
|
},
|
||||||
"failed to toggle target",
|
"failed to toggle target",
|
||||||
targetActivated, targetDeactivated,
|
targetActivated, targetDeactivated,
|
||||||
|
|||||||
@@ -1,66 +0,0 @@
|
|||||||
package handlers_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
"net/http/httptest"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
"gorm.io/gorm"
|
|
||||||
)
|
|
||||||
|
|
||||||
// TestHandleTargetToggle_DoesNotUndoAnEdit proves that a toggle which
|
|
||||||
// loaded the target before an edit of it was saved does not write the
|
|
||||||
// old name and settings back over the edit. The edit is submitted from
|
|
||||||
// a callback on the toggle's own read of the target, so it is saved
|
|
||||||
// after that read and before the toggle writes.
|
|
||||||
func TestHandleTargetToggle_DoesNotUndoAnEdit(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
env := setupSourceTest(t)
|
|
||||||
wh, tgt := seedHTTPTarget(t, env, "", "")
|
|
||||||
require.True(t, tgt.Active)
|
|
||||||
|
|
||||||
var (
|
|
||||||
edited bool
|
|
||||||
editCode int
|
|
||||||
)
|
|
||||||
|
|
||||||
require.NoError(t, env.db.DB().Callback().Query().
|
|
||||||
After("gorm:query").
|
|
||||||
Register("test:edit_after_toggle_read", func(tx *gorm.DB) {
|
|
||||||
// The edit reads the target too; only the toggle's read,
|
|
||||||
// the first, submits it.
|
|
||||||
if tx.Statement.Table != "targets" || edited {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
edited = true
|
|
||||||
editCode = submitTargetEdit(
|
|
||||||
env, wh.ID, tgt.ID,
|
|
||||||
editForm(editReplacedURL, "", ""),
|
|
||||||
).Code
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
|
|
||||||
req := postRequest(
|
|
||||||
"/hook/"+wh.ID+"/targets/"+tgt.ID+"/toggle",
|
|
||||||
env.cookies,
|
|
||||||
map[string]string{paramSourceID: wh.ID, paramTargetID: tgt.ID},
|
|
||||||
)
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
|
|
||||||
env.handlers.HandleTargetToggle().ServeHTTP(w, req)
|
|
||||||
|
|
||||||
require.Equal(t, http.StatusSeeOther, w.Code)
|
|
||||||
require.Equal(t, http.StatusSeeOther, editCode)
|
|
||||||
|
|
||||||
stored := storedTarget(t, env, tgt.ID)
|
|
||||||
assert.False(t, stored.Active)
|
|
||||||
assert.Equal(t, "edited-name", stored.Name)
|
|
||||||
assert.Equal(t, 5, stored.MaxRetries)
|
|
||||||
assert.Equal(
|
|
||||||
t, editReplacedURL, storedHTTPConfig(t, env, tgt.ID).URL,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/gorilla/sessions"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"sneak.berlin/go/webhooker/internal/config"
|
"sneak.berlin/go/webhooker/internal/config"
|
||||||
@@ -77,7 +78,14 @@ func newTestSessionManager(
|
|||||||
key[i] = byte(i)
|
key[i] = byte(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
store := session.NewStore(key)
|
store := sessions.NewCookieStore(key)
|
||||||
|
store.Options = &sessions.Options{
|
||||||
|
Path: "/",
|
||||||
|
MaxAge: 86400 * 7,
|
||||||
|
HttpOnly: true,
|
||||||
|
Secure: false,
|
||||||
|
SameSite: http.SameSiteLaxMode,
|
||||||
|
}
|
||||||
|
|
||||||
var now func() time.Time
|
var now func() time.Time
|
||||||
|
|
||||||
@@ -923,7 +931,8 @@ func metricsAuthMiddleware(
|
|||||||
}
|
}
|
||||||
|
|
||||||
key := make([]byte, testKeySize)
|
key := make([]byte, testKeySize)
|
||||||
store := session.NewStore(key)
|
store := sessions.NewCookieStore(key)
|
||||||
|
store.Options = &sessions.Options{Path: "/", MaxAge: 86400}
|
||||||
|
|
||||||
sessManager := session.NewForTest(store, cfg, log, key, nil)
|
sessManager := session.NewForTest(store, cfg, log, key, nil)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package session
|
||||||
|
|
||||||
|
import "github.com/gorilla/sessions"
|
||||||
|
|
||||||
|
// NewStore exposes the production cookie-store constructor so tests
|
||||||
|
// exercise the store the application actually runs with, rather than a
|
||||||
|
// lookalike assembled in the test.
|
||||||
|
func NewStore(key []byte) *sessions.CookieStore {
|
||||||
|
return newStore(key)
|
||||||
|
}
|
||||||
@@ -8,13 +8,6 @@ import (
|
|||||||
"sneak.berlin/go/webhooker/internal/config"
|
"sneak.berlin/go/webhooker/internal/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewStore exposes the production cookie-store constructor so tests
|
|
||||||
// exercise the store the application actually runs with, rather than a
|
|
||||||
// lookalike assembled in the test.
|
|
||||||
func NewStore(key []byte) *sessions.CookieStore {
|
|
||||||
return newStore(key)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewForTest creates a Session with a pre-configured cookie store for use
|
// NewForTest creates a Session with a pre-configured cookie store for use
|
||||||
// in tests. This bypasses the fx lifecycle and database dependency, allowing
|
// in tests. This bypasses the fx lifecycle and database dependency, allowing
|
||||||
// middleware and handler tests to use real session functionality. The key
|
// middleware and handler tests to use real session functionality. The key
|
||||||
|
|||||||
Reference in New Issue
Block a user