diff --git a/.github/codeql/config.yml b/.github/codeql/config.yml deleted file mode 100644 index 3a18ed59..00000000 --- a/.github/codeql/config.yml +++ /dev/null @@ -1,2 +0,0 @@ -paths-ignore: -- ./http/client/testdata \ No newline at end of file diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index eeedf6a8..9ec1234a 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -31,9 +31,6 @@ jobs: - name: Initialize CodeQL uses: github/codeql-action/init@v2 - with: - languages: ${{ matrix.language }} - config-file: ./.github/codeql/config.yml - name: Autobuild uses: github/codeql-action/autobuild@v2 diff --git a/go.mod b/go.mod index 3b1c399e..6465410a 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,6 @@ require ( github.com/coreos/go-oidc/v3 v3.7.0 github.com/gorilla/mux v1.8.0 github.com/lib/pq v1.10.9 - github.com/mccutchen/go-httpbin/v2 v2.11.1 github.com/prometheus/client_golang v1.17.0 github.com/tdewolff/minify/v2 v2.19.10 github.com/yuin/goldmark v1.5.6 diff --git a/go.sum b/go.sum index 0d431cbd..b945f822 100644 --- a/go.sum +++ b/go.sum @@ -30,8 +30,6 @@ github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/mccutchen/go-httpbin/v2 v2.11.1 h1:itBs6fEQvMKcGKIbMI9xzoGPZV56o2EMHA2rkCIdmLw= -github.com/mccutchen/go-httpbin/v2 v2.11.1/go.mod h1:f4DUXYlU6yH0V81O4lJIwqpmYdTXXmYwzxMnYEimFPk= 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/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= diff --git a/internal/api/feed.go b/internal/api/feed.go index 27f93ab7..33973402 100644 --- a/internal/api/feed.go +++ b/internal/api/feed.go @@ -41,9 +41,9 @@ func (h *handler) createFeed(w http.ResponseWriter, r *http.Request) { return } - feed, err := feedHandler.CreateFeed(h.store, userID, &feedCreationRequest) - if err != nil { - json.ServerError(w, r, err) + feed, localizedError := feedHandler.CreateFeed(h.store, userID, &feedCreationRequest) + if localizedError != nil { + json.ServerError(w, r, localizedError.Error()) return } @@ -59,9 +59,9 @@ func (h *handler) refreshFeed(w http.ResponseWriter, r *http.Request) { return } - err := feedHandler.RefreshFeed(h.store, userID, feedID, false) - if err != nil { - json.ServerError(w, r, err) + localizedError := feedHandler.RefreshFeed(h.store, userID, feedID, false) + if localizedError != nil { + json.ServerError(w, r, localizedError.Error()) return } diff --git a/internal/api/subscription.go b/internal/api/subscription.go index eb744419..499d99a0 100644 --- a/internal/api/subscription.go +++ b/internal/api/subscription.go @@ -32,7 +32,7 @@ func (h *handler) discoverSubscriptions(w http.ResponseWriter, r *http.Request) rssbridgeURL = intg.RSSBridgeURL } - subscriptions, finderErr := subscription.FindSubscriptions( + subscriptions, localizedError := subscription.FindSubscriptions( subscriptionDiscoveryRequest.URL, subscriptionDiscoveryRequest.UserAgent, subscriptionDiscoveryRequest.Cookie, @@ -42,12 +42,13 @@ func (h *handler) discoverSubscriptions(w http.ResponseWriter, r *http.Request) subscriptionDiscoveryRequest.AllowSelfSignedCertificates, rssbridgeURL, ) - if finderErr != nil { - json.ServerError(w, r, finderErr) + + if localizedError != nil { + json.ServerError(w, r, localizedError.Error()) return } - if subscriptions == nil { + if len(subscriptions) == 0 { json.NotFound(w, r) return } diff --git a/internal/errors/errors.go b/internal/errors/errors.go deleted file mode 100644 index e98ca6f7..00000000 --- a/internal/errors/errors.go +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved. -// SPDX-License-Identifier: Apache-2.0 - -package errors // import "miniflux.app/v2/internal/errors" - -import ( - "fmt" - - "miniflux.app/v2/internal/locale" -) - -// LocalizedError represents an error than could be translated to another language. -type LocalizedError struct { - message string - args []interface{} -} - -// Error returns untranslated error message. -func (l LocalizedError) Error() string { - return fmt.Sprintf(l.message, l.args...) -} - -// Localize returns the translated error message. -func (l LocalizedError) Localize(printer *locale.Printer) string { - return printer.Printf(l.message, l.args...) -} - -// NewLocalizedError returns a new LocalizedError. -func NewLocalizedError(message string, args ...interface{}) *LocalizedError { - return &LocalizedError{message: message, args: args} -} diff --git a/internal/googlereader/handler.go b/internal/googlereader/handler.go index 681bed4c..242cf55c 100644 --- a/internal/googlereader/handler.go +++ b/internal/googlereader/handler.go @@ -673,9 +673,9 @@ func (h *handler) quickAddHandler(w http.ResponseWriter, r *http.Request) { return } - subscriptions, s_err := mfs.FindSubscriptions(url, "", "", "", "", false, false, "") - if s_err != nil { - json.ServerError(w, r, s_err) + subscriptions, localizedError := mfs.FindSubscriptions(url, "", "", "", "", false, false, "") + if localizedError != nil { + json.ServerError(w, r, localizedError.Error()) return } @@ -746,9 +746,9 @@ func subscribe(newFeed Stream, category Stream, title string, store *storage.Sto return nil, verr.Error() } - created, err := mff.CreateFeed(store, userID, &feedRequest) + created, localizedError := mff.CreateFeed(store, userID, &feedRequest) if err != nil { - return nil, err + return nil, localizedError.Error() } if title != "" { diff --git a/internal/http/client/client.go b/internal/http/client/client.go deleted file mode 100644 index 00baf650..00000000 --- a/internal/http/client/client.go +++ /dev/null @@ -1,322 +0,0 @@ -// SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved. -// SPDX-License-Identifier: Apache-2.0 - -package client // import "miniflux.app/v2/internal/http/client" - -import ( - "bytes" - "crypto/tls" - "crypto/x509" - "fmt" - "io" - "log/slog" - "net" - "net/http" - "net/url" - "time" - - "miniflux.app/v2/internal/config" - "miniflux.app/v2/internal/errors" -) - -const ( - defaultHTTPClientTimeout = 20 - defaultHTTPClientMaxBodySize = 15 * 1024 * 1024 -) - -var ( - errInvalidCertificate = "Invalid SSL certificate (original error: %q)" - errNetworkOperation = "This website is unreachable (original error: %q)" - errRequestTimeout = "Website unreachable, the request timed out after %d seconds" -) - -// Client builds and executes HTTP requests. -type Client struct { - inputURL string - - requestEtagHeader string - requestLastModifiedHeader string - requestAuthorizationHeader string - requestUsername string - requestPassword string - requestUserAgent string - requestCookie string - customHeaders map[string]string - useProxy bool - doNotFollowRedirects bool - - ClientTimeout int - ClientMaxBodySize int64 - ClientProxyURL string - AllowSelfSignedCertificates bool -} - -// New initializes a new HTTP client. -func New(url string) *Client { - return &Client{ - inputURL: url, - ClientTimeout: defaultHTTPClientTimeout, - ClientMaxBodySize: defaultHTTPClientMaxBodySize, - } -} - -// NewClientWithConfig initializes a new HTTP client with application config options. -func NewClientWithConfig(url string, opts *config.Options) *Client { - return &Client{ - inputURL: url, - requestUserAgent: opts.HTTPClientUserAgent(), - ClientTimeout: opts.HTTPClientTimeout(), - ClientMaxBodySize: opts.HTTPClientMaxBodySize(), - ClientProxyURL: opts.HTTPClientProxy(), - } -} - -// WithCredentials defines the username/password for HTTP Basic authentication. -func (c *Client) WithCredentials(username, password string) *Client { - if username != "" && password != "" { - c.requestUsername = username - c.requestPassword = password - } - return c -} - -// WithCustomHeaders defines custom HTTP headers. -func (c *Client) WithCustomHeaders(customHeaders map[string]string) *Client { - c.customHeaders = customHeaders - return c -} - -// WithCacheHeaders defines caching headers. -func (c *Client) WithCacheHeaders(etagHeader, lastModifiedHeader string) *Client { - c.requestEtagHeader = etagHeader - c.requestLastModifiedHeader = lastModifiedHeader - return c -} - -// WithProxy enables proxy for the current HTTP request. -func (c *Client) WithProxy() *Client { - c.useProxy = true - return c -} - -// WithoutRedirects disables HTTP redirects. -func (c *Client) WithoutRedirects() *Client { - c.doNotFollowRedirects = true - return c -} - -// WithUserAgent defines the User-Agent header to use for HTTP requests. -func (c *Client) WithUserAgent(userAgent string) *Client { - if userAgent != "" { - c.requestUserAgent = userAgent - } - return c -} - -// WithCookie defines the Cookies to use for HTTP requests. -func (c *Client) WithCookie(cookie string) *Client { - if cookie != "" { - c.requestCookie = cookie - } - return c -} - -// Get performs a GET HTTP request. -func (c *Client) Get() (*Response, error) { - request, err := c.buildRequest(http.MethodGet, nil) - if err != nil { - return nil, err - } - - return c.executeRequest(request) -} - -func (c *Client) executeRequest(request *http.Request) (*Response, error) { - startTime := time.Now() - - slog.Debug("Executing outgoing HTTP request", - slog.Group("request", - slog.String("method", request.Method), - slog.String("url", request.URL.String()), - slog.String("user_agent", request.UserAgent()), - slog.Bool("is_authenticated", c.requestAuthorizationHeader != "" || (c.requestUsername != "" && c.requestPassword != "")), - slog.Bool("has_cookie", c.requestCookie != ""), - slog.Bool("with_redirects", !c.doNotFollowRedirects), - slog.Bool("with_proxy", c.useProxy), - slog.String("proxy_url", c.ClientProxyURL), - slog.Bool("with_caching_headers", c.requestEtagHeader != "" || c.requestLastModifiedHeader != ""), - ), - ) - - client := c.buildClient() - resp, err := client.Do(request) - if resp != nil { - defer resp.Body.Close() - } - - if err != nil { - if uerr, ok := err.(*url.Error); ok { - switch uerr.Err.(type) { - case x509.CertificateInvalidError, x509.HostnameError: - err = errors.NewLocalizedError(errInvalidCertificate, uerr.Err) - case *net.OpError: - err = errors.NewLocalizedError(errNetworkOperation, uerr.Err) - case net.Error: - nerr := uerr.Err.(net.Error) - if nerr.Timeout() { - err = errors.NewLocalizedError(errRequestTimeout, c.ClientTimeout) - } - } - } - - return nil, err - } - - if resp.ContentLength > c.ClientMaxBodySize { - return nil, fmt.Errorf("client: response too large (%d bytes)", resp.ContentLength) - } - - buf, err := io.ReadAll(resp.Body) - if err != nil { - return nil, fmt.Errorf("client: error while reading body %v", err) - } - - response := &Response{ - Body: bytes.NewReader(buf), - StatusCode: resp.StatusCode, - EffectiveURL: resp.Request.URL.String(), - LastModified: resp.Header.Get("Last-Modified"), - ETag: resp.Header.Get("ETag"), - Expires: resp.Header.Get("Expires"), - ContentType: resp.Header.Get("Content-Type"), - ContentLength: resp.ContentLength, - } - - slog.Debug("Completed outgoing HTTP request", - slog.Duration("duration", time.Since(startTime)), - slog.Group("request", - slog.String("method", request.Method), - slog.String("url", request.URL.String()), - slog.String("user_agent", request.UserAgent()), - slog.Bool("is_authenticated", c.requestAuthorizationHeader != "" || (c.requestUsername != "" && c.requestPassword != "")), - slog.Bool("has_cookie", c.requestCookie != ""), - slog.Bool("with_redirects", !c.doNotFollowRedirects), - slog.Bool("with_proxy", c.useProxy), - slog.String("proxy_url", c.ClientProxyURL), - slog.Bool("with_caching_headers", c.requestEtagHeader != "" || c.requestLastModifiedHeader != ""), - ), - slog.Group("response", - slog.Int("status_code", response.StatusCode), - slog.String("effective_url", response.EffectiveURL), - slog.String("content_type", response.ContentType), - slog.Int64("content_length", response.ContentLength), - slog.String("last_modified", response.LastModified), - slog.String("etag", response.ETag), - slog.String("expires", response.Expires), - ), - ) - - // Ignore caching headers for feeds that do not want any cache. - if resp.Header.Get("Expires") == "0" { - response.ETag = "" - response.LastModified = "" - } - - return response, err -} - -func (c *Client) buildRequest(method string, body io.Reader) (*http.Request, error) { - request, err := http.NewRequest(method, c.inputURL, body) - if err != nil { - return nil, err - } - - request.Header = c.buildHeaders() - - if c.requestUsername != "" && c.requestPassword != "" { - request.SetBasicAuth(c.requestUsername, c.requestPassword) - } - - return request, nil -} - -func (c *Client) buildClient() http.Client { - client := http.Client{ - Timeout: time.Duration(c.ClientTimeout) * time.Second, - } - - transport := &http.Transport{ - Proxy: http.ProxyFromEnvironment, - DialContext: (&net.Dialer{ - // Default is 30s. - Timeout: 10 * time.Second, - - // Default is 30s. - KeepAlive: 15 * time.Second, - }).DialContext, - - // Default is 100. - MaxIdleConns: 50, - - // Default is 90s. - IdleConnTimeout: 10 * time.Second, - } - - if c.AllowSelfSignedCertificates { - transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true} - } - - if c.doNotFollowRedirects { - client.CheckRedirect = func(req *http.Request, via []*http.Request) error { - return http.ErrUseLastResponse - } - } - - if c.useProxy && c.ClientProxyURL != "" { - proxyURL, err := url.Parse(c.ClientProxyURL) - if err != nil { - slog.Error("Unable to parse proxy URL", - slog.String("proxy_url", c.ClientProxyURL), - slog.Any("error", err), - ) - } else { - transport.Proxy = http.ProxyURL(proxyURL) - } - } - - client.Transport = transport - - return client -} - -func (c *Client) buildHeaders() http.Header { - headers := make(http.Header) - headers.Add("Accept", "*/*") - - if c.requestUserAgent != "" { - headers.Add("User-Agent", c.requestUserAgent) - } - - if c.requestEtagHeader != "" { - headers.Add("If-None-Match", c.requestEtagHeader) - } - - if c.requestLastModifiedHeader != "" { - headers.Add("If-Modified-Since", c.requestLastModifiedHeader) - } - - if c.requestAuthorizationHeader != "" { - headers.Add("Authorization", c.requestAuthorizationHeader) - } - - if c.requestCookie != "" { - headers.Add("Cookie", c.requestCookie) - } - - for key, value := range c.customHeaders { - headers.Add(key, value) - } - - headers.Add("Connection", "close") - return headers -} diff --git a/internal/http/client/client_test.go b/internal/http/client/client_test.go deleted file mode 100644 index c68e48a4..00000000 --- a/internal/http/client/client_test.go +++ /dev/null @@ -1,70 +0,0 @@ -// SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved. -// SPDX-License-Identifier: Apache-2.0 - -package client // import "miniflux.app/v2/internal/http/client" - -import ( - "fmt" - "net/http/httptest" - "os" - "testing" - - "github.com/mccutchen/go-httpbin/v2/httpbin" -) - -var srv *httptest.Server - -func TestMain(m *testing.M) { - srv = httptest.NewServer(httpbin.New()) - exitCode := m.Run() - srv.Close() - os.Exit(exitCode) -} - -func MakeClient(path string) *Client { - return New(fmt.Sprintf("%s%s", srv.URL, path)) -} - -func TestClientWithDelay(t *testing.T) { - clt := MakeClient("/delay/5") - clt.ClientTimeout = 1 - _, err := clt.Get() - if err == nil { - t.Fatal(`The client should stops after 1 second`) - } -} - -func TestClientWithError(t *testing.T) { - clt := MakeClient("/status/502") - clt.ClientTimeout = 5 - response, err := clt.Get() - if err != nil { - t.Fatal(err) - } - - if response.StatusCode != 502 { - t.Fatalf(`Unexpected response status code: %d`, response.StatusCode) - } - - if !response.HasServerFailure() { - t.Fatal(`A 502 error is considered as server failure`) - } -} - -func TestClientWithResponseTooLarge(t *testing.T) { - clt := MakeClient("/bytes/100") - clt.ClientMaxBodySize = 10 - _, err := clt.Get() - if err == nil { - t.Fatal(`The client should fails when reading a response too large`) - } -} - -func TestClientWithBasicAuth(t *testing.T) { - clt := MakeClient("/basic-auth/testuser/testpassword") - clt.WithCredentials("testuser", "testpassword") - _, err := clt.Get() - if err != nil { - t.Fatalf(`The client should be authenticated successfully: %v`, err) - } -} diff --git a/internal/http/client/response.go b/internal/http/client/response.go deleted file mode 100644 index 7b2faca7..00000000 --- a/internal/http/client/response.go +++ /dev/null @@ -1,119 +0,0 @@ -// SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved. -// SPDX-License-Identifier: Apache-2.0 - -package client // import "miniflux.app/v2/internal/http/client" - -import ( - "bytes" - "fmt" - "io" - "regexp" - "strings" - "unicode/utf8" - - "golang.org/x/net/html/charset" -) - -var xmlEncodingRegex = regexp.MustCompile(`<\?xml(.*)encoding=["'](.+)["'](.*)\?>`) - -// Response wraps a server response. -type Response struct { - Body io.Reader - StatusCode int - EffectiveURL string - LastModified string - ETag string - Expires string - ContentType string - ContentLength int64 -} - -func (r *Response) String() string { - return fmt.Sprintf( - `StatusCode=%d EffectiveURL=%q LastModified=%q ETag=%s Expires=%s ContentType=%q ContentLength=%d`, - r.StatusCode, - r.EffectiveURL, - r.LastModified, - r.ETag, - r.Expires, - r.ContentType, - r.ContentLength, - ) -} - -// IsNotFound returns true if the resource doesn't exist anymore. -func (r *Response) IsNotFound() bool { - return r.StatusCode == 404 || r.StatusCode == 410 -} - -// IsNotAuthorized returns true if the resource require authentication. -func (r *Response) IsNotAuthorized() bool { - return r.StatusCode == 401 -} - -// HasServerFailure returns true if the status code represents a failure. -func (r *Response) HasServerFailure() bool { - return r.StatusCode >= 400 -} - -// IsModified returns true if the resource has been modified. -func (r *Response) IsModified(etag, lastModified string) bool { - if r.StatusCode == 304 { - return false - } - - if r.ETag != "" && r.ETag == etag { - return false - } - - if r.LastModified != "" && r.LastModified == lastModified { - return false - } - - return true -} - -// EnsureUnicodeBody makes sure the body is encoded in UTF-8. -// -// If a charset other than UTF-8 is detected, we convert the document to UTF-8. -// This is used by the scraper and feed readers. -// -// Do not forget edge cases: -// -// - Feeds with encoding specified only in Content-Type header and not in XML document -// - Feeds with encoding specified in both places -// - Feeds with encoding specified only in XML document and not in HTTP header -// - Feeds with wrong encoding defined and already in UTF-8 -func (r *Response) EnsureUnicodeBody() (err error) { - buffer, err := io.ReadAll(r.Body) - if err != nil { - return err - } - - r.Body = bytes.NewReader(buffer) - if utf8.Valid(buffer) { - return nil - } - - if strings.Contains(r.ContentType, "xml") { - // We ignore documents with encoding specified in XML prolog. - // This is going to be handled by the XML parser. - length := 1024 - if len(buffer) < 1024 { - length = len(buffer) - } - - if xmlEncodingRegex.Match(buffer[0:length]) { - return nil - } - } - - r.Body, err = charset.NewReader(r.Body, r.ContentType) - return err -} - -// BodyAsString returns the response body as string. -func (r *Response) BodyAsString() string { - bytes, _ := io.ReadAll(r.Body) - return string(bytes) -} diff --git a/internal/http/client/response_test.go b/internal/http/client/response_test.go deleted file mode 100644 index 184bc77b..00000000 --- a/internal/http/client/response_test.go +++ /dev/null @@ -1,148 +0,0 @@ -// SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved. -// SPDX-License-Identifier: Apache-2.0 - -package client // import "miniflux.app/v2/internal/http/client" - -import ( - "bytes" - "os" - "strings" - "testing" - "unicode/utf8" -) - -func TestIsNotFound(t *testing.T) { - scenarios := map[int]bool{ - 200: false, - 404: true, - 410: true, - } - - for input, expected := range scenarios { - r := &Response{StatusCode: input} - actual := r.IsNotFound() - - if actual != expected { - t.Errorf(`Unexpected result, got %v instead of %v for status code %d`, actual, expected, input) - } - } -} - -func TestIsNotAuthorized(t *testing.T) { - scenarios := map[int]bool{ - 200: false, - 401: true, - 403: false, - } - - for input, expected := range scenarios { - r := &Response{StatusCode: input} - actual := r.IsNotAuthorized() - - if actual != expected { - t.Errorf(`Unexpected result, got %v instead of %v for status code %d`, actual, expected, input) - } - } -} - -func TestHasServerFailure(t *testing.T) { - scenarios := map[int]bool{ - 200: false, - 404: true, - 500: true, - } - - for input, expected := range scenarios { - r := &Response{StatusCode: input} - actual := r.HasServerFailure() - - if actual != expected { - t.Errorf(`Unexpected result, got %v instead of %v for status code %d`, actual, expected, input) - } - } -} - -func TestIsModifiedWith304Status(t *testing.T) { - r := &Response{StatusCode: 304} - if r.IsModified("etag", "lastModified") { - t.Error("The resource should not be considered modified") - } -} - -func TestIsModifiedWithIdenticalEtag(t *testing.T) { - r := &Response{StatusCode: 200, ETag: "etag"} - if r.IsModified("etag", "lastModified") { - t.Error("The resource should not be considered modified") - } -} - -func TestIsModifiedWithIdenticalLastModified(t *testing.T) { - r := &Response{StatusCode: 200, LastModified: "lastModified"} - if r.IsModified("etag", "lastModified") { - t.Error("The resource should not be considered modified") - } -} - -func TestIsModifiedWithDifferentHeaders(t *testing.T) { - r := &Response{StatusCode: 200, ETag: "some etag", LastModified: "some date"} - if !r.IsModified("etag", "lastModified") { - t.Error("The resource should be considered modified") - } -} - -func TestToString(t *testing.T) { - input := `test` - r := &Response{Body: strings.NewReader(input)} - - if r.BodyAsString() != input { - t.Error(`Unexpected output`) - } -} - -func TestEnsureUnicodeWithHTMLDocuments(t *testing.T) { - var unicodeTestCases = []struct { - filename, contentType string - convertedToUnicode bool - }{ - {"HTTP-charset.html", "text/html; charset=iso-8859-15", true}, - {"UTF-16LE-BOM.html", "", true}, - {"UTF-16BE-BOM.html", "", true}, - {"meta-content-attribute.html", "text/html", true}, - {"meta-charset-attribute.html", "text/html", true}, - {"No-encoding-declaration.html", "text/html", true}, - {"HTTP-vs-UTF-8-BOM.html", "text/html; charset=iso-8859-15", true}, - {"HTTP-vs-meta-content.html", "text/html; charset=iso-8859-15", true}, - {"HTTP-vs-meta-charset.html", "text/html; charset=iso-8859-15", true}, - {"UTF-8-BOM-vs-meta-content.html", "text/html", true}, - {"UTF-8-BOM-vs-meta-charset.html", "text/html", true}, - {"windows_1251.html", "text/html; charset=windows-1251", true}, - {"gb2312.html", "text/html", true}, - {"urdu.xml", "text/xml; charset=utf-8", true}, - {"content-type-only-win-8859-1.xml", "application/xml; charset=ISO-8859-1", true}, - {"rdf_utf8.xml", "application/rss+xml; charset=utf-8", true}, - {"rdf_utf8.xml", "application/rss+xml; charset: utf-8", true}, // Invalid Content-Type - {"charset-content-type-xml-iso88591.xml", "application/rss+xml; charset=ISO-8859-1", false}, - {"windows_1251.xml", "text/xml", false}, - {"smallfile.xml", "text/xml; charset=utf-8", true}, - {"single_quote_xml_encoding.xml", "text/xml; charset=utf-8", true}, - } - - for _, tc := range unicodeTestCases { - content, err := os.ReadFile("testdata/" + tc.filename) - if err != nil { - t.Fatalf(`Unable to read file %q: %v`, tc.filename, err) - } - - r := &Response{Body: bytes.NewReader(content), ContentType: tc.contentType} - parseErr := r.EnsureUnicodeBody() - if parseErr != nil { - t.Fatalf(`Unicode conversion error for %q - %q: %v`, tc.filename, tc.contentType, parseErr) - } - - isUnicode := utf8.ValidString(r.BodyAsString()) - if isUnicode != tc.convertedToUnicode { - t.Errorf(`Unicode conversion %q - %q, got: %v, expected: %v`, - tc.filename, tc.contentType, isUnicode, tc.convertedToUnicode) - } - } -} diff --git a/internal/http/client/testdata/HTTP-charset.html b/internal/http/client/testdata/HTTP-charset.html deleted file mode 100644 index 9915fa0e..00000000 --- a/internal/http/client/testdata/HTTP-charset.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - HTTP charset - - - - - - - - - - - -

HTTP charset

- - -
- - -
 
- - - - - -
-

The character encoding of a page can be set using the HTTP header charset declaration.

-

The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector .test div.ÜÀÚ. This matches the sequence of bytes above when they are interpreted as ISO 8859-15. If the class name matches the selector then the test will pass.

The only character encoding declaration for this HTML file is in the HTTP header, which sets the encoding to ISO 8859-15.

-
-
-
Next test
HTML5
-

the-input-byte-stream-001
Result summary & related tests
Detailed results for this test
Link to spec

-
Assumptions:
-
- - - - - - diff --git a/internal/http/client/testdata/HTTP-vs-UTF-8-BOM.html b/internal/http/client/testdata/HTTP-vs-UTF-8-BOM.html deleted file mode 100644 index 26e5d8b4..00000000 --- a/internal/http/client/testdata/HTTP-vs-UTF-8-BOM.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - HTTP vs UTF-8 BOM - - - - - - - - - - - -

HTTP vs UTF-8 BOM

- - -
- - -
 
- - - - - -
-

A character encoding set in the HTTP header has lower precedence than the UTF-8 signature.

-

The HTTP header attempts to set the character encoding to ISO 8859-15. The page starts with a UTF-8 signature.

The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector .test div.ýäè. This matches the sequence of bytes above when they are interpreted as UTF-8. If the class name matches the selector then the test will pass.

If the test is unsuccessful, the characters  should appear at the top of the page. These represent the bytes that make up the UTF-8 signature when encountered in the ISO 8859-15 encoding.

-
-
-
Next test
HTML5
-

the-input-byte-stream-034
Result summary & related tests
Detailed results for this test
Link to spec

-
Assumptions:
-
- - - - - - diff --git a/internal/http/client/testdata/HTTP-vs-meta-charset.html b/internal/http/client/testdata/HTTP-vs-meta-charset.html deleted file mode 100644 index 2f07e951..00000000 --- a/internal/http/client/testdata/HTTP-vs-meta-charset.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - HTTP vs meta charset - - - - - - - - - - - -

HTTP vs meta charset

- - -
- - -
 
- - - - - -
-

The HTTP header has a higher precedence than an encoding declaration in a meta charset attribute.

-

The HTTP header attempts to set the character encoding to ISO 8859-15. The page contains an encoding declaration in a meta charset attribute that attempts to set the character encoding to ISO 8859-1.

The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector .test div.ÜÀÚ. This matches the sequence of bytes above when they are interpreted as ISO 8859-15. If the class name matches the selector then the test will pass.

-
-
-
Next test
HTML5
-

the-input-byte-stream-018
Result summary & related tests
Detailed results for this test
Link to spec

-
Assumptions:
-
- - - - - - diff --git a/internal/http/client/testdata/HTTP-vs-meta-content.html b/internal/http/client/testdata/HTTP-vs-meta-content.html deleted file mode 100644 index 6853cdde..00000000 --- a/internal/http/client/testdata/HTTP-vs-meta-content.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - HTTP vs meta content - - - - - - - - - - - -

HTTP vs meta content

- - -
- - -
 
- - - - - -
-

The HTTP header has a higher precedence than an encoding declaration in a meta content attribute.

-

The HTTP header attempts to set the character encoding to ISO 8859-15. The page contains an encoding declaration in a meta content attribute that attempts to set the character encoding to ISO 8859-1.

The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector .test div.ÜÀÚ. This matches the sequence of bytes above when they are interpreted as ISO 8859-15. If the class name matches the selector then the test will pass.

-
-
-
Next test
HTML5
-

the-input-byte-stream-016
Result summary & related tests
Detailed results for this test
Link to spec

-
Assumptions:
-
- - - - - - diff --git a/internal/http/client/testdata/No-encoding-declaration.html b/internal/http/client/testdata/No-encoding-declaration.html deleted file mode 100644 index 612e26c6..00000000 --- a/internal/http/client/testdata/No-encoding-declaration.html +++ /dev/null @@ -1,47 +0,0 @@ - - - - No encoding declaration - - - - - - - - - - - -

No encoding declaration

- - -
- - -
 
- - - - - -
-

A page with no encoding information in HTTP, BOM, XML declaration or meta element will be treated as UTF-8.

-

The test on this page contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector .test div.ýäè. This matches the sequence of bytes above when they are interpreted as UTF-8. If the class name matches the selector then the test will pass.

-
-
-
Next test
HTML5
-

the-input-byte-stream-015
Result summary & related tests
Detailed results for this test
Link to spec

-
Assumptions:
-
- - - - - - diff --git a/internal/http/client/testdata/README b/internal/http/client/testdata/README deleted file mode 100644 index 38ef0f9f..00000000 --- a/internal/http/client/testdata/README +++ /dev/null @@ -1,9 +0,0 @@ -These test cases come from -http://www.w3.org/International/tests/repository/html5/the-input-byte-stream/results-basics - -Distributed under both the W3C Test Suite License -(http://www.w3.org/Consortium/Legal/2008/04-testsuite-license) -and the W3C 3-clause BSD License -(http://www.w3.org/Consortium/Legal/2008/03-bsd-license). -To contribute to a W3C Test Suite, see the policies and contribution -forms (http://www.w3.org/2004/10/27-testcases). diff --git a/internal/http/client/testdata/UTF-16BE-BOM.html b/internal/http/client/testdata/UTF-16BE-BOM.html deleted file mode 100644 index 3abf7a93..00000000 Binary files a/internal/http/client/testdata/UTF-16BE-BOM.html and /dev/null differ diff --git a/internal/http/client/testdata/UTF-16LE-BOM.html b/internal/http/client/testdata/UTF-16LE-BOM.html deleted file mode 100644 index 76254c98..00000000 Binary files a/internal/http/client/testdata/UTF-16LE-BOM.html and /dev/null differ diff --git a/internal/http/client/testdata/UTF-8-BOM-vs-meta-charset.html b/internal/http/client/testdata/UTF-8-BOM-vs-meta-charset.html deleted file mode 100644 index 83de4333..00000000 --- a/internal/http/client/testdata/UTF-8-BOM-vs-meta-charset.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - UTF-8 BOM vs meta charset - - - - - - - - - - - -

UTF-8 BOM vs meta charset

- - -
- - -
 
- - - - - -
-

A page with a UTF-8 BOM will be recognized as UTF-8 even if the meta charset attribute declares a different encoding.

-

The page contains an encoding declaration in a meta charset attribute that attempts to set the character encoding to ISO 8859-15, but the file starts with a UTF-8 signature.

The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector .test div.ýäè. This matches the sequence of bytes above when they are interpreted as UTF-8. If the class name matches the selector then the test will pass.

-
-
-
Next test
HTML5
-

the-input-byte-stream-038
Result summary & related tests
Detailed results for this test
Link to spec

-
Assumptions:
-
- - - - - - diff --git a/internal/http/client/testdata/UTF-8-BOM-vs-meta-content.html b/internal/http/client/testdata/UTF-8-BOM-vs-meta-content.html deleted file mode 100644 index 501aac2d..00000000 --- a/internal/http/client/testdata/UTF-8-BOM-vs-meta-content.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - UTF-8 BOM vs meta content - - - - - - - - - - - -

UTF-8 BOM vs meta content

- - -
- - -
 
- - - - - -
-

A page with a UTF-8 BOM will be recognized as UTF-8 even if the meta content attribute declares a different encoding.

-

The page contains an encoding declaration in a meta content attribute that attempts to set the character encoding to ISO 8859-15, but the file starts with a UTF-8 signature.

The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector .test div.ýäè. This matches the sequence of bytes above when they are interpreted as UTF-8. If the class name matches the selector then the test will pass.

-
-
-
Next test
HTML5
-

the-input-byte-stream-037
Result summary & related tests
Detailed results for this test
Link to spec

-
Assumptions:
-
- - - - - - diff --git a/internal/http/client/testdata/charset-content-type-xml-iso88591.xml b/internal/http/client/testdata/charset-content-type-xml-iso88591.xml deleted file mode 100644 index bbba7aa6..00000000 --- a/internal/http/client/testdata/charset-content-type-xml-iso88591.xml +++ /dev/null @@ -1,422 +0,0 @@ - - - - - Golem.de - IT-News fuer Profis - https://www.golem.de/ - - Sun, 28 Oct 2018 13:49:01 +0100 - FeedCreator 1.6 - - https://www.golem.de/staticrl/images/golem-rss.png - Golem.de - https://www.golem.de/ - Golem.de News Feed - - de - - - Red Dead Redemption 2: Hinweise auf PC-Umsetzung in App von Rockstar Games - https://www.golem.de/news/red-dead-redemption-2-hinweise-auf-pc-umsetzung-in-app-von-rockstar-games-1810-137358-rss.html - Viele Spieler wnschen sich eine PC-Version von Red Dead Redemption 2, aber Entwickler Rockstar Games schweigt zu dem Thema. Anders die offizielle Companion App: In einigen ihrer Daten gibt es Hinweise auf die Umsetzung. (<a href="https://www.golem.de/specials/red-dead-redemption-2/">Red Dead Redemption 2</a>, <a href="https://www.golem.de/specials/red-dead-redemption/">Red Dead Redemption</a>) <img src="https://cpx.golem.de/cpx.php?class=17&amp;aid=137358&amp;page=1&amp;ts=1540730880" alt="" width="1" height="1" /> - Sun, 28 Oct 2018 13:48:00 +0100 - https://www.golem.de/1810/137358-rss.html - Viele Spieler wnschen sich eine PC-Version von Red Dead Redemption 2, aber Entwickler Rockstar Games schweigt zu dem Thema. Anders die offizielle Companion App: In einigen ihrer Daten gibt es Hinweise auf die Umsetzung. (Red Dead Redemption 2, Red Dead Redemption) ]]> - - - - Let's Play: Twitch will Streamer zusammen spielen und singen lassen - https://www.golem.de/news/let-s-play-twitch-will-streamer-zusammen-spielen-und-singen-lassen-1810-137357-rss.html - Der Streamingdienst Twitch hat auf seiner Hausmesse neue Funktionen fr Kanalbetreiber und Zuschauer vorgestellt. Unter anderem soll es knftig bertragungen mit bis zu vier Spielern geben - und Singwettbewerbe. (<a href="https://www.golem.de/specials/twitch/">Twitch</a>, <a href="https://www.golem.de/specials/amazon/">Amazon</a>) <img src="https://cpx.golem.de/cpx.php?class=17&amp;aid=137357&amp;page=1&amp;ts=1540728000" alt="" width="1" height="1" /> - https://forum.golem.de/kommentare/games/let-s-play-twitch-will-streamer-zusammen-spielen-und-singen-lassen/121579,list.html - Sun, 28 Oct 2018 13:00:00 +0100 - https://www.golem.de/1810/137357-rss.html - Der Streamingdienst Twitch hat auf seiner Hausmesse neue Funktionen fr Kanalbetreiber und Zuschauer vorgestellt. Unter anderem soll es knftig bertragungen mit bis zu vier Spielern geben - und Singwettbewerbe. (Twitch, Amazon) ]]> - - - - Zhuque-1: Erste private chinesische Satellitenmission fehlgeschlagen - https://www.golem.de/news/zhuque-1-erste-private-chinesische-satellitenmission-fehlgeschlagen-1810-137356-rss.html - Die Zhuque-1 hat es nicht in den Orbit geschafft: Beim Znden der dritten Raketenstufe kam es zu Problemen. Bei einem Erfolg wre der Hersteller Landspace das erste von rund 60 kommerziellen chinesischen Unternehmen gewesen, das einen Satelliten ins All gebracht htte. (<a href="https://www.golem.de/specials/raumfahrt/">Raumfahrt</a>, <a href="https://www.golem.de/specials/internet/">Internet</a>) <img src="https://cpx.golem.de/cpx.php?class=17&amp;aid=137356&amp;page=1&amp;ts=1540722420" alt="" width="1" height="1" /> - https://forum.golem.de/kommentare/internet/zhuque-1-erste-private-chinesische-satellitenmission-fehlgeschlagen/121578,list.html - Sun, 28 Oct 2018 11:27:00 +0100 - https://www.golem.de/1810/137356-rss.html - Die Zhuque-1 hat es nicht in den Orbit geschafft: Beim Znden der dritten Raketenstufe kam es zu Problemen. Bei einem Erfolg wre der Hersteller Landspace das erste von rund 60 kommerziellen chinesischen Unternehmen gewesen, das einen Satelliten ins All gebracht htte. (Raumfahrt, Internet) ]]> - 1 - - - City Transformer: Startup entwickelt faltbares Elektroauto gegen Parkplatznot - https://www.golem.de/news/city-transformer-startup-entwickelt-faltbares-elektroauto-gegen-parkplatznot-1810-137355-rss.html - Es passt fast in jede Parklcke: Ein Faltauto des Startups City Transformer soll Stdtern knftig das Leben erleichtern. Das innovative Fahrzeug wird zusammen mit Yamaha entwickelt. Vorbestellungen sollen voraussichtlich ab 2020 mglich sein, mehrere Versionen sind geplant. (<a href="https://www.golem.de/specials/elektromobilitaet/">Elektromobilitt</a>, <a href="https://www.golem.de/specials/elektroauto/">Elektroauto</a>) <img src="https://cpx.golem.de/cpx.php?class=17&amp;aid=137355&amp;page=1&amp;ts=1540721400" alt="" width="1" height="1" /> - https://forum.golem.de/kommentare/automobil/city-transformer-startup-entwickelt-faltbares-elektroauto-gegen-parkplatznot/121577,list.html - Sun, 28 Oct 2018 11:10:00 +0100 - https://www.golem.de/1810/137355-rss.html - Es passt fast in jede Parklcke: Ein Faltauto des Startups City Transformer soll Stdtern knftig das Leben erleichtern. Das innovative Fahrzeug wird zusammen mit Yamaha entwickelt. Vorbestellungen sollen voraussichtlich ab 2020 mglich sein, mehrere Versionen sind geplant. (Elektromobilitt, Elektroauto) ]]> - 37 - - - Machine Learning: Von KI erstelltes Portrt fr 432.500 US.Dollar versteigert - https://www.golem.de/news/machine-learning-von-ki-erstelltes-portraet-fuer-432-500-us-dollar-versteigert-1810-137353-rss.html - Kann Software Kunst erstellen? Eine erfolgreiche Auktion beweist, dass es zumindest Abnehmer dafr gibt. Allerdings hat sich das Entwicklerteam Obvious wohl stark bei anderen KI-Systemen bedient. (<a href="https://www.golem.de/specials/neuronalesnetzwerk/">Neuronales Netzwerk</a>, <a href="https://www.golem.de/specials/ki/">KI</a>) <img src="https://cpx.golem.de/cpx.php?class=17&amp;aid=137353&amp;page=1&amp;ts=1540643580" alt="" width="1" height="1" /> - https://forum.golem.de/kommentare/applikationen/machine-learning-von-ki-erstelltes-portraet-fuer-432.500-us.dollar-versteigert/121575,list.html - Sat, 27 Oct 2018 13:33:00 +0100 - https://www.golem.de/1810/137353-rss.html - Kann Software Kunst erstellen? Eine erfolgreiche Auktion beweist, dass es zumindest Abnehmer dafr gibt. Allerdings hat sich das Entwicklerteam Obvious wohl stark bei anderen KI-Systemen bedient. (Neuronales Netzwerk, KI) ]]> - 31 - - - Projekt Jedi: Microsoft will weiter mit US-Militr zusammenarbeiten - https://www.golem.de/news/project-jedi-microsoft-will-weiter-mit-us-militaer-zusammenarbeiten-1810-137352-rss.html - In einem Blogbeitrag hat sich Microsoft-Prsident Brad Smith zur Zusammenarbeit mit dem US-Verteidigungsministerium bekannt. Mitarbeiter, die nicht an derartigen Projekten arbeiten wollen, sollen in andere Bereiche des Unternehmens wechseln knnen. (<a href="https://www.golem.de/specials/microsoft/">Microsoft</a>, <a href="https://www.golem.de/specials/google/">Google</a>) <img src="https://cpx.golem.de/cpx.php?class=17&amp;aid=137352&amp;page=1&amp;ts=1540641780" alt="" width="1" height="1" /> - https://forum.golem.de/kommentare/internet/projekt-jedi-microsoft-will-weiter-mit-us-militaer-zusammenarbeiten/121574,list.html - Sat, 27 Oct 2018 13:03:00 +0100 - https://www.golem.de/1810/137352-rss.html - In einem Blogbeitrag hat sich Microsoft-Prsident Brad Smith zur Zusammenarbeit mit dem US-Verteidigungsministerium bekannt. Mitarbeiter, die nicht an derartigen Projekten arbeiten wollen, sollen in andere Bereiche des Unternehmens wechseln knnen. (Microsoft, Google) ]]> - 21 - - - Star Wars: Boba-Fett-Film ist "zu 100 Prozent tot" - https://www.golem.de/news/star-wars-boba-fett-film-ist-zu-100-prozent-tot-1810-137351-rss.html - Es wird wohl doch keinen dritten Star-Wars-Ableger geben, der sich um den kultigen Kopfgeldjger Boba Fett dreht. Das wird laut einem Medienbericht teils auf den geringen Erfolg des Han-Solo-Films zurckgefhrt. Stattdessen soll ein bisher unbekannter Charakter in einer Serie die mandalorianische Rstung anziehen. (<a href="https://www.golem.de/specials/star-wars/">Star Wars</a>, <a href="https://www.golem.de/specials/film/">Film</a>) <img src="https://cpx.golem.de/cpx.php?class=17&amp;aid=137351&amp;page=1&amp;ts=1540639620" alt="" width="1" height="1" /> - https://forum.golem.de/kommentare/audio-video/star-wars-boba-fett-film-ist-zu-100-prozent-tot/121573,list.html - Sat, 27 Oct 2018 12:27:00 +0100 - https://www.golem.de/1810/137351-rss.html - Es wird wohl doch keinen dritten Star-Wars-Ableger geben, der sich um den kultigen Kopfgeldjger Boba Fett dreht. Das wird laut einem Medienbericht teils auf den geringen Erfolg des Han-Solo-Films zurckgefhrt. Stattdessen soll ein bisher unbekannter Charakter in einer Serie die mandalorianische Rstung anziehen. (Star Wars, Film) ]]> - 148 - - - Lenovo: Fehlerhafte Bios-Einstellung macht Thinkpads unbrauchbar - https://www.golem.de/news/lenovo-fehlerhafte-bios-einstellung-macht-thinkpads-unbrauchbar-1810-137350-rss.html - Die Bios-Untersttzung fr Thunderbolt bei Thinkpads zu aktivieren, ist derzeit keine gute Idee: Mehrere Nutzer berichten von nicht mehr startenden Notebooks, nachdem sie diese Funktion aktiviert haben. Das konnte auf diversen Linux-Distributionen, aber auch mit Windows 10 repliziert werden. (<a href="https://www.golem.de/specials/lenovo/">Lenovo</a>, <a href="https://www.golem.de/specials/business-notebooks/">Business-Notebooks</a>) <img src="https://cpx.golem.de/cpx.php?class=17&amp;aid=137350&amp;page=1&amp;ts=1540633200" alt="" width="1" height="1" /> - https://forum.golem.de/kommentare/applikationen/lenovo-fehlerhafte-bios-einstellung-macht-thinkpads-unbrauchbar/121572,list.html - Sat, 27 Oct 2018 10:40:00 +0100 - https://www.golem.de/1810/137350-rss.html - Die Bios-Untersttzung fr Thunderbolt bei Thinkpads zu aktivieren, ist derzeit keine gute Idee: Mehrere Nutzer berichten von nicht mehr startenden Notebooks, nachdem sie diese Funktion aktiviert haben. Das konnte auf diversen Linux-Distributionen, aber auch mit Windows 10 repliziert werden. (Lenovo, Business-Notebooks) ]]> - 16 - - - Wochenrckblick: Wilder Westen, buntes Handy, nutzloses Siegel - https://www.golem.de/news/wochenrueckblick-wilder-westen-buntes-handy-nutzloses-siegel-1810-137318-rss.html - Wir testen das iPhone Xr, sind ein Revolverheld und entdecken wieder Sicherheitslcken. Sieben Tage und viele Meldungen im berblick. (<a href="https://www.golem.de/specials/golemwochenrueckblick/">Golem-Wochenrckblick</a>, <a href="https://www.golem.de/specials/business-notebooks/">Business-Notebooks</a>) <img src="https://cpx.golem.de/cpx.php?class=17&amp;aid=137318&amp;page=1&amp;ts=1540623720" alt="" width="1" height="1" /> - https://forum.golem.de/kommentare/politik-recht/wochenrueckblick-wilder-westen-buntes-handy-nutzloses-siegel/121571,list.html - Sat, 27 Oct 2018 08:02:00 +0100 - https://www.golem.de/1810/137318-rss.html - Wir testen das iPhone Xr, sind ein Revolverheld und entdecken wieder Sicherheitslcken. Sieben Tage und viele Meldungen im berblick. (Golem-Wochenrckblick, Business-Notebooks) ]]> - - - - Fernsehen: 5G-Netz wird so wichtig wie Strom und Wasser - https://www.golem.de/news/fernsehen-5g-netz-wird-so-wichtig-wie-strom-und-wasser-1810-137349-rss.html - Ein 5G-FeMBMS-Sendernetz fr die Fernsehverbreitung sorgt fr Aufsehen, noch bevor man wei, ob es funktioniert. Wie Rundfunkbertragung und Mobilfunk zusammenkommen knnen, wurde auf den Medientagen Mnchen besprochen. (<a href="https://www.golem.de/specials/fernsehen/">Fernsehen</a>, <a href="https://www.golem.de/specials/technologie/">Technologie</a>) <img src="https://cpx.golem.de/cpx.php?class=17&amp;aid=137349&amp;page=1&amp;ts=1540572960" alt="" width="1" height="1" /> - https://forum.golem.de/kommentare/handy/fernsehen-5g-netz-wird-so-wichtig-wie-strom-und-wasser/121570,list.html - Fri, 26 Oct 2018 17:56:00 +0100 - https://www.golem.de/1810/137349-rss.html - Ein 5G-FeMBMS-Sendernetz fr die Fernsehverbreitung sorgt fr Aufsehen, noch bevor man wei, ob es funktioniert. Wie Rundfunkbertragung und Mobilfunk zusammenkommen knnen, wurde auf den Medientagen Mnchen besprochen. (Fernsehen, Technologie) ]]> - 25 - - - Linux und BSD: Sicherheitslcke in X.org ermglicht Root-Rechte - https://www.golem.de/news/linux-und-bsd-sicherheitsluecke-in-x-org-ermoeglicht-root-rechte-1810-137347-rss.html - Eine Sicherheitslcke im Displayserver X.org erlaubt unter bestimmten Umstnden das berschreiben von Dateien und das Ausweiten der Benutzerrechte. Der passende Exploit passt in einen Tweet. (<a href="https://www.golem.de/specials/sicherheitsluecke/">Sicherheitslcke</a>, <a href="https://www.golem.de/specials/openbsd/">OpenBSD</a>) <img src="https://cpx.golem.de/cpx.php?class=17&amp;aid=137347&amp;page=1&amp;ts=1540564620" alt="" width="1" height="1" /> - https://forum.golem.de/kommentare/security/linux-und-bsd-sicherheitsluecke-in-x.org-ermoeglicht-root-rechte/121569,list.html - Fri, 26 Oct 2018 15:37:00 +0100 - https://www.golem.de/1810/137347-rss.html - Eine Sicherheitslcke im Displayserver X.org erlaubt unter bestimmten Umstnden das berschreiben von Dateien und das Ausweiten der Benutzerrechte. Der passende Exploit passt in einen Tweet. (Sicherheitslcke, OpenBSD) ]]> - 47 - - - Augsburg: Fujitsu Deutschland macht alles dicht - https://www.golem.de/news/augsburg-fujitsu-deutschland-macht-alles-dicht-1810-137348-rss.html - Fujitsu will seine gesamte Fertigung auerhalb Japans schlieen. In Deutschland ist der Standort in Augsburg komplett betroffen. (<a href="https://www.golem.de/specials/fujitsu/">Fujitsu</a>, <a href="https://www.golem.de/specials/sap/">SAP</a>) <img src="https://cpx.golem.de/cpx.php?class=17&amp;aid=137348&amp;page=1&amp;ts=1540562340" alt="" width="1" height="1" /> - https://forum.golem.de/kommentare/wirtschaft/augsburg-fujitsu-deutschland-macht-alles-dicht/121568,list.html - Fri, 26 Oct 2018 14:59:00 +0100 - https://www.golem.de/1810/137348-rss.html - Fujitsu will seine gesamte Fertigung auerhalb Japans schlieen. In Deutschland ist der Standort in Augsburg komplett betroffen. (Fujitsu, SAP) ]]> - 56 - - - Bundesnetzagentur: Seehofer fordert Verschiebung von 5G-Auktion - https://www.golem.de/news/bundesnetzagentur-seehofer-fordert-verschiebung-von-5g-auktion-1810-137346-rss.html - Bundesinnenminister Horst Seehofer will die 5G-Auktion verschieben, bis die lndlichen Regionen besser bercksichtigt werden. Er wird von einer Gruppe um den CDU-Abgeordneten Stefan Rouenhoff untersttzt. (<a href="https://www.golem.de/specials/5g/">5G</a>, <a href="https://www.golem.de/specials/bundesnetzagentur/">Bundesnetzagentur</a>) <img src="https://cpx.golem.de/cpx.php?class=17&amp;aid=137346&amp;page=1&amp;ts=1540557900" alt="" width="1" height="1" /> - https://forum.golem.de/kommentare/handy/bundesnetzagentur-seehofer-fordert-verschiebung-von-5g-auktion/121567,list.html - Fri, 26 Oct 2018 13:45:00 +0100 - https://www.golem.de/1810/137346-rss.html - Bundesinnenminister Horst Seehofer will die 5G-Auktion verschieben, bis die lndlichen Regionen besser bercksichtigt werden. Er wird von einer Gruppe um den CDU-Abgeordneten Stefan Rouenhoff untersttzt. (5G, Bundesnetzagentur) ]]> - 14 - - - Linux und Patente: Open Source bei Microsoft ist "Kultur statt Strategie" - https://www.golem.de/news/linux-und-patente-open-source-bei-microsoft-ist-kultur-statt-strategie-1810-137345-rss.html - Der Microsoft-Angestellte Stephen Walli beschreibt den Wandel bei Microsoft hin zu Open Source Software und Linux als kulturell getrieben. Mit Blick auf den Beitritt zu dem Patentpool des Open Invention Network zeigt sich jedoch auch, dass das Unternehmen noch sehr viel Arbeit vor sich hat. Ein Bericht von Sebastian Grner (<a href="https://www.golem.de/specials/microsoft/">Microsoft</a>, <a href="https://www.golem.de/specials/softwarepatente/">Softwarepatent</a>) <img src="https://cpx.golem.de/cpx.php?class=17&amp;aid=137345&amp;page=1&amp;ts=1540556820" alt="" width="1" height="1" /> - https://forum.golem.de/kommentare/politik-recht/linux-und-patente-open-source-bei-microsoft-ist-kultur-statt-strategie/121566,list.html - Fri, 26 Oct 2018 13:27:00 +0100 - https://www.golem.de/1810/137345-rss.html - Der Microsoft-Angestellte Stephen Walli beschreibt den Wandel bei Microsoft hin zu Open Source Software und Linux als kulturell getrieben. Mit Blick auf den Beitritt zu dem Patentpool des Open Invention Network zeigt sich jedoch auch, dass das Unternehmen noch sehr viel Arbeit vor sich hat. Ein Bericht von Sebastian Grner (Microsoft, Softwarepatent) ]]> - 20 - - - Sicherheitslcke: Daten von 185.000 weiteren British-Airways-Kunden betroffen - https://www.golem.de/news/sicherheitsluecke-daten-von-185-000-weiteren-british-airways-kunden-betroffen-1810-137344-rss.html - Von dem Datenleck im Buchungssystem von British Airways waren deutlich mehr Kunden betroffen als bisher bekannt. Die Fluggesellschaft rt betroffenen Kunden, ihre Bank zu kontaktieren. Kreditkarten werden in diesem Fall hufig komplett ausgetauscht. (<a href="https://www.golem.de/specials/sicherheitsluecke/">Sicherheitslcke</a>, <a href="https://www.golem.de/specials/datenschutz/">Datenschutz</a>) <img src="https://cpx.golem.de/cpx.php?class=17&amp;aid=137344&amp;page=1&amp;ts=1540553820" alt="" width="1" height="1" /> - https://forum.golem.de/kommentare/security/sicherheitsluecke-daten-von-185.000-weiteren-british-airways-kunden-betroffen/121565,list.html - Fri, 26 Oct 2018 12:37:00 +0100 - https://www.golem.de/1810/137344-rss.html - Von dem Datenleck im Buchungssystem von British Airways waren deutlich mehr Kunden betroffen als bisher bekannt. Die Fluggesellschaft rt betroffenen Kunden, ihre Bank zu kontaktieren. Kreditkarten werden in diesem Fall hufig komplett ausgetauscht. (Sicherheitslcke, Datenschutz) ]]> - - - - iPhone Xr im Test: Apples gnstigeres iPhone ist nicht gnstig - https://www.golem.de/news/iphone-xr-im-test-apples-guenstiges-iphone-ist-nicht-guenstig-1810-137327-rss.html - Apple versucht es 2018 wieder einmal mit einem relativ preisgnstigen iPhone - weniger teuer als die Xs-Modelle, aber mit 850 Euro auch nicht gerade preiswert. Kufer bekommen dafr allerdings auch ein Smartphone mit sehr guter Ausstattung, in einigen Punkten wurde jedoch auf Hardware der teuren Modelle verzichtet. Ein Test von Tobias Kltzsch (<a href="https://www.golem.de/specials/iphone/">iPhone</a>, <a href="https://www.golem.de/specials/smartphone/">Smartphone</a>) <img src="https://cpx.golem.de/cpx.php?class=17&amp;aid=137327&amp;page=1&amp;ts=1540548180" alt="" width="1" height="1" /> - https://forum.golem.de/kommentare/handy/iphone-xr-im-test-apples-guenstigeres-iphone-ist-nicht-guenstig/121563,list.html - Fri, 26 Oct 2018 11:03:00 +0100 - https://www.golem.de/1810/137327-rss.html - Apple versucht es 2018 wieder einmal mit einem relativ preisgnstigen iPhone - weniger teuer als die Xs-Modelle, aber mit 850 Euro auch nicht gerade preiswert. Kufer bekommen dafr allerdings auch ein Smartphone mit sehr guter Ausstattung, in einigen Punkten wurde jedoch auf Hardware der teuren Modelle verzichtet. Ein Test von Tobias Kltzsch (iPhone, Smartphone) ]]> - 169 - - - Microsoft: PC-Spieleangebot des Xbox Game Pass wird erweitert - https://www.golem.de/news/microsoft-pc-spieleangebot-des-xbox-game-pass-wird-erweitert-1810-137343-rss.html - Der Xbox Game Pass soll knftig um mehr Angebote fr Windows-PC erweitert werden, sagt Microsoft-Chef Satya Nadella. Derzeit gibt es fr 10 Euro nur wenige plattformbergreifend verfgbare Spiele. (<a href="https://www.golem.de/specials/xbox-one/">Xbox One</a>, <a href="https://www.golem.de/specials/microsoft/">Microsoft</a>) <img src="https://cpx.golem.de/cpx.php?class=17&amp;aid=137343&amp;page=1&amp;ts=1540546800" alt="" width="1" height="1" /> - https://forum.golem.de/kommentare/wirtschaft/microsoft-pc-spieleangebot-des-xbox-game-pass-wird-erweitert/121562,list.html - Fri, 26 Oct 2018 10:40:00 +0100 - https://www.golem.de/1810/137343-rss.html - Der Xbox Game Pass soll knftig um mehr Angebote fr Windows-PC erweitert werden, sagt Microsoft-Chef Satya Nadella. Derzeit gibt es fr 10 Euro nur wenige plattformbergreifend verfgbare Spiele. (Xbox One, Microsoft) ]]> - 19 - - - Breitbandgesellschaft: Grne wollen Netzbetreiber zum Ausbau zwingen - https://www.golem.de/news/breitbandgesellschaft-gruene-wollen-netzbetreiber-zum-ausbau-zwingen-1810-137342-rss.html - Die Grnen haben die Netzversorgung in Deutschland analysiert. Die Partei, die zurzeit in Whlerumfragen stark zugewinnt, fordert den Breitbandausbau auf Kosten der Konzerne und will Glasfaser staatlich durchsetzen. (<a href="https://www.golem.de/specials/breitband/">Breitband</a>, <a href="https://www.golem.de/specials/handy/">Handy</a>) <img src="https://cpx.golem.de/cpx.php?class=17&amp;aid=137342&amp;page=1&amp;ts=1540545840" alt="" width="1" height="1" /> - https://forum.golem.de/kommentare/politik-recht/breitbandgesellschaft-gruene-wollen-netzbetreiber-zum-ausbau-zwingen/121561,list.html - Fri, 26 Oct 2018 10:24:00 +0100 - https://www.golem.de/1810/137342-rss.html - Die Grnen haben die Netzversorgung in Deutschland analysiert. Die Partei, die zurzeit in Whlerumfragen stark zugewinnt, fordert den Breitbandausbau auf Kosten der Konzerne und will Glasfaser staatlich durchsetzen. (Breitband, Handy) ]]> - 22 - - - Studie: Silicon Valley dient als rechte Hand des groen Bruders - https://www.golem.de/news/studie-silicon-valley-dient-als-rechte-hand-des-grossen-bruders-1810-137316-rss.html - Die US-Hightech-Branche verdingt sich zunehmend als technischer Dienstleister fr staatliche Big-Brother-Projekte wie die berwachung und Abschiebung von Immigranten, heit es in einem Bericht von Brgerrechtlern. Amazon und Palantir verdienten damit am meisten. Von Stefan Krempl (<a href="https://www.golem.de/specials/datenschutz/">Datenschutz</a>, <a href="https://www.golem.de/specials/ibm/">IBM</a>) <img src="https://cpx.golem.de/cpx.php?class=17&amp;aid=137316&amp;page=1&amp;ts=1540543080" alt="" width="1" height="1" /> - https://forum.golem.de/kommentare/security/studie-silicon-valley-dient-als-rechte-hand-des-grossen-bruders/121560,list.html - Fri, 26 Oct 2018 09:38:00 +0100 - https://www.golem.de/1810/137316-rss.html - Die US-Hightech-Branche verdingt sich zunehmend als technischer Dienstleister fr staatliche Big-Brother-Projekte wie die berwachung und Abschiebung von Immigranten, heit es in einem Bericht von Brgerrechtlern. Amazon und Palantir verdienten damit am meisten. Von Stefan Krempl (Datenschutz, IBM) ]]> - 20 - - - Bethesda: Postnukleare PC-Systemanforderungen fr Fallout 76 - https://www.golem.de/news/bethesda-postnukleare-pc-systemanforderungen-fuer-fallout-76-1810-137340-rss.html - Kurz vor dem Start der Betaversion fr PC-Spieler hat Bethesda die Systemanforderung von Fallout 76 verffentlicht. Hoffnungen auf lange Abenteuer in der Vorabversion gibt es aber zumindest nach den Erfahrungen des Xbox-Zugangs eher nicht. (<a href="https://www.golem.de/specials/fallout-76/">Fallout 76</a>, <a href="https://www.golem.de/specials/rollenspiel/">Rollenspiel</a>) <img src="https://cpx.golem.de/cpx.php?class=17&amp;aid=137340&amp;page=1&amp;ts=1540542180" alt="" width="1" height="1" /> - https://forum.golem.de/kommentare/games/bethesda-postnukleare-pc-systemanforderungen-fuer-fallout-76/121559,list.html - Fri, 26 Oct 2018 09:23:00 +0100 - https://www.golem.de/1810/137340-rss.html - Kurz vor dem Start der Betaversion fr PC-Spieler hat Bethesda die Systemanforderung von Fallout 76 verffentlicht. Hoffnungen auf lange Abenteuer in der Vorabversion gibt es aber zumindest nach den Erfahrungen des Xbox-Zugangs eher nicht. (Fallout 76, Rollenspiel) ]]> - 101 - - - Quartalszahlen: Intel legt 19-Milliarden-USD-Rekord vor - https://www.golem.de/news/quartalszahlen-intel-legt-19-milliarden-usd-rekord-vor-1810-137339-rss.html - Ungeachtet der 14-nm-Knappheit und diverser Sicherheitslcken konnte Intel im dritten Quartal 2018 mehr Umsatz erwirtschaften und mehr Gewinn erzielen als jemals zuvor. Vor allem das florierende Server-Geschft wird bei Intel immer wichtiger. (<a href="https://www.golem.de/specials/intel/">Intel</a>, <a href="https://www.golem.de/specials/cpu/">Prozessor</a>) <img src="https://cpx.golem.de/cpx.php?class=17&amp;aid=137339&amp;page=1&amp;ts=1540540260" alt="" width="1" height="1" /> - https://forum.golem.de/kommentare/wirtschaft/quartalszahlen-intel-legt-19-milliarden-usd-rekord-vor/121558,list.html - Fri, 26 Oct 2018 08:51:00 +0100 - https://www.golem.de/1810/137339-rss.html - Ungeachtet der 14-nm-Knappheit und diverser Sicherheitslcken konnte Intel im dritten Quartal 2018 mehr Umsatz erwirtschaften und mehr Gewinn erzielen als jemals zuvor. Vor allem das florierende Server-Geschft wird bei Intel immer wichtiger. (Intel, Prozessor) ]]> - 10 - - - Physik: Weg mit der Schnheit! - https://www.golem.de/news/physik-weg-mit-der-schoenheit-1810-137161-rss.html - Ist eine Theorie richtig, nur weil sie schn ist? Nein, sagt Sabine Hossenfelder. In ihrem Buch "Das hssliche Universum" zeigt die theoretische Physikerin, wie das Schnheitsdenken die Wissenschaft lhmt und erklrt dabei recht unterhaltsam die unterschiedlichen Theorien und Modelle der Teilchenphysik. Eine Rezension von Friedemann Zweynert (<a href="https://www.golem.de/specials/physik/">Physik</a>, <a href="https://www.golem.de/specials/internet/">Internet</a>) <img src="https://cpx.golem.de/cpx.php?class=17&amp;aid=137161&amp;page=1&amp;ts=1540537380" alt="" width="1" height="1" /> - https://forum.golem.de/kommentare/internet/physik-weg-mit-der-schoenheit/121557,list.html - Fri, 26 Oct 2018 08:03:00 +0100 - https://www.golem.de/1810/137161-rss.html - Ist eine Theorie richtig, nur weil sie schn ist? Nein, sagt Sabine Hossenfelder. In ihrem Buch "Das hssliche Universum" zeigt die theoretische Physikerin, wie das Schnheitsdenken die Wissenschaft lhmt und erklrt dabei recht unterhaltsam die unterschiedlichen Theorien und Modelle der Teilchenphysik. Eine Rezension von Friedemann Zweynert (Physik, Internet) ]]> - 86 - - - Elon Musk: Teslas Model 3 fr 35.000 US-Dollar derzeit unmglich - https://www.golem.de/news/elon-musk-teslas-model-3-fuer-35-000-us-dollar-derzeit-unmoeglich-1810-137335-rss.html - Tesla-Chef Elon Musk hat eingerumt, das bei 35.000 US-Dollar startende Basismodell des Elektroautos Model 3 immer noch nicht liefern zu knnen. (<a href="https://www.golem.de/specials/tesla-model-3/">Tesla Model 3</a>, <a href="https://www.golem.de/specials/technologie/">Technologie</a>) <img src="https://cpx.golem.de/cpx.php?class=17&amp;aid=137335&amp;page=1&amp;ts=1540533540" alt="" width="1" height="1" /> - https://forum.golem.de/kommentare/automobil/elon-musk-teslas-model-3-fuer-35.000-us-dollar-derzeit-unmoeglich/121556,list.html - Fri, 26 Oct 2018 06:59:00 +0100 - https://www.golem.de/1810/137335-rss.html - Tesla-Chef Elon Musk hat eingerumt, das bei 35.000 US-Dollar startende Basismodell des Elektroautos Model 3 immer noch nicht liefern zu knnen. (Tesla Model 3, Technologie) ]]> - 235 - - - Solarzellen als Dach: Tesla-Solarschindeln verzgern sich bis 2019 - https://www.golem.de/news/solarzellen-als-dach-tesla-solarschindeln-verzoegern-sich-auf-2019-1810-137334-rss.html - Tesla wird die Serienproduktion seiner Solardachziegel nicht mehr wie geplant in diesem Jahr starten. Nach Angaben von Firmenchef Elon Musk verschiebt sich das Vorhaben auf 2019. (<a href="https://www.golem.de/specials/solarenergie/">Solarenergie</a>, <a href="https://www.golem.de/specials/technologie/">Technologie</a>) <img src="https://cpx.golem.de/cpx.php?class=17&amp;aid=137334&amp;page=1&amp;ts=1540532460" alt="" width="1" height="1" /> - https://forum.golem.de/kommentare/wissenschaft/solarzellen-als-dach-tesla-solarschindeln-verzoegern-sich-bis-2019/121555,list.html - Fri, 26 Oct 2018 06:41:00 +0100 - https://www.golem.de/1810/137334-rss.html - Tesla wird die Serienproduktion seiner Solardachziegel nicht mehr wie geplant in diesem Jahr starten. Nach Angaben von Firmenchef Elon Musk verschiebt sich das Vorhaben auf 2019. (Solarenergie, Technologie) ]]> - 47 - - - Uniti One: Elektroauto fr 15.000 Euro wird in Grobritannien gebaut - https://www.golem.de/news/uniti-one-elektroauto-fuer-15-000-euro-wird-in-grossbritannien-gebaut-1810-137333-rss.html - Das schwedische Unternehmen Uniti will sein Elektroauto One in Grobritannien bauen. Einen fahrenden Prototyp des Uniti One gibt es schon. Das Auto soll je nach Modell fr 15.000 bis 20.000 Euro auf den Markt kommen. (<a href="https://www.golem.de/specials/elektroauto/">Elektroauto</a>, <a href="https://www.golem.de/specials/technologie/">Technologie</a>) <img src="https://cpx.golem.de/cpx.php?class=17&amp;aid=137333&amp;page=1&amp;ts=1540531080" alt="" width="1" height="1" /> - https://forum.golem.de/kommentare/automobil/uniti-one-elektroauto-fuer-15.000-euro-wird-in-grossbritannien-gebaut/121554,list.html - Fri, 26 Oct 2018 06:18:00 +0100 - https://www.golem.de/1810/137333-rss.html - Das schwedische Unternehmen Uniti will sein Elektroauto One in Grobritannien bauen. Einen fahrenden Prototyp des Uniti One gibt es schon. Das Auto soll je nach Modell fr 15.000 bis 20.000 Euro auf den Markt kommen. (Elektroauto, Technologie) ]]> - 28 - - - Quartalsbericht: Alphabet macht in drei Monaten 9,2 Milliarden Dollar Gewinn - https://www.golem.de/news/quartalsbericht-alphabet-macht-in-drei-monaten-9-2-milliarden-dollar-gewinn-1810-137337-rss.html - Alphabet erwirtschaftet weiter extrem hohe Gewinne, der Umsatz wchst nicht ganz so stark. Google muss zugleich auf eine Enthllung in der US-Presse zu sexueller Belstigung um Android-Begrnder Andy Rubin reagieren. (<a href="https://www.golem.de/specials/google/">Google</a>, <a href="https://www.golem.de/specials/boerse/">Brse</a>) <img src="https://cpx.golem.de/cpx.php?class=17&amp;aid=137337&amp;page=1&amp;ts=1540504320" alt="" width="1" height="1" /> - https://forum.golem.de/kommentare/wirtschaft/quartalsbericht-alphabet-macht-in-drei-monaten-9-2-milliarden-dollar-gewinn/121553,list.html - Thu, 25 Oct 2018 22:52:00 +0100 - https://www.golem.de/1810/137337-rss.html - Alphabet erwirtschaftet weiter extrem hohe Gewinne, der Umsatz wchst nicht ganz so stark. Google muss zugleich auf eine Enthllung in der US-Presse zu sexueller Belstigung um Android-Begrnder Andy Rubin reagieren. (Google, Brse) ]]> - 12 - - - Quartalsbericht: Amazon verfehlt die Umsatzprognosen - https://www.golem.de/news/quartalsbericht-amazon-verfehlt-die-umsatzprognosen-1810-137336-rss.html - Amazon weist erneut einen hohen Gewinn aus. Doch der Konzern lag beim Umsatz unter den Prognosen der Analysten. (<a href="https://www.golem.de/specials/amazon/">Amazon</a>, <a href="https://www.golem.de/specials/onlineshop/">Onlineshop</a>) <img src="https://cpx.golem.de/cpx.php?class=17&amp;aid=137336&amp;page=1&amp;ts=1540500780" alt="" width="1" height="1" /> - https://forum.golem.de/kommentare/wirtschaft/quartalsbericht-amazon-verfehlt-die-umsatzprognosen/121552,list.html - Thu, 25 Oct 2018 21:53:00 +0100 - https://www.golem.de/1810/137336-rss.html - Amazon weist erneut einen hohen Gewinn aus. Doch der Konzern lag beim Umsatz unter den Prognosen der Analysten. (Amazon, Onlineshop) ]]> - 24 - - - Datenskandal: Britische Datenschutzbehrde verurteilt Facebook - https://www.golem.de/news/datenskandal-britische-datenschutzbehoerde-verurteilt-facebook-1810-137332-rss.html - Im Skandal um Cambridge Analytica hat die britische Datenschutzbehrde die Hchststrafe von 500.000 Pfund verhngt. Facebook habe einen schweren Versto gegen geltendes Recht zugelassen. (<a href="https://www.golem.de/specials/facebook/">Facebook</a>, <a href="https://www.golem.de/specials/socialnetwork/">Soziales Netz</a>) <img src="https://cpx.golem.de/cpx.php?class=17&amp;aid=137332&amp;page=1&amp;ts=1540483080" alt="" width="1" height="1" /> - https://forum.golem.de/kommentare/security/datenskandal-britische-datenschutzbehoerde-verurteilt-facebook/121550,list.html - Thu, 25 Oct 2018 16:58:00 +0100 - https://www.golem.de/1810/137332-rss.html - Im Skandal um Cambridge Analytica hat die britische Datenschutzbehrde die Hchststrafe von 500.000 Pfund verhngt. Facebook habe einen schweren Versto gegen geltendes Recht zugelassen. (Facebook, Soziales Netz) ]]> - 35 - - - Corsair: Neue K70 MK.2 kommt mit Cherrys Low-Profile-Switches - https://www.golem.de/news/corsair-neue-k70-mk-2-kommt-mit-cherrys-low-profile-switches-1810-137331-rss.html - Corsair erweitert sein Tastaturportefeuille um zwei Gaming-Tastaturen mit Cherrys flachen Low-Profile-Switches. Ein Modell hat Schalter mit einem besonders kurzem Auslseweg von 1 mm - die Schalter darf Corsair exklusiv verwenden. (<a href="https://www.golem.de/specials/corsair/">Corsair</a>, <a href="https://www.golem.de/specials/eingabegeraet/">Eingabegert</a>) <img src="https://cpx.golem.de/cpx.php?class=17&amp;aid=137331&amp;page=1&amp;ts=1540480320" alt="" width="1" height="1" /> - https://forum.golem.de/kommentare/sonstiges/corsair-neue-k70-mk.2-kommt-mit-cherrys-low-profile-switches/121549,list.html - Thu, 25 Oct 2018 16:12:00 +0100 - https://www.golem.de/1810/137331-rss.html - Corsair erweitert sein Tastaturportefeuille um zwei Gaming-Tastaturen mit Cherrys flachen Low-Profile-Switches. Ein Modell hat Schalter mit einem besonders kurzem Auslseweg von 1 mm - die Schalter darf Corsair exklusiv verwenden. (Corsair, Eingabegert) ]]> - 19 - - - Cambridge-Analytica-Skandal: EU-Parlament fordert schrfere Kontrolle von Facebook - https://www.golem.de/news/cambridge-analytica-skandal-eu-parlament-fordert-schaerfere-kontrolle-von-facebook-1810-137329-rss.html - Die EU-Abgeordneten haben als Reaktion auf die Datenschutzverste von Facebook und Cambridge Analytica Behrden angehalten, ihre Aktivitten auf dem Netzwerk zu berdenken. Profiling zu politischen Zwecken wollen sie verbieten. Von Stefan Krempl (<a href="https://www.golem.de/specials/facebook/">Facebook</a>, <a href="https://www.golem.de/specials/socialnetwork/">Soziales Netz</a>) <img src="https://cpx.golem.de/cpx.php?class=17&amp;aid=137329&amp;page=1&amp;ts=1540479120" alt="" width="1" height="1" /> - https://forum.golem.de/kommentare/security/cambridge-analytica-skandal-eu-parlament-fordert-schaerfere-kontrolle-von-facebook/121548,list.html - Thu, 25 Oct 2018 15:52:00 +0100 - https://www.golem.de/1810/137329-rss.html - Die EU-Abgeordneten haben als Reaktion auf die Datenschutzverste von Facebook und Cambridge Analytica Behrden angehalten, ihre Aktivitten auf dem Netzwerk zu berdenken. Profiling zu politischen Zwecken wollen sie verbieten. Von Stefan Krempl (Facebook, Soziales Netz) ]]> - 3 - - - Kuriosum: Das Hellgate London ffnet sich mal wieder - https://www.golem.de/news/kuriosum-das-hellgate-london-oeffnet-sich-mal-wieder-1810-137328-rss.html - Einer der groen Trash-Klassiker der Spielegeschichte wagt einen neuen Anlauf: Mitte November 2018 soll ein neue, fr Einzelspieler ausgelegte Windows-Fassung von Hellgate London erscheinen. Das Ursprungskonzept hatten sich ehemalige Blizzard-Chefentwickler ausgedacht. (<a href="https://www.golem.de/specials/rollenspiel/">Rollenspiel</a>, <a href="https://www.golem.de/specials/steam/">Steam</a>) <img src="https://cpx.golem.de/cpx.php?class=17&amp;aid=137328&amp;page=1&amp;ts=1540476600" alt="" width="1" height="1" /> - https://forum.golem.de/kommentare/games/kuriosum-das-hellgate-london-oeffnet-sich-mal-wieder/121547,list.html - Thu, 25 Oct 2018 15:10:00 +0100 - https://www.golem.de/1810/137328-rss.html - Einer der groen Trash-Klassiker der Spielegeschichte wagt einen neuen Anlauf: Mitte November 2018 soll ein neue, fr Einzelspieler ausgelegte Windows-Fassung von Hellgate London erscheinen. Das Ursprungskonzept hatten sich ehemalige Blizzard-Chefentwickler ausgedacht. (Rollenspiel, Steam) ]]> - 61 - - - Tweether: 10 GBit/s ber einen Quadratkilometer verteilt - https://www.golem.de/news/tweether-10-gbit-s-ueber-einen-quadratkilometer-verteilt-1810-137326-rss.html - Eine neue Technologie verteilt 10 GBit/s ber eine groe Flche. Der erste Feldversuch ist erfolgreich verlaufen. Zum ersten Mal wurde ein stabiles drahtloses Netzwerk bei diesen Frequenzen und mit diesen Datenraten betrieben. (<a href="https://www.golem.de/specials/wissenschaft/">Wissenschaft</a>, <a href="https://www.golem.de/specials/mobil/">Mobil</a>) <img src="https://cpx.golem.de/cpx.php?class=17&amp;aid=137326&amp;page=1&amp;ts=1540475400" alt="" width="1" height="1" /> - https://forum.golem.de/kommentare/wissenschaft/tweether-10-gbit-s-ueber-einen-quadratkilometer-verteilt/121546,list.html - Thu, 25 Oct 2018 14:50:00 +0100 - https://www.golem.de/1810/137326-rss.html - Eine neue Technologie verteilt 10 GBit/s ber eine groe Flche. Der erste Feldversuch ist erfolgreich verlaufen. Zum ersten Mal wurde ein stabiles drahtloses Netzwerk bei diesen Frequenzen und mit diesen Datenraten betrieben. (Wissenschaft, Mobil) ]]> - 20 - - - Red Dead Redemption 2: Saloon-Prgelei (der Worte) im Livestream - https://www.golem.de/news/red-dead-redemption-2-saloon-pruegelei-der-worte-im-livestream-1810-137312-rss.html - Die Golem.de-Redakteure Peter Steinlechner und Michael Wieczorek diskutieren gemeinsam mit unserer Community ber den Test zu Red Dead Redemption 2 live ab 18 Uhr. (<a href="https://www.golem.de/specials/red-dead-redemption-2/">Red Dead Redemption 2</a>, <a href="https://www.golem.de/specials/spieletest/">Spieletest</a>) <img src="https://cpx.golem.de/cpx.php?class=17&amp;aid=137312&amp;page=1&amp;ts=1540474200" alt="" width="1" height="1" /> - https://forum.golem.de/kommentare/games/red-dead-redemption-2-saloon-pruegelei-der-worte-im-livestream/121545,list.html - Thu, 25 Oct 2018 14:30:00 +0100 - https://www.golem.de/1810/137312-rss.html - Die Golem.de-Redakteure Peter Steinlechner und Michael Wieczorek diskutieren gemeinsam mit unserer Community ber den Test zu Red Dead Redemption 2 live ab 18 Uhr. (Red Dead Redemption 2, Spieletest) ]]> - - - - Wolf Intelligence: Trojanerfirma aus Deutschland lsst interne Daten im Netz - https://www.golem.de/news/wolf-intelligence-trojanerfirma-aus-deutschland-laesst-interne-daten-im-netz-1810-137323-rss.html - Wolf Intelligence verkauft Schadsoftware an Staaten. Eine Sicherheitsfirma hat sensible Daten des Unternehmens ffentlich zugnglich im Internet gefunden. In einer Prsentation wurden die Funde gezeigt. (<a href="https://www.golem.de/specials/trojaner/">Trojaner</a>, <a href="https://www.golem.de/specials/virus/">Virus</a>) <img src="https://cpx.golem.de/cpx.php?class=17&amp;aid=137323&amp;page=1&amp;ts=1540472400" alt="" width="1" height="1" /> - https://forum.golem.de/kommentare/security/wolf-intelligence-trojanerfirma-aus-deutschland-laesst-interne-daten-im-netz/121543,list.html - Thu, 25 Oct 2018 14:00:00 +0100 - https://www.golem.de/1810/137323-rss.html - Wolf Intelligence verkauft Schadsoftware an Staaten. Eine Sicherheitsfirma hat sensible Daten des Unternehmens ffentlich zugnglich im Internet gefunden. In einer Prsentation wurden die Funde gezeigt. (Trojaner, Virus) ]]> - 16 - - - NBN: Der Top-Nutzer verwendet 24 TByte im Monat - https://www.golem.de/news/nbn-der-top-nutzer-verwendet-24-tbyte-im-monat-1810-137324-rss.html - Ein staatliches FTTH-Netzwerk fr fast alle in Australien bis 2017 war einst das Ziel. Doch davon ist beim (NBN) National Broadband Network nicht mehr viel brig geblieben. In Berlin wurde eine Zwischenbilanz gezogen. (<a href="https://www.golem.de/specials/festnetz/">Festnetz</a>, <a href="https://www.golem.de/specials/dsl/">DSL</a>) <img src="https://cpx.golem.de/cpx.php?class=17&amp;aid=137324&amp;page=1&amp;ts=1540471380" alt="" width="1" height="1" /> - https://forum.golem.de/kommentare/internet/nbn-der-top-nutzer-verwendet-24-tbyte-im-monat/121542,list.html - Thu, 25 Oct 2018 13:43:00 +0100 - https://www.golem.de/1810/137324-rss.html - Ein staatliches FTTH-Netzwerk fr fast alle in Australien bis 2017 war einst das Ziel. Doch davon ist beim (NBN) National Broadband Network nicht mehr viel brig geblieben. In Berlin wurde eine Zwischenbilanz gezogen. (Festnetz, DSL) ]]> - 51 - - - Linux-Kernel: Mit Machine Learning auf der Suche nach Bug-Fixes - https://www.golem.de/news/linux-kernel-mit-machine-learning-auf-der-suche-nach-bug-fixes-1810-137321-rss.html - Wichtige Patches, die in stabilen Kernel-Versionen landen sollten, werden von der Linux-Community oft vergessen oder bersehen. Abhilfe schaffen soll offenbar Machine Learning, wie die Entwickler Sasha Levin und Julia Lawall erklren. (<a href="https://www.golem.de/specials/linux-kernel/">Linux-Kernel</a>, <a href="https://www.golem.de/specials/linux/">Linux</a>) <img src="https://cpx.golem.de/cpx.php?class=17&amp;aid=137321&amp;page=1&amp;ts=1540468800" alt="" width="1" height="1" /> - https://forum.golem.de/kommentare/security/linux-kernel-mit-machine-learning-auf-der-suche-nach-bug-fixes/121541,list.html - Thu, 25 Oct 2018 13:00:00 +0100 - https://www.golem.de/1810/137321-rss.html - Wichtige Patches, die in stabilen Kernel-Versionen landen sollten, werden von der Linux-Community oft vergessen oder bersehen. Abhilfe schaffen soll offenbar Machine Learning, wie die Entwickler Sasha Levin und Julia Lawall erklren. (Linux-Kernel, Linux) ]]> - 4 - - - Quartalszahlen: AMDs Aktie gibt wegen miger Aussichten nach - https://www.golem.de/news/quartalszahlen-amds-aktie-gibt-wegen-maessiger-aussichten-nach-1810-137320-rss.html - Im dritten Quartal 2018 konnte AMD zwar Umsatz und Gewinn steigern, aber nicht so stark wie erwartet. Die Aktie brach dennoch von ber 25 US-Dollar auf 17 US-Dollar ein, da das vierte Quartal schlechter laufen wird als von den Anlegern gedacht - hier wurde zu viel erwartet. (<a href="https://www.golem.de/specials/amd/">AMD</a>, <a href="https://www.golem.de/specials/cpu/">Prozessor</a>) <img src="https://cpx.golem.de/cpx.php?class=17&amp;aid=137320&amp;page=1&amp;ts=1540467600" alt="" width="1" height="1" /> - https://forum.golem.de/kommentare/wirtschaft/quartalszahlen-amds-aktie-gibt-wegen-maessiger-aussichten-nach/121540,list.html - Thu, 25 Oct 2018 12:40:00 +0100 - https://www.golem.de/1810/137320-rss.html - Im dritten Quartal 2018 konnte AMD zwar Umsatz und Gewinn steigern, aber nicht so stark wie erwartet. Die Aktie brach dennoch von ber 25 US-Dollar auf 17 US-Dollar ein, da das vierte Quartal schlechter laufen wird als von den Anlegern gedacht - hier wurde zu viel erwartet. (AMD, Prozessor) ]]> - 17 - - - Projekt Broadband: Bahn will 3,5 Milliarden Euro vom Bund fr Glasfasernetz - https://www.golem.de/news/projekt-broadband-bahn-will-3-5-milliarden-euro-vom-bund-fuer-glasfasernetz-1810-137322-rss.html - Die Plne fr das eigene Glasfasernetz der Deutschen Bahn werden konkret. ber die Finanzierung redet man jetzt mit der Regierung. Das Netz soll schnell gebaut werden. (<a href="https://www.golem.de/specials/deutsche-bahn/">Deutsche Bahn</a>, <a href="https://www.golem.de/specials/umts/">UMTS</a>) <img src="https://cpx.golem.de/cpx.php?class=17&amp;aid=137322&amp;page=1&amp;ts=1540466580" alt="" width="1" height="1" /> - https://forum.golem.de/kommentare/internet/projekt-broadband-bahn-will-3-5-milliarden-euro-vom-bund-fuer-glasfasernetz/121539,list.html - Thu, 25 Oct 2018 12:23:00 +0100 - https://www.golem.de/1810/137322-rss.html - Die Plne fr das eigene Glasfasernetz der Deutschen Bahn werden konkret. ber die Finanzierung redet man jetzt mit der Regierung. Das Netz soll schnell gebaut werden. (Deutsche Bahn, UMTS) ]]> - 31 - - - Red Dead Redemption 2 im Test: Der Revolverhelden-Simulator - https://www.golem.de/news/red-dead-redemption-2-im-test-der-revolverhelden-simulator-1810-137304-rss.html - Reiten, prgeln, kochen, jagen, schieen, bse sein oder (relativ) brav: In Red Dead Redemption 2 gibt es enorme Mglichkeiten, sich als Revolverheld in einer wunderschnen Westernwelt auszuleben. Das Actionspiel von Rockstar Games ist ein groer Spa - aber nicht ganz so gut wie GTA 5. Von Peter Steinlechner (<a href="https://www.golem.de/specials/red-dead-redemption-2/">Red Dead Redemption 2</a>, <a href="https://www.golem.de/specials/spieletest/">Spieletest</a>) <img src="https://cpx.golem.de/cpx.php?class=17&amp;aid=137304&amp;page=1&amp;ts=1540465260" alt="" width="1" height="1" /> - https://forum.golem.de/kommentare/games/red-dead-redemption-2-im-test-der-revolverhelden-simulator/121537,list.html - Thu, 25 Oct 2018 12:01:00 +0100 - https://www.golem.de/1810/137304-rss.html - Reiten, prgeln, kochen, jagen, schieen, bse sein oder (relativ) brav: In Red Dead Redemption 2 gibt es enorme Mglichkeiten, sich als Revolverheld in einer wunderschnen Westernwelt auszuleben. Das Actionspiel von Rockstar Games ist ein groer Spa - aber nicht ganz so gut wie GTA 5. Von Peter Steinlechner (Red Dead Redemption 2, Spieletest) ]]> - 107 - - - Xiaomi: Das Mi Mix 3 hat keine Notch und eine versteckte Frontkamera - https://www.golem.de/news/xiaomi-das-mi-mix-3-hat-keine-notch-und-eine-versteckte-frontkamera-1810-137319-rss.html - Das Display von Xiaomis angekndigtem Smartphone Mi Mix 3 ist nahezu randlos. Die Frontkamera versteckt das Gert hinter der aufschiebbaren Schale. Neu ist zudem, dass Xiaomi ein OLED-Panel verbaut und wieder den Qi-Ladestandard nutzt. (<a href="https://www.golem.de/specials/xiaomi/">Xiaomi</a>, <a href="https://www.golem.de/specials/smartphone/">Smartphone</a>) <img src="https://cpx.golem.de/cpx.php?class=17&amp;aid=137319&amp;page=1&amp;ts=1540464540" alt="" width="1" height="1" /> - https://forum.golem.de/kommentare/handy/xiaomi-das-mi-mix-3-hat-keine-notch-und-eine-versteckte-frontkamera/121536,list.html - Thu, 25 Oct 2018 11:49:00 +0100 - https://www.golem.de/1810/137319-rss.html - Das Display von Xiaomis angekndigtem Smartphone Mi Mix 3 ist nahezu randlos. Die Frontkamera versteckt das Gert hinter der aufschiebbaren Schale. Neu ist zudem, dass Xiaomi ein OLED-Panel verbaut und wieder den Qi-Ladestandard nutzt. (Xiaomi, Smartphone) ]]> - 125 - - - diff --git a/internal/http/client/testdata/content-type-only-win-8859-1.xml b/internal/http/client/testdata/content-type-only-win-8859-1.xml deleted file mode 100644 index 06e28e42..00000000 --- a/internal/http/client/testdata/content-type-only-win-8859-1.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - Flux RSS du magazine de psychologie Le Cercle Psy - https://le-cercle-psy.scienceshumaines.com/rss - Flux RSS du magazine de psychologie Le Cercle Psy, le magazine de toutes les psychologies. - Le Cercle Psy - - - Perturbateurs endocriniens : quels effets sur le cerveau ? - https://le-cercle-psy.scienceshumaines.com/perturbateurs-endocriniens-quels-effets-sur-le-cerveau_sh_39995 - Wed, 17 Oct 2018 10:30:00 GMT - Si leur impact semble discret au premier abord, nombre d'tudes montrent que les perturbateurs endocriniens pourraient tre l'origine de troubles neuro-dveloppementaux chez l'enfant. - - - - Masters en Psycho: une simplificationet#8230; trs complexe - https://le-cercle-psy.scienceshumaines.com/masters-en-psycho-une-simplification-tres-complexe_sh_40065 - Wed, 17 Oct 2018 10:30:00 GMT - Une nouvelle nomenclature adopte en 2014 a voulu simplifier les options proposes aux tudiants en Master de Psychologie. Mais on en revient des choix aussi illisibles qu'auparavant ! - - - - La criminalit lie surtout ... l'ennui ? - https://le-cercle-psy.scienceshumaines.com/la-criminalite-liee-surtout-a-l-ennui_sh_39986 - Wed, 17 Oct 2018 10:30:00 GMT - L'oisivet est mre de tous les vices, dit le proverbe... Certains chercheurs amricains paraissent proches de cette position ! - - - - - - Wed, 17 Oct 2018 10:30:00 GMT - - - - - Caroline Eliacheff : Dolto reste authentiquement subversive - https://le-cercle-psy.scienceshumaines.com/caroline-eliacheff-dolto-reste-authentiquement-subversive_sh_39992 - Wed, 17 Oct 2018 10:30:00 GMT - Franoise Dolto est morte il y a trente ans. D'abord adule par des gnrations de parents et de collgues, on lui a ensuite reproch d'avoir favoris l'mergence d'enfants-rois tyranniques. Et s'il existait une autre voie ? - - - - L'enfant dou : quand trop comprendre... empche parfois de comprendre - https://le-cercle-psy.scienceshumaines.com/l-enfant-doue-quand-trop-comprendre-empeche-parfois-de-comprendre_sh_40004 - Wed, 17 Oct 2018 10:30:00 GMT - On ne le rptera jamais assez: raliser le portrait-robot d'un enfant dou頻, surdou頻, haut potentiel, peu importe la qualification choisie, est vain. Cet ouvrage nous rappelle que chaque facilit, talent, comptence ou mme don, peut s'accompagner d'un versant potentiellement plus problmatique. Mais insistons: potentiellement. - - - - Travail, organisations, emploi : les modles europens - https://le-cercle-psy.scienceshumaines.com/travail-organisations-emploi-les-modeles-europeens_sh_33090 - Wed, 17 Oct 2018 10:30:00 GMT - Les pays europens diffrent en matire de performance, de niveau de chmage et de qualit de vie au travail. Certains pays russissent mieux que d'autres et sont pris comme modles. Comment font-ils? - - - - Migrants : l'urgence thrapeutique - https://le-cercle-psy.scienceshumaines.com/migrants-l-urgence-therapeutique_sh_39180 - Wed, 17 Oct 2018 10:30:00 GMT - Pousss l'exil par les conflits, la pauvret et l'espoir d'une vie meilleure, les migrants arrivent aprs un long parcours. Beaucoup sont blesss, briss, dsesprs parfois. Quelle rponse pour les aider ? - - - - Psy en prison, une mission impossible ? - https://le-cercle-psy.scienceshumaines.com/psy-en-prison-une-mission-impossible_sh_38718 - Wed, 17 Oct 2018 10:30:00 GMT - Dtenus proches de la psychose, manque cruel de moyens, hirarchie intrusive... Les praticiens intervenant en prison n'ont pas un quotidien facile. Retour sur un sacerdoce des temps modernes. - - - - Psychologue domicile : de la clinique l'tat brut - https://le-cercle-psy.scienceshumaines.com/psychologue-a-domicile-de-la-clinique-a-l-etat-brut_sh_35540 - Wed, 17 Oct 2018 10:30:00 GMT - Si tu ne peux pas venir au psychologue, le psychologue viendra toi ! L'intervention domicile demeure une pratique encore peu rpandue chez les psys. En quoi diffre-t-elle d'une consultation ordinaire ? - - - - diff --git a/internal/http/client/testdata/gb2312.html b/internal/http/client/testdata/gb2312.html deleted file mode 100644 index 3126e573..00000000 --- a/internal/http/client/testdata/gb2312.html +++ /dev/null @@ -1,862 +0,0 @@ - - - - - 7Уû - 51CTO.COM - - - - - - - - - - - - -
-
- -
|
-
-
Ƶ -
- ˹ - Ƽ - - - - ȫ - ϵͳ - ƶ - -
-
-
-
|
-
-
51CTOվ - - - -
-
-
|
- -
|
-
-
ƶ - -
- -
- -
-
-
- -
-
-
- - - - -
-
-
-
-
    -
  • -
  • -
  • -
  • -
-
-
-
- -
- - - -
- -
-
-

7Уû

-

ǵĵʼDZŸƭ֡ûз֣ôҲǺ졭֮һᷢ֡ؼǣƭʱ?

-
-
ߣСԴ4hou|2018-10-29 10:35
-
-
-  ղ -
-
-    -
-
-
-
-
- -

ǵĵʼDZŸƭ֡ûз֣ôҲǺ……֮һᷢ֡ؼǣƭʱ?

-

оԱıʼеƭѾԽԽֹڴºǵնʹӶû˵Webroot˾ϯϢȫGary HayslipʾȻûԽԽֵթƭĹַҲ٣Dz赲ָĵթƭν“һħһ”㹥ַͨʽƭȡûҵϢ

-

Hayslipʾ

- - - - - - -
“ҾõʼеƭѾձڵĵزûҲϰʶص鿴ʼ֪ӦôǹʵʩĿ֮!”
-

dzĺͬģͨԼҪˣƷ㹥ĸԴڡԺϰ“ҵʱæͿ”“”“ұӦ֪ǵʼ”ڣԼʼĴΪ

-

Hayslip

- - - - - - -
“öټֶκ͹ֹǣа취ɹƭû”
-

գWebroot˾ɨ˹ȥ18ڵijǧʼ˽йضĿijеķչơHayslipȫԼ100ϯϢȫչʾ˴˴ε˽⵽“ܶ˶յƵʼ”ʼоԿйصϢͽ֪ͨڲ֮ͬ¡

-

Cofense(ǰΪPhishMe)簲ȫսԼJohn“Lex”RobinsonӦHayslipĹ۵㣬ʾ߶Ƿ͵ĵʼıԼǵĹĿ꣬ѾԽԽ˽⡣˵

- - - - - - -
“ǽĹͨʽ()15ǰ20ǰ30ǰȣܾԵòôͨˡʼҪĴͨףҪҵлһ¡”
-

һЩУչʾϢԼʾĹߵĿͲԵݡ

-

1.

-

-

߲ϣĿԥʱǾͻдһֽȸУΪϣܹ

-

Ҳõʼֱ˵“”ѡ֮ƵİʾHayslipʾΪһϯϢȫ٣;ῴΪҪṩУҪǣܶܺߵǣΪûвȡijЩܺҪжܵͷHayslipԱ

- - - - - - -
“ԸȥѰרҵҲԸΪ¶ҽԺκԼ‘’۵δ֪ʼΪĽͨܶЧ;绰”
-

2. Ʊ

-

-

Cofense⵽“Top10ʼ”У“Ʊ”һʾͶռ6(ֻDZ﷽ʽ)Ҳ˵ڿʱ񶯻Ȼλ

-

̸Cofense׷ٵƭʱRobinsonʾ

- - - - - - -
“˵˼Ǿƭֶ漰Ǯ⡣ȻǮÿ˵һߴ̼ԵĻ……һߴ̼ԵĻʱǵȤ”
-

Ȼǰ6ƭֵľϢͬ˶ͼ“Ʊ”һΪǵĿꡣǮһǿĶߺ֪һ㣬ǵߡʾCofenseɨʼУԼ100,000ʼ“Ʊ”һΪġ

-

CofenseоԱ֣“”һܻӭı⣬ʹҲ40,000ʼͬʱ“”“”ҲǷdzܻӭ⡣

-

WebRoot֣“”Ҳһֳѡ񣬵ȻһЩʼ壺“Chase֪ͨ”һܻӭIJ⡣

-

ҪעǣҪΪթֻᷢûϣʹǻ˾Ҳ⵽թƭթƭСѾﵽԪȸFacebookĻƲŵڱװ˶ͨǵת˼¼׼һ̣ԪķƱ

-

Ȼº󾭹ִصŬ׷ʧ;˾Ͳôˣ2016ֵ30Ԫթƭ󲿷ֶ޷׷ء

-

3. ֪ͨ

-

-

HayslipʾԹ˾߹ܵľö㹥Ҫ߸ŬоԼΪϽĴǺ﷨ͳƣ

- - - - - - -
“Ϊ‘’(whaling attacks)ͨ㹥֮ν“”ʵһթͣҵij˾߲߹Ŷӵ͵ʼַ(Ϣͨҳṩ)׫дЩԱ乫˾ְλƵĵʼЩʼͼʹ߹ǵijӲijվڴ˶صУư¼ѳϢ˾ܡ”
-

Ը߼ԱʵʩĹߣϣʼϢʵǿܻͰضƻ“Э”źŵթԵʼǻȶĿѡноģз֪ͨϢ⣬߻ܻϵǵCEOCFOвһЩ⣬ҪϵİĽ֤ʲתƵĺԺͿԡ

-

4. ˻֤

-

-

һֱӵľϵ󣬵֪ʶȨԴںܴ͵Ĺͨƾ֤(credential phishing)ΪĿڻȡ㡣ϷҪƾ֤ΪȷϷʵԵĻƾ֤ͻͼȡϷƾ֤ˣƾ֤һԣ߾ͿֱӻȡĸϢʹߵ˺šȵȡ

-

ڽƾ֤ʱҪͨ“˻֤”֮¼ҳ֤ƾ֤ΪһϵкУҪȡûݣҪȡЩϢͿ漰ðʹõƷƷ“˻֤”ĵʼ

-

5. ĵ

-

-

Ȼڵʼձ飬RobinsonΪҲȻܻӭʮЧ뷢Ʊ֪ͨصĵʼ߶ͽصľС

-

ϹǶҵ񻷾ơΪ֪Աļʵͻ֪ӱWordļʽĸǺġԽԽĸԼΪҪʽʵԽԽҵ񻷾֪ʼзʲôݲġ

-

⣬ʼⶼdẓֻһ֡ҲִҵͨķʽԷʽġΪҵе˱æµ÷dzʽ⡣

-

͸ԣ׼Ĺ̺ͨ߿԰֯Чطʽ㹥֯ԱչʾЩʼӦԼӦòȡָʽԱܹʱթʼ

-

6. ж“֧β”

-

-

HayslipָĿŴʼ⡣ڵʼв“Ҫ”صУܹɹʹĿɹҪɵκ顣Ҳָ“ж”صʱʵȷʵ——“ж”صĵʼУӵĵʸߴԼ40%߻ὫܺضٵԴվȡ¼ƾ֤ܺڱƭƣ“֪ҵʱӦ”

-

ڹȥһУѾʹö⸽תΪǶӡ񣬴ʼжӣҴӱ濴ܺԽԽжЩǷ԰ȫΪڹȥǿԽͣһ鿴Ƿ;ŹߵļַʽѾˡ

-

7. ѷ/ijĶ#812-4623ѵ

-

-

Hayslipָ͵ʼͨڼڼ(ϾҪ˫11ʢ)ͳƣÿشڼգ̼ҶĿͻʹ۴ݶ̬ʼʱ򣬵ʼҲŻˡ⣬һЩض͵ĹһеIJͬʱγ֣磬ںͲصƭֻ˰ռʱ;ʥڼͻ“֧”صթϢ

-

HayslipϢҲܲرἰǷѾܻվΪն⸽

-

ѷ/ijϹˣܴԥصЩʼԲ鿴еȷԼʲôʱܹȵȡȻҲͻԥصеĶ鿴ǶඩƷǷԼ豸ѾȾʱѻ֮ӡ

-

ûӦξʼ?

-
    -
  • ⿪·ĵʼļװɱʱ֪ʶͲϵͳϢ˽򿪸˷ǽ;
  • -
  • Ҫ˺Ϣͣÿ˺֮ʼ;
  • -
  • ΪҪDzҪظߵʼӣʵʼϢʹõ绰;ij˾վʹֱӷʣǵʼе;
  • -
  • ַ–ϷվַԽ϶̣ͨ.com.govβðվĵַͨϳֻаϷҵ();
  • -
  • ͬ˺ʹòͬҪʹͬĿ;
  • -
  • Ҫʹúܼ򵥵Ŀ(000000յ);
  • -
-

һ䣬þȡÿ

-

༭Ƽ

-
-
    -
  1. AI²£ ȫרұʾ
  2. -
  3. ҵչ(ERM)ν簲ȫвҵ
  4. -
  5. ۽緸ŻCobalt Gang Commodity Builder infrastructure
  6. -
  7. ڿͽPythonΪԵѡ
  8. -
  9. 繥߿ʹȨûƾ֤3طʽ
  10. -
-
-
α༭ TEL01068476606

- 0 -
-
- -
-
: -
- - - -
-
- - -
-
-
- - - -
-
-
- - -
-
-
Ҷڿ
ϲ
-
-
    -
  • -
    -
    -
  • -
  • -
    -
  • -
-
-
-
- - -
-
- - - - - -
-
-
- - -
- - -
- -
- -
-
- - - - -
-
-
-

Ƶγ+

- -
-
֮ - Nmapɨ蹤 -Ƶ̳̣ȫNmapרŻݣ
-
-

֮ - Nmapɨ蹤 -Ƶ

-

ʦ949ѧϰ

-
-
- -
-
簲ȫ֮»ΪUSGǽۼʵսƵγ
-
-

簲ȫ֮»ΪUSGǽۼʵս

-

ʦڷ3047ѧϰ

-
-
- -
-
֮ - Nmapɨ蹤 ɨƵ̳
-
-

֮ - Nmapɨ蹤 ɨƵ

-

ʦ208ѧϰ

-
-
- -
-
-
-
- + -
- CTOƷ -
-
- -
-
-
-
-
-

ר+

-
-
ע簲ȫ Ԥթƭ
-
- ע簲ȫ Ԥթƭ -

թƭ

-
-
-
2018ñרⱨ
-
- 2018ñרⱨ -

ñ

-
-
-
2018׶簲ȫרⱨ
-
- 2018׶簲ȫרⱨ -

׶簲ȫ

-
-
-
2018RSAϢȫרⱨ
-
- 2018RSAϢȫרⱨ -

RSA

-
-
-
-
-
-
- -
-
-

+

-
- -
-

SOA

- ڱУThomas ERL˵һ˶Զ˵Ľ̳̣ṩ˴ӻ㿪ʼĽģƵָͨ𲽵ġġõSOA... -
- -
-
-
-
-
-
-
-

51CTOʿ

-

- 51CTOʿ -
-
-
-
-
- -
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/internal/http/client/testdata/meta-charset-attribute.html b/internal/http/client/testdata/meta-charset-attribute.html deleted file mode 100644 index 2d7d25ab..00000000 --- a/internal/http/client/testdata/meta-charset-attribute.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - meta charset attribute - - - - - - - - - - - -

meta charset attribute

- - -
- - -
 
- - - - - -
-

The character encoding of the page can be set by a meta element with charset attribute.

-

The only character encoding declaration for this HTML file is in the charset attribute of the meta element, which declares the encoding to be ISO 8859-15.

The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector .test div.ÜÀÚ. This matches the sequence of bytes above when they are interpreted as ISO 8859-15. If the class name matches the selector then the test will pass.

-
-
-
Next test
HTML5
-

the-input-byte-stream-009
Result summary & related tests
Detailed results for this test
Link to spec

-
Assumptions:
-
- - - - - - diff --git a/internal/http/client/testdata/meta-content-attribute.html b/internal/http/client/testdata/meta-content-attribute.html deleted file mode 100644 index 1c3f228e..00000000 --- a/internal/http/client/testdata/meta-content-attribute.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - meta content attribute - - - - - - - - - - - -

meta content attribute

- - -
- - -
 
- - - - - -
-

The character encoding of the page can be set by a meta element with http-equiv and content attributes.

-

The only character encoding declaration for this HTML file is in the content attribute of the meta element, which declares the encoding to be ISO 8859-15.

The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector .test div.ÜÀÚ. This matches the sequence of bytes above when they are interpreted as ISO 8859-15. If the class name matches the selector then the test will pass.

-
-
-
Next test
HTML5
-

the-input-byte-stream-007
Result summary & related tests
Detailed results for this test
Link to spec

-
Assumptions:
-
- - - - - - diff --git a/internal/http/client/testdata/rdf_utf8.xml b/internal/http/client/testdata/rdf_utf8.xml deleted file mode 100644 index 108ef6a2..00000000 --- a/internal/http/client/testdata/rdf_utf8.xml +++ /dev/null @@ -1,374 +0,0 @@ - - - - heise online News - https://www.heise.de/newsticker/ - Nachrichten nicht nur aus der Welt der Computer - - - - - OLED-TVs: Vorsichtsmaßnahmen gegen Einbrennen - https://www.heise.de/newsticker/meldung/OLED-TVs-Vorsichtsmassnahmen-gegen-Einbrennen-4205274.html?wt_mc=rss.ho.beitrag.rdf - Wer gerade einen neuen OLED-Fernseher gekauft hat oder sich zu Weihnachten einen zuzulegen möchte, sollte unbedingt ein paar Hinweise beachten. - - - - Mega-Deal: IBM übernimmt Red Hat - https://www.heise.de/newsticker/meldung/Mega-Deal-IBM-uebernimmt-Red-Hat-4205582.html?wt_mc=rss.ho.beitrag.rdf - Giganten-Hochzeit in den USA: Der Computerkonzern IBM übernimmt den Open-Source-Anbieter Red Hat für umgerechnet 30 Milliarden Euro. - - - - Fortnite-Macher: Epic Games soll 15 Milliarden Dollar wert sein - https://www.heise.de/newsticker/meldung/Fortnite-Macher-Epic-Games-soll-15-Milliarden-Dollar-wert-sein-4205522.html?wt_mc=rss.ho.beitrag.rdf - Epic Games konnte bei einer Investionsrunde einige neue Geldgeber von sich überzeugen. Insgesamt flossen 1,25 Milliarden US-Dollar. - - - - Erster nichtstaatlicher Raketenstart in China fehlgeschlagen - https://www.heise.de/newsticker/meldung/Erster-nichtstaatlicher-Rekatenstart-in-China-fehlgeschlagen-4205524.html?wt_mc=rss.ho.beitrag.rdf - Die Trägerrakete ZQ-1 hat es wegen unbekannter technischer Probleme nach dem Start nicht in die Erdumlaufbahn geschafft. - - - - eARC: Immer mehr Hersteller schalten HDMI-Audio-Rückkanal frei - https://www.heise.de/newsticker/meldung/eARC-Hersteller-schalten-HDMI-Audio-Rueckkanal-frei-4205518.html?wt_mc=rss.ho.beitrag.rdf - Während andere HDMI-2.1-Funktionen auf sich warten lassen, ist der "enhanced Audio Return Channel" nach einem Firmware-Update schon bei AV-Receivern nutzbar. - - - - Vorschau: Neue PC-Spiele im November 2018 - https://www.heise.de/newsticker/meldung/Vorschau-Neue-PC-Spiele-im-November-2018-4202098.html?wt_mc=rss.ho.beitrag.rdf - Jeden Monat schicken Spiele-Hersteller zahlreiche neue Titel ins Rennen. Wir haben die wichtigsten Spiele-Neuerscheinungen im November herausgesucht. - - - - Israelisches Start-up baut faltbares Elektroauto - https://www.heise.de/newsticker/meldung/Israelisches-Start-up-baut-faltbares-Elektroauto-4205501.html?wt_mc=rss.ho.beitrag.rdf - Das zweisitzige Auto kann sein Fahrgestell zum Parken einklappen und passt dann auf einen Motorradparkplatz. - - - - Flash-Speicher: WD will Produktion einschränken - https://www.heise.de/newsticker/meldung/Flash-Speicher-WD-will-Produktion-einschraenken-4205498.html?wt_mc=rss.ho.beitrag.rdf - Die Preise für NAND-Flash-Speicher kennen derzeit nur eine Richtung: abwärts. WD will dem mit Produktionseinschränkungen begegnen. - - - - LED-Tastatur Aukey KM-G6 im Test: mechanisch, günstig und laut - https://www.techstage.de/news/Mechanische-Tastatur-Aukey-KM-G6-im-Test-guenstig-und-laut-4205068.html?wt_mc=rss.ho.beitrag.rdf - Die Aukey KM-G6 kostet weniger als 50 Euro und zeigt, dass mechanische Tastaturen nicht teuer sein müssen. Wir testen das Keyboard. - - - - Einhörner zum Leben erwecken - Kultur-Hackathon in Mainz gestartet - https://www.heise.de/newsticker/meldung/Einhoerner-zum-Leben-erwecken-Kultur-Hackathon-in-Mainz-gestartet-4205490.html?wt_mc=rss.ho.beitrag.rdf - In Museen, Bibliotheken und Archive stecken viele Daten, die sich kreativ nutzen lassen. Programmierer, Designer und Historiker haben sich das vorgenommen. - - - - Impressionen von der SPIEL 2018: Gesellschaftsspiele für Nerds und Geeks - https://www.heise.de/newsticker/meldung/Impressionen-von-der-SPIEL-2018-Gesellschaftsspiele-fuer-Nerds-und-Geeks-4205405.html?wt_mc=rss.ho.beitrag.rdf - Weg von Bildschirm und Controller, hin zu Würfeln und Karten. Die SPIEL-Messe zeigt Neuheiten bei IT-affinen Brett-, Karten- und Tabletop-Spielen. - - - - Missing Link: Vor 100 Jahren begann die deutsche Revolution - https://www.heise.de/newsticker/meldung/Missing-Link-Vor-100-Jahren-begann-die-deutsche-Revolution-4205422.html?wt_mc=rss.ho.beitrag.rdf - Von den Sturmvögeln zu den Stiefkindern der Revolution: Mit dem Matrosenaufstand startete Deutschland in die erste Republik. - - - - 4W: Was war. Was wird. Wettrüsten oder Waffelessen, das ist die Frage. - https://www.heise.de/newsticker/meldung/Was-war-Wettruesten-oder-Waffelessen-das-ist-die-Frage-4205432.html?wt_mc=rss.ho.beitrag.rdf - Zeit! Irgendwann gab es sie gar nicht, heute wird sie uns geschenkt. Ja, auch Hal Faber weiß, dass das Quatsch ist. Wie so vieles andere. - - - - Kommentar: Vom DNS, aktuellen Hypes, Überwachung und Zensur - https://www.heise.de/newsticker/meldung/Kommentar-Vom-DNS-aktuellen-Hypes-Ueberwachung-und-Zensur-4205380.html?wt_mc=rss.ho.beitrag.rdf - Das DNS ist gereift, es kann mit den Bedrohungen der Überwachung und Zensur umgehen. Eine Antwort von Lutz Donnerhacke auf "Die Gruft DNS gehört ausgelüftet". - - - - Microsoft will Militär und Geheimdienste beliefern - https://www.heise.de/newsticker/meldung/Microsoft-will-Militaer-und-Geheimdienste-beliefern-4205383.html?wt_mc=rss.ho.beitrag.rdf - Microsoft ist trotz Protesten von Mitarbeitern bereit, dem Militär und den Geheimdiensten des Landes KI-Systeme und sonstige Technologien zu verkaufen. - - - - Zurück zur "Normalzeit": Uhren werden (möglichweise zum letzten Mal) um eine Stunde zurückgestellt - https://www.heise.de/newsticker/meldung/Zurueck-zur-Normalzeit-Uhren-werden-moeglichweise-zum-letzten-Mal-um-eine-Stunde-zurueckgestellt-4205376.html?wt_mc=rss.ho.beitrag.rdf - Die Zeitumstellung könnte bald Geschichte sein. Es gibt aber Bereiche, in denen eine Umstellung sehr aufwendig werden könnte. - - - - 5G: Seehofer fordert Änderung der Vergaberegeln - https://www.heise.de/newsticker/meldung/5G-Seehofer-fordert-Aenderung-der-Vergaberegeln-4205373.html?wt_mc=rss.ho.beitrag.rdf - Der Bundesinnenminister sieht Bewohner ländlicher Gebiete durch die Ausschreibungsregeln für das 5G-Netz benachteiligt und verlangt Nachbesserungen. - - - - Ausstellung erinnert an das Lebenswerk von Konrad Zuse - https://www.heise.de/newsticker/meldung/Ausstellung-erinnert-an-das-Lebenswerk-von-Konrad-Zuse-4205359.html?wt_mc=rss.ho.beitrag.rdf - In Hopferau im Ostallgäu stellte Konrad Zuse seine Rechenmaschine Z4 fertig. Jetzt erinnert eine Ausstellung im Schloss Hopferau an den Computerpionier. - - - - Test TrackerID LTS-450: GPS-Flaschenhalter am Fahrrad - https://www.techstage.de/news/Test-TrackerID-LTS-450-GPS-Flaschenhalter-am-Fahrrad-4205272.html?wt_mc=rss.ho.beitrag.rdf - Fahrraddiebe sind blöd, aber nicht dumm: Sehen sie einen GPS-Tracker, entfernen sie ihn. Deswegen tarnt sich der TrackerID LTS-450 in einem Flaschenhalter. - - - - Fünf mobile Beamer im Vergleichstest - https://www.techstage.de/news/Fuenf-mobile-Beamer-im-Vergleichstest-4204823.html?wt_mc=rss.ho.beitrag.rdf - In den vergangenen Wochen haben wir uns fünf kompakte Beamer mit integriertem Akku angeschaut. Im Vergleichstest zeigen wir Vor- und Nachteile. - - - - In Japan geht ein weiterer Atomreaktor wieder ans Netz - https://www.heise.de/newsticker/meldung/In-Japan-geht-ein-weiterer-Atomreaktor-wieder-ans-Netz-4205351.html?wt_mc=rss.ho.beitrag.rdf - Das Atomkraftwerk Ikata in Japan hat einen Reaktor wieder hochgefahren, gegen dessen Betrieb eine Bürgergruppe geklagt hatte. - - - - FlyCroTug: Kleine Drohne mit großer Zugkraft - https://www.heise.de/newsticker/meldung/FlyCroTug-Kleine-Drohne-mit-grosser-Zugkraft-4205335.html?wt_mc=rss.ho.beitrag.rdf - Forscher haben 100 Gramm leichte Minidrohnen entwickelt, die von einem festen Haltepunkt aus das 40-fache ihres Gewichts bewegen können. - - - - - Google Office-Programme: Neue Dokumente in Browserzeile anlegen - https://www.heise.de/newsticker/meldung/Google-Docs-Neue-Dokumente-in-Browserzeile-anlegen-4205346.html?wt_mc=rss.ho.beitrag.rdf - Für seine webbasierten Office-Programme hat Google eine praktische Abkürzung direkt in die Anwendungen Docs, Sheets, Slides und Forms veröffentlicht. - - - - Wo Hobby-Astronomen den Profis voraus sind - https://www.heise.de/newsticker/meldung/Wo-Hobby-Astronomen-den-Profis-voraus-sind-4205332.html?wt_mc=rss.ho.beitrag.rdf - Hobby-Astronomen leisten einen wertvollen Beitrag zur Wissenschaft, etwa durch das Beobachten veränderlicher Sterne oder die Suche nach Meteoriten. - - - - Zahlen geschönt? FBI-Untersuchung gegen Tesla - https://www.heise.de/newsticker/meldung/Zahlen-geschoent-FBI-Untersuchung-gegen-Tesla-4205285.html?wt_mc=rss.ho.beitrag.rdf - Es besteht der Verdacht, dass Tesla Produktionszahlen wissentlich überoptimistisch vorhergesagt hat. Das FBI ermittelt strafrechtlich. - - - - c't uplink 24.6: Linux mit UEFI / OLED-Defekte / Dropbox-Alternativen - https://www.heise.de/ct/artikel/c-t-uplink-24-6-Linux-mit-UEFI-OLED-Defekte-Dropbox-Alternativen-4205070.html?wt_mc=rss.ho.beitrag.rdf - Die c't-uplink Show: Dieses Mal mit eingebrannten Logos bei OLED-TVs, Alternativen zu Dropbox und wie man Linux am besten mit UEFI verheiratet. - - - - Die Bilder der Woche (KW 43): Von Porträt bis Landschaft - https://www.heise.de/foto/meldung/Die-Bilder-der-Woche-KW-43-Von-Portraet-bis-Landschaft-4204550.html?wt_mc=rss.ho.beitrag.rdf - Blickfang: Unsere Bilder des Tages haben in dieser Woche keine Scheu vor direktem Augenkontakt und Spiegelbildern. - - - - BIOS-Option macht ThinkPads zu Briefbeschwerern - https://www.heise.de/newsticker/meldung/BIOS-Option-macht-ThinkPads-zu-Briefbeschwerern-4205185.html?wt_mc=rss.ho.beitrag.rdf - Ein einziger Klick im BIOS-Setup - und einige aktuelle Lenovo-Notebooks starten nicht mehr; eine Lösung des Problems fehlt noch. - - - - Markenstreit um “Dash”: Bragi beantragt einstweilige Verfügung gegen Oneplus - https://www.heise.de/newsticker/meldung/Markenstreit-um-Dash-Bragi-beantragt-einstweilige-Verfuegung-gegen-Oneplus-4205223.html?wt_mc=rss.ho.beitrag.rdf - Der Hersteller der smarten Kopfhörer “The Dash” sieht seine Markenrechte durch die Schnelladegeräte der chinesischen Smartphones verletzt. - - - - Übernahme von GitHub durch Microsoft abgeschlossen - https://www.heise.de/newsticker/meldung/Uebernahme-von-GitHub-durch-Microsoft-abgeschlossen-4205119.html?wt_mc=rss.ho.beitrag.rdf - Microsofts Übernahme von GitHub ist abgeschlossen. Ab Montag beginnt die Arbeit des neuen CEO Nat Friedman. Er will GitHub für die Entwickler besser machen. - - - - Webhosting und Cloud Computing: Aus 1&1 und ProfitBricks wird 1&1 Ionos - https://www.heise.de/newsticker/meldung/Webhosting-und-Cloud-Computing-Aus-1-1-und-ProfitBricks-wird-1-1-Ionos-4205066.html?wt_mc=rss.ho.beitrag.rdf - 1&1 bietet seine Webhosting- und Cloud-Produkte künftig unter dem Namen 1&1 Ionos an. Besserer Service soll Unternehmen den Cloud-Start schmackhaft machen. - - - - iPhone XR: Die 10 wichtigsten Testergebnisse - https://www.heise.de/mac-and-i/meldung/iPhone-XR-Die-10-wichtigsten-Testergebnisse-4204845.html?wt_mc=rss.ho.beitrag.rdf - Seit heute ist das dritte und günstigste von Apples neuen Smartphones im Handel. Mac & i konnte es bereits testen. - - - - Motorola One: Android-One-Smartphone für 299 Euro im Test - https://www.techstage.de/news/Motorola-One-im-Test-Android-One-Smartphone-mit-Notch-4203618.html?wt_mc=rss.ho.beitrag.rdf - Das Motorola One ist ein Smartphone mit schickem Design und Android One als Betriebssystem. Ob und für wen sich der Kauf lohnt, hat TechStage getestet. - - - - US Copyright Office: DRM darf für Reparaturen umgangen werden - https://www.heise.de/newsticker/meldung/US-Copyright-Office-DRM-darf-fuer-Reparaturen-umgangen-werden-4205173.html?wt_mc=rss.ho.beitrag.rdf - In den USA ist es künftig legal, den Kopierschutz elektronischer Geräte zu knacken, um etwa sein Smartphone, Auto oder den vernetzten Kühlschrank zu reparieren. - - - - Ausprobiert: Haptik-Datenhandschuhe von Senseglove - https://www.heise.de/newsticker/meldung/Ausprobiert-Haptik-Datenhandschuhe-von-Senseglove-4205142.html?wt_mc=rss.ho.beitrag.rdf - Der Senseglove-Datenhandschuh trackt nicht nur jeden Finger, sondern simuliert auch Widerstand und Haptik. Wir haben ihn ausprobiert. - - - - Apple News soll "Netflix für Nachrichten" werden - https://www.heise.de/mac-and-i/meldung/Apple-News-soll-Netflix-fuer-Nachrichten-werden-4204886.html?wt_mc=rss.ho.beitrag.rdf - Apple betreibt für seinen hauseigenen Infodienst eine eigene Redaktion – und setzt kaum auf Algorithmen. Im Abo könnten bald diverse Magazine hinzukommen. - - - - Xbox One X im 4K-Test: Spaßzentrale für UHD-TVs - https://www.techstage.de/news/Xbox-One-X-im-4K-Test-Spasszentrale-fuer-UHD-TVs-4204803.html?wt_mc=rss.ho.beitrag.rdf - Die aktuelle Xbox One X bewirbt Microsoft als idealen Zuspieler für UHD-Fernseher. Wir haben ihre 4K-Fähigkeiten bei Filmen und Spielen getestet. - - - - Red Dead Redemption 2: Die Entschleunigung des Action-Adventures - https://www.heise.de/newsticker/meldung/Red-Dead-Redemption-2-Die-Entschleunigung-des-Action-Adventures-4205034.html?wt_mc=rss.ho.beitrag.rdf - Nach dem Live-Stream: Unsere Eindrücke aus den ersten Stunden des Gaming-Blockbusters Red Dead Redemption 2. - - - - Grüne: Netzbetreiber sollen Breitband-Universaldienst finanzieren - https://www.heise.de/newsticker/meldung/Gruene-Netzbetreiber-sollen-Breitband-Universaldienst-finanzieren-4205022.html?wt_mc=rss.ho.beitrag.rdf - Schwarz-Rot will bis spätestens 2025 einen Anspruch auf Breitband für alle gesetzlich verankern. Die Grünen sehen dagegen sofortigen Handlungsbedarf. - - - - Programmiersprache: Rust 1.30 will mehr Klarheit schaffen - https://www.heise.de/developer/meldung/Programmiersprache-Rust-1-30-will-mehr-Klarheit-schaffen-4204893.html?wt_mc=rss.ho.beitrag.rdf - Der Umgang mit absoluten Pfaden und neue prozedurale Makros sind die Highlights der aktuellen Rust-Version. - - - - Apples Oktober-Event: iPad Pro 2018 und neue Macs vor der Tür - https://www.heise.de/mac-and-i/meldung/Apples-Oktober-Event-iPad-Pro-2018-und-neue-Macs-vor-der-Tuer-4204922.html?wt_mc=rss.ho.beitrag.rdf - Nach der Einführung der iPhones wird sich Apple der Zukunft seiner Computer zuwenden: Wichtige Neuerungen stehen an. - - - - Magento-Shops: Verwundbare Add-ons als Schlupfloch für Kreditkarten-Skimmer - https://www.heise.de/security/meldung/Magento-Shops-Verwundbare-Add-ons-als-Schlupfloch-fuer-Kreditkarten-Skimmer-4204828.html?wt_mc=rss.ho.beitrag.rdf - Ein Sicherheitsforscher warnt vor knapp über 20 Add-ons, die Onlineshops basierend auf der Magento-Software angreifbar machen. - - - - Atomkraft: Gericht kippt Schließungs-Dekret für Fessenheim - https://www.heise.de/newsticker/meldung/Atomkraft-Gericht-kippt-Schliessungs-Dekret-fuer-Fessenheim-4204853.html?wt_mc=rss.ho.beitrag.rdf - Der Conseil d'État hat zu Gunsten der Gemeinde Fessenheim und der Gewerkschaften entschieden. - - - - Qt Design Studio erreicht Version 1.0 - https://www.heise.de/developer/meldung/Qt-Design-Studio-erreicht-Version-1-0-4204902.html?wt_mc=rss.ho.beitrag.rdf - Neue Funktionen wie die Qt Photoshop Bridge und zeitachsenbasierte Animationen sollen die Zusammenarbeit von Entwicklern und Designern vereinfachen. - - - - Vodafone bringt Mini-Handy von Palm nach Deutschland - https://www.heise.de/newsticker/meldung/Vodafone-bringt-Mini-Handy-von-Palm-nach-Deutschland-4204878.html?wt_mc=rss.ho.beitrag.rdf - Das neue Palm kommt auch in Deutschland auf den Markt: Vodafone bringt das kuriose Mini-Handy exklusiv in den Handel. - - - - Xeons und Modems bescheren Intel Rekordquartal - https://www.heise.de/newsticker/meldung/Xeons-und-Modems-bescheren-Intel-Rekordquartal-4204869.html?wt_mc=rss.ho.beitrag.rdf - Starke Nachfrage nach Prozessoren für Cloud-Rechenzentren sowie LTE-Modems lassen bei Intel die Gewinne sprudeln und bescheren gute Aussichten. - - - - KI druckt Kunst: Auktionshaus Christie's versteigert KI-Gemälde für 380.000 Euro - https://www.heise.de/newsticker/meldung/KI-druckt-Kunst-Auktionshaus-Christie-s-versteigert-KI-Gemaelde-fuer-380-000-Euro-4204793.html?wt_mc=rss.ho.beitrag.rdf - Das renommierte Auktionshaus Christie's hat erstmals ein von einer KI erschaffenes Bild versteigert. Der Preis war wesentlich höher als erwartet. - - - - EU-Parlament verabschiedet Resolution zur Datenschutzuntersuchung bei Facebook - https://www.heise.de/newsticker/meldung/EU-Parlament-verabschiedet-Resolution-zur-Datenschutzuntersuchung-bei-Facebook-4204766.html?wt_mc=rss.ho.beitrag.rdf - Facebook soll mehr Aufklärung über seine Datenschutzpraxis leisten. Das EU-Parlament hat deshalb eine Untersuchung durch EU-Institutionen verabschiedet. - - - - IBM setzt auf 277.000 Apple-Geräte - https://www.heise.de/mac-and-i/meldung/IBM-setzt-auf-277-000-Apple-Geraete-4204728.html?wt_mc=rss.ho.beitrag.rdf - Bei IBM stellen Macs inzwischen ein Viertel aller Laptops. Das Open-Source-Tool Mac@IBM soll auch Admins anderer Firmen die Einrichtung erleichtern. - - - - heise-Angebot: #TGIQF - das c't-Retroquiz: 8 Bit & mehr - https://www.heise.de/newsticker/meldung/TGIQF-das-c-t-Retroquiz-8-Bit-mehr-4202717.html?wt_mc=rss.ho.beitrag.rdf - C64, ZX Spectrum, Apple II ... die Heimcomputer lösten eine IT-Revolution in den Kinderzimmern aus. Wie viel ist aus der Zeit bei Ihnen hängen geblieben? - - - - heise-Angebot: c't Fotografie: Spiegeloses Vollformat im Test - https://www.heise.de/foto/meldung/c-t-Fotografie-Spiegeloses-Vollformat-im-Test-4201826.html?wt_mc=rss.ho.beitrag.rdf - Lange war Sony der einzige Anbieter für spiegellose Vollformatkameras. Mit der Canon EOS R und der Nikon Z-Serie werden die Karten neu gemischt. - - - - British-Airways-Hack: 185.000 weitere Kunden betroffen - https://www.heise.de/newsticker/meldung/British-Airways-Hack-185-000-weitere-Kunden-betroffen-4204675.html?wt_mc=rss.ho.beitrag.rdf - Die Fluggesellschaft hat nun bekanntgegeben, dass bis dato Unbekannte Kreditkartendaten von noch mehr Kunden als bislang bekannt kopiert haben. - - - - Google: 48 Mitarbeiter wegen sexueller Belästigung gefeuert - https://www.heise.de/newsticker/meldung/Google-48-Mitarbeiter-wegen-sexueller-Belaestigung-gefeuert-4204687.html?wt_mc=rss.ho.beitrag.rdf - Der Weggang von Android-Schöpfer Andy Rubin von Google war wohl nicht freiwillig – ihm wurde sexuelle Nötigung vorgeworfen. Und er war nicht der einzige. - - - - Fujitsu schließt Werk in Augsburg - https://www.heise.de/newsticker/meldung/Fujitsu-schliesst-Werk-in-Augsburg-4204722.html?wt_mc=rss.ho.beitrag.rdf - Fujitsu plant einen Konzernumbau. In Augsburg sind davon 1500 Beschäftigte betroffen. - - - - Ego-Shooter Metro 2033 bei Steam kostenlos - https://www.heise.de/newsticker/meldung/Metro-2033-ist-bei-Steam-heute-kostenlos-4204706.html?wt_mc=rss.ho.beitrag.rdf - Metro 2033 wird am heutigen Freitag auf Steam kostenlos angeboten. Der Ego-Shooter basiert auf dem gleichnamigen Roman von Dmitri Gluchowski. - - - - Lightroom-Alternative: DxO bringt PhotoLab 2 - https://www.heise.de/foto/meldung/Lightroom-Alternative-DxO-bringt-PhotoLab-2-4204614.html?wt_mc=rss.ho.beitrag.rdf - PhotoLab gibt es nun in Version 2: Verbessert wurde unter anderem die Bildverwaltung, zudem integriert DxO die von den Nik-Filtern bekannte U-Point-Technologie. - - - - Google schaltet Nearby Notifcations in Android ab - https://www.heise.de/developer/meldung/Google-schaltet-Nearby-Notifcations-in-Android-ab-4204667.html?wt_mc=rss.ho.beitrag.rdf - Die Funktion für standortbasierte Benachrichtigungen lieferte wohl mehr Spam als nützliche Inhalte. - - - - iPhone XR: Verkaufsstart ohne Ansturm - https://www.heise.de/mac-and-i/meldung/iPhone-XR-Verkaufsstart-ohne-Ansturm-4204679.html?wt_mc=rss.ho.beitrag.rdf - Apple bringt die billigeren und bunten iPhone-Modellreihe in den Handel. Groß anstehen mussten Kunden dafür nicht. - - - - - Snapchat: Aktienabsturz durch Nutzerschwund - https://www.heise.de/newsticker/meldung/Snapchat-Aktienabsturz-durch-Nutzerschwund-4204631.html?wt_mc=rss.ho.beitrag.rdf - Snapchat laufen weiterhin die Nutzer weg – und das wird sich vorerst nicht ändern, sagt Snap. Die Aktie stürzte trotz geringerer Verluste um zehn Prozent ab. - - - - Mi Mix 3: Xiaomi-Flaggschiff mit Kamera-Slider und 10 GByte RAM - https://www.heise.de/newsticker/meldung/Mi-Mix-3-Xiaomi-Flaggschiff-mit-Kamera-Slider-und-10-GByte-RAM-4204655.html?wt_mc=rss.ho.beitrag.rdf - Xiaomis nächstes Flaggschiff bietet eine fast randlose Display-Front. Die Selfie-Kamera ist in einem magnetischen Slider-Mechanismus untergebracht. - - - - - \ No newline at end of file diff --git a/internal/http/client/testdata/single_quote_xml_encoding.xml b/internal/http/client/testdata/single_quote_xml_encoding.xml deleted file mode 100644 index 21fcba8e..00000000 --- a/internal/http/client/testdata/single_quote_xml_encoding.xml +++ /dev/null @@ -1,6217 +0,0 @@ - - -GitLab -https://about.gitlab.com/blog/ - -2018-12-12T00:00:00+00:00 - -The GitLab Team - - -What to expect at Predict 2019, a virtual reality conference - -https://about.gitlab.com/2018/12/12/what-to-expect-at-predict-2019/ -2018-12-12T00:00:00+00:00 -2018-12-12T00:00:00+00:00 - -Tina Sturgis - -<p>✅ Learn about up and coming tech trends in 2019</p> - -<p>✅ For free</p> - -<p>✅ Without leaving your desk</p> - -<p>If your response is <a href="https://predict2019.com">"Sign me up!"</a>, let's talk about Predict 2019.</p> - -<h2 id="what-is-predict-2019">What is Predict 2019?</h2> - -<p><a href="https://predict2019.com">Predict 2019</a> is the industry’s first truly immersive, virtual reality conference focused on predictions on the future of DevOps, Security, and related technology. Taking place on Dec. 18, <a href="https://predict2019.com">Predict 2019</a> is hosted on a platform that makes it look and feel like a real conference, with simulated theaters to view the keynotes and presentations, a conference lobby for chatting and socializing, and a virtual expo floor with exhibitor stands equipped with video, downloads, and even swag for you to take. This exciting event is offered through MediaOps, the company behind technical communities such as DevOps.com, Container Journal, Security Boulevard, and DevOps TV. So when GitLab had an opportunity to be a premier sponsor for Predict 2019, we jumped at the chance.</p> - -<div class="newsletter-cta-b panel panel-default panel-newsletter-cta"> -<div class="panel-body newsletter-cta"> -<div class="panel-header"> -<?xml version="1.0" encoding="UTF-8"?> -<svg width="56px" height="52px" viewBox="0 0 56 52" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> - <defs></defs> - <g id="Desktop" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> - <g id="blog-newsletter-cta-graphic-v2" transform="translate(-1070.000000, -383.000000)" fill="#FFFFFF"> - <g id="gitlab-newsletter-cta-b" transform="translate(948.000000, 363.000000)"> - <g id="Page-1" transform="translate(122.000000, 20.000000)"> - <path d="M53.1397841,30.8022957 L34.558125,44.3561117 L51.1622841,22.9844307 L53.4156477,29.9385534 C53.5192159,30.2590074 53.4081705,30.6062589 53.1397841,30.8022957 Z M2.86117045,30.8027742 C2.59198864,30.6062589 2.48094318,30.2590074 2.58419318,29.9395104 L4.83819318,22.9833141 L21.4412386,44.3634491 L2.86117045,30.8027742 Z M11.2584659,3.11293374 L16.410625,19.0155227 L6.12523864,19.0155227 L11.2584659,3.11293374 Z M36.0973295,21.5676699 L28.0054886,46.5780748 L19.9136477,21.5676699 L36.0973295,21.5676699 Z M44.7420114,3.11277423 L49.8844659,19.0155227 L39.5995568,19.0155227 L44.7420114,3.11277423 Z M31.4494886,44.2040994 L33.126625,39.0203693 L38.7700568,21.578038 L49.0266477,21.578038 L32.9091477,42.3254 L31.4494886,44.2040994 Z M17.2337614,21.578038 L24.5527386,44.1996331 L6.98544318,21.578038 L17.2337614,21.578038 Z M55.8366932,29.1508969 L52.8941477,20.069719 C52.8793523,19.9864552 52.8535795,19.904946 52.8220795,19.8248724 L46.9193295,1.57207485 C46.5984432,0.615657669 45.7433295,-4.78527557e-05 44.7385114,-4.78527557e-05 L44.725625,-4.78527557e-05 C43.7206477,0.00521595093 42.8707841,0.62730184 42.5600795,1.58547362 L36.9236477,19.0155227 L19.0866932,19.0155227 L13.4396023,1.58483558 C13.1295341,0.62746135 12.2796705,0.00537546013 11.2746932,-4.78527557e-05 C10.2687614,-0.00563067484 9.40314773,0.611669939 9.07589773,1.58611166 L3.17648864,19.8628356 C3.17092045,19.8781485 3.16344318,19.8923448 3.15851136,19.9076577 L0.163147727,29.151854 C-0.280556818,30.5249092 0.201329545,32.0172773 1.36269318,32.8658663 L27.2447159,51.755584 C27.4696705,51.919719 27.7320114,51.9999521 27.9932386,51.9999521 C28.2622614,51.9999521 28.5292159,51.9133387 28.7525795,51.746492 C28.753375,51.745854 28.7543295,51.745535 28.755125,51.7448969 L54.6377841,32.8655472 C55.7988295,32.0172773 56.2807159,30.5249092 55.8366932,29.1508969 Z" id="Fill-1"></path> - </g> - </g> - </g> - </g> -</svg> -<div id="above-cta-form"> -<div class="newsletter-preamble"> -New blog posts directly to your inbox -</div> -<div class="newsletter-sub-preamble"> -Sign up for our bi-monthly newsletter -</div> -</div> -<div id="confirm-cta-form" style="display: none;"> -<div class="newsletter-preamble"> -Thanks, you’re -<br /> -signed up! -</div> -<div class="newsletter-sub-preamble"> -GitLab is coming to your inbox -</div> -<img class="success-image" src="/images/emojis/newsletter-signup-success.png" /> -</div> -</div> -<div class="newsletter-form"> -<form class="notdefined" id="mktoForm_1547"> -<script src="//app-ab13.marketo.com/js/forms2/js/forms2.min.js"></script> -<script type="text/javascript"> -MktoForms2.loadForm("//app-ab13.marketo.com", "194-VVC-221", 1547, function(form) { - form.onSuccess(function(values, followUpUrl) { - - form.getFormElem().hide(); - document.getElementById('above-cta-form').style.display = 'none'; - document.getElementById('confirm-cta-form').style.display = 'block'; - - dataLayer.push({event: 'mktoLead',mktoFormId: form.getId()}); - return false; - }); - function getgacid() { - try { - var tracker = ga.getAll()[0]; - return tracker.get('clientId'); - } catch (e) { - return 'n/a'; - } - } - form.vals({ - 'gacid': getgacid() - }); -}); - -</script> -</form> -</div> -</div> - -</div> - -<h2 id="gitlab-at-predict-2019">GitLab at Predict 2019</h2> - -<h3 id="speakers">Speakers</h3> - -<p>During the event on Dec. 18, GitLab's <a href="/company/team/#brandoncjung">Brandon Jung</a>, VP of Alliances, will be speaking at a theater session called "Accelerate software delivery: How to make 2019 your cloud-native year" at 2 p.m. EST.</p> - -<p>Additionally, Senior Product Marketing Manager <a href="/company/team/#cblake2000">Cindy Blake</a> will take part in a panel session, "Ubiquitous Open Source makes for security challenges," at 12 p.m. EST.</p> - -<p>Don’t worry if you are already booked for the day of the event; the virtual conference will be available to attend for 90 days afterwards too.</p> - -<h3 id="booth-and-swag">Booth and swag</h3> - -<p>We will also have a GitLab virtual booth located in the exhibit hall where you will have access to loads of information in the form of videos, webpage links, and pdf files to download and review immediately or take with you for future reference. -You won't even need a bag to carry it all with you! Bonus!</p> - -<p>During the live event we will have GitLabbers on hand to chat with and answer your questions, and if you visit our booth we'll arm you with a code for a FREE GitLab T-shirt from the <a href="https://shop.gitlab.com/">GitLab swag store</a>.</p> - -<p class="alert alert-gitlab-purple"><a href="https://predict2019.com/#join-us">Sign up now to attend Predict 2019</a>!</p> - -<p class="note">Photo by <a href="https://unsplash.com/photos/xGtHjC_QNJM?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">JESHOOTS.COM</a> on <a href="https://unsplash.com/search/photos/virtual-reality?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></p> -<img src='https://about.gitlab.com/images/blogimages/woman-wearing-vr-goggles.jpg' class='webfeedsFeaturedVisual' style='display: none;' /> - - -GitLab's HackerOne Bug Bounty Program is public today - -https://about.gitlab.com/2018/12/12/gitlab-hackerone-bug-bounty-program-is-public-today/ -2018-12-12T00:00:00+00:00 -2018-12-12T00:00:00+00:00 - -Kathy Wang - -<p>Today, we are announcing that our HackerOne bug bounty program is now <a href="https://hackerone.com/gitlab">public</a>. Since we opened our private bounty program in December, 2017, we have been preparing to take this program public by working through some of the challenges of managing a bug bounty program. We have awarded over $200,000 in bounties since the bug bounty program went live last year. This means we mitigated nearly 200 vulnerabilities reported to us.</p> - -<p>Our first response time to newly submitted findings has decreased significantly, from an average time of 48+ hours to 7 hours. That is a significant reduction achieved through security automation, and will help us scale, and better engage the hacker community.</p> - -<div class="newsletter-cta-b panel panel-default panel-newsletter-cta"> -<div class="panel-body newsletter-cta"> -<div class="panel-header"> -<?xml version="1.0" encoding="UTF-8"?> -<svg width="56px" height="52px" viewBox="0 0 56 52" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> - <defs></defs> - <g id="Desktop" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> - <g id="blog-newsletter-cta-graphic-v2" transform="translate(-1070.000000, -383.000000)" fill="#FFFFFF"> - <g id="gitlab-newsletter-cta-b" transform="translate(948.000000, 363.000000)"> - <g id="Page-1" transform="translate(122.000000, 20.000000)"> - <path d="M53.1397841,30.8022957 L34.558125,44.3561117 L51.1622841,22.9844307 L53.4156477,29.9385534 C53.5192159,30.2590074 53.4081705,30.6062589 53.1397841,30.8022957 Z M2.86117045,30.8027742 C2.59198864,30.6062589 2.48094318,30.2590074 2.58419318,29.9395104 L4.83819318,22.9833141 L21.4412386,44.3634491 L2.86117045,30.8027742 Z M11.2584659,3.11293374 L16.410625,19.0155227 L6.12523864,19.0155227 L11.2584659,3.11293374 Z M36.0973295,21.5676699 L28.0054886,46.5780748 L19.9136477,21.5676699 L36.0973295,21.5676699 Z M44.7420114,3.11277423 L49.8844659,19.0155227 L39.5995568,19.0155227 L44.7420114,3.11277423 Z M31.4494886,44.2040994 L33.126625,39.0203693 L38.7700568,21.578038 L49.0266477,21.578038 L32.9091477,42.3254 L31.4494886,44.2040994 Z M17.2337614,21.578038 L24.5527386,44.1996331 L6.98544318,21.578038 L17.2337614,21.578038 Z M55.8366932,29.1508969 L52.8941477,20.069719 C52.8793523,19.9864552 52.8535795,19.904946 52.8220795,19.8248724 L46.9193295,1.57207485 C46.5984432,0.615657669 45.7433295,-4.78527557e-05 44.7385114,-4.78527557e-05 L44.725625,-4.78527557e-05 C43.7206477,0.00521595093 42.8707841,0.62730184 42.5600795,1.58547362 L36.9236477,19.0155227 L19.0866932,19.0155227 L13.4396023,1.58483558 C13.1295341,0.62746135 12.2796705,0.00537546013 11.2746932,-4.78527557e-05 C10.2687614,-0.00563067484 9.40314773,0.611669939 9.07589773,1.58611166 L3.17648864,19.8628356 C3.17092045,19.8781485 3.16344318,19.8923448 3.15851136,19.9076577 L0.163147727,29.151854 C-0.280556818,30.5249092 0.201329545,32.0172773 1.36269318,32.8658663 L27.2447159,51.755584 C27.4696705,51.919719 27.7320114,51.9999521 27.9932386,51.9999521 C28.2622614,51.9999521 28.5292159,51.9133387 28.7525795,51.746492 C28.753375,51.745854 28.7543295,51.745535 28.755125,51.7448969 L54.6377841,32.8655472 C55.7988295,32.0172773 56.2807159,30.5249092 55.8366932,29.1508969 Z" id="Fill-1"></path> - </g> - </g> - </g> - </g> -</svg> -<div id="above-cta-form"> -<div class="newsletter-preamble"> -New blog posts directly to your inbox -</div> -<div class="newsletter-sub-preamble"> -Sign up for our bi-monthly newsletter -</div> -</div> -<div id="confirm-cta-form" style="display: none;"> -<div class="newsletter-preamble"> -Thanks, you’re -<br /> -signed up! -</div> -<div class="newsletter-sub-preamble"> -GitLab is coming to your inbox -</div> -<img class="success-image" src="/images/emojis/newsletter-signup-success.png" /> -</div> -</div> -<div class="newsletter-form"> -<form class="notdefined" id="mktoForm_1547"> -<script src="//app-ab13.marketo.com/js/forms2/js/forms2.min.js"></script> -<script type="text/javascript"> -MktoForms2.loadForm("//app-ab13.marketo.com", "194-VVC-221", 1547, function(form) { - form.onSuccess(function(values, followUpUrl) { - - form.getFormElem().hide(); - document.getElementById('above-cta-form').style.display = 'none'; - document.getElementById('confirm-cta-form').style.display = 'block'; - - dataLayer.push({event: 'mktoLead',mktoFormId: form.getId()}); - return false; - }); - function getgacid() { - try { - var tracker = ga.getAll()[0]; - return tracker.get('clientId'); - } catch (e) { - return 'n/a'; - } - } - form.vals({ - 'gacid': getgacid() - }); -}); - -</script> -</form> -</div> -</div> - -</div> - -<p>On average, our mean time to mitigation (MTTR) for critical security issues is currently less than 30 days. Our current goal is to now focus on bringing the MTTR metric for medium-high security issues to less than 60 days, on average.</p> - -<p>Yesterday, we released a <a href="https://www.hackerone.com/resources/gitlab-hps-for-startups">webinar</a> to announce our plans to be a public bug bounty program. In managing a <a href="https://hackerone.com/gitlab">public bug bounty program</a>, we will now be able to reward our hacker community for reporting security vulnerabilities to us directly through the program.</p> - -<p>The past year has been a great journey of learning about managing a bug bounty program, and we have plans to further expand upon our public program in 2019 and beyond. We would also like to acknowledge some of our top contributors from the hacker community, including <a href="https://hackerone.com/ngalog">ngalog</a>, <a href="https://hackerone.com/jobert">jobert</a>, and <a href="https://hackerone.com/fransrosen">fransrosen</a>. Check out the <a href="https://hackerone.com/gitlab">program</a> to see how you can contribute!</p> -<img src='https://about.gitlab.com/images/blogimages/security-cover.png' class='webfeedsFeaturedVisual' style='display: none;' /> - - -Announcing GitLab Serverless - -https://about.gitlab.com/2018/12/11/introducing-gitlab-serverless/ -2018-12-11T00:00:00+00:00 -2018-12-11T00:00:00+00:00 - -Priyanka Sharma - -<p>Serverless is the latest innovation in cloud computing that promises to alter the cost-benefit equation for enterprises. As our CEO, <a href="/company/team/#sytses">Sid Sijbrandij</a> says, "All roads lead to compute." There is a race among providers to acquire as many workloads from enterprises as possible, at the cheapest cost. The latter is where serverless comes in: serverless computing is an execution model in which the cloud provider acts as the server, dynamically managing the allocation of machine resources. Pricing is based on the actual resources consumed by an application, rather than on pre-purchased units of capacity.</p> - -<p>This field began with the release of <a href="https://en.wikipedia.org/wiki/AWS_Lambda">AWS Lambda</a> in November 2014. In the four short years since then, it has become a well-known workflow that enterprises are eager to adopt. Today, we are announcing <a href="/product/serverless/">GitLab Serverless</a> to enable our users to take advantage of the benefits of serverless.</p> - -<h2 id="gitlab-serverless-is-launching-dec-22">GitLab Serverless is launching Dec. 22</h2> - -<p>GitLab is the only single application for the entire DevOps lifecycle. As part of that vision, we will release GitLab Serverless in GitLab 11.6, coming later this month, to allow enterprises to plan, build, and manage serverless workloads with the rest of their code from within the same GitLab UI. It leverages <a href="https://cloud.google.com/knative/">Knative</a>, which enables <a href="https://en.wikipedia.org/wiki/Autoscaling">autoscaling</a> down to zero and back up to run serverless workloads on Kubernetes. This allows businesses to employ a multi-cloud strategy and leverage the value of serverless without being locked into a specific cloud provider.</p> - -<p>In order to bring the best-in-class to our users, we partnered with <a href="https://triggermesh.com/">TriggerMesh</a> founder <a href="https://twitter.com/sebgoa">Sebastien Goasguen</a> and his team. Sebastien has been part of the serverless landscape since the beginning. He built a precursor to Knative, Kubeless. He is actively involved with the Knative community and understands the workflow from soup to nuts. Sebastien says, "We are excited to help GitLab enable all their users to deploy functions directly on the Knative function-as-a-service clusters. We believe that these additions to GitLab will give those users the best possible experience for complete serverless computing from beginning to end."</p> - -<h2 id="serverless-first">"Serverless first"</h2> - -<p>As any attendees at <a href="/2018/12/06/aws-reinvent-recap/">AWS re:Invent</a> would have noticed, the behemoth is putting all its energies behind serverless. We heard <a href="https://www.computerworlduk.com/cloud-computing/how-trustpilot-takes-serverless-first-approach-engineering-with-aws-3688267/">stories from the likes of TrustPilot</a> about changing their engineering culture to "serverless first." This is because serverless cloud providers save money by not having to keep idle machines provisioned and running, and are passing on the benefits to their customers. While this is amazing news, it is hard to truly embrace a workflow if it lives outside of developers' entrenched habits. GitLab has millions of users and is used by over 100,000 organizations, and with GitLab Serverless they can now enjoy the cost savings and elegant code design serverless brings, from the comfort of their established workflows.</p> - -<p>As with all GitLab endeavors, making serverless multi-cloud and accessible to everyone is a big, hairy, audacious goal. Today, Knative can be installed to a Kubernetes cluster with a single click via the GitLab Kubernetes integration. It shipped in <a href="/2018/11/22/gitlab-11-5-released/#easily-deploy-and-integrate-knative-with-gitlab">GitLab 11.5</a>.</p> - -<h3 id="how-to-activate-gitlab-serverless">How to activate GitLab Serverless</h3> - -<p>Starting with the release of GitLab 11.6 on Dec. 22, the "Serverless" tab will be available for users as an alpha offering. Please do check it out and share your feedback with us.</p> - -<ol> - <li>Go to your GitLab instance and pick your project of choice.</li> - <li>Click on the <code>Operations</code> menu item in the sidebar.</li> - <li>Pick <code>Serverless</code> to view the list of all the functions you have defined. You will also be able to see a brief description as well as the Knative cluster the function is deploying to.</li> -</ol> - -<p><img src="https://gitlab.com/gitlab-org/gitlab-ce/uploads/8b821d4aaa1bb75375dc54567a4313ad/CE-project__serverless-grouped.png" alt="Serverless list view" title="Serverless list view" class="shadow large center" /></p> - -<p>To dig further, click into the function for more info.</p> - -<p><img src="https://gitlab.com/gitlab-org/gitlab-ce/uploads/9e1e3893aa5369a2a165d1dd95c98dd8/CE-project__serverless--function-details.png" alt="function detail view" title="function detail view" class="shadow large center" /></p> - -<p>All this goodness will be available Dec. 22. In the meantime, we would love to see you at <a href="/events">KubeCon Seattle</a>, where our product and engineering experts are attending to talk all things serverless with attendees. Hope to see you at booth S44!</p> -<img src='https://about.gitlab.com/images/blogimages/gitlab-serverless-blog.png' class='webfeedsFeaturedVisual' style='display: none;' /> - - -Friends don't let friends add options to code - -https://about.gitlab.com/2018/12/10/friends-dont-let-friends-add-options-to-code/ -2018-12-10T00:00:00+00:00 -2018-12-10T00:00:00+00:00 - -Suri Patel - -<p>Sometimes, when trying to make it easier to work in an application, our instinct is to add -optional features that users can enable if their situations require a specific functionality. -Our intentions may be good, but these actions can actually cause <em>more</em> problems, since we invite users - to second-guess their choices by adding extra steps into the user experience.</p> - -<h2 id="the-disadvantages-of-a-choose-your-own-adventure-model">The disadvantages of a <a href="https://en.wikipedia.org/wiki/Choose_Your_Own_Adventure">choose your own adventure</a> model</h2> - -<p>One of the most celebrated aspects of <a href="/solutions/open-source/">open source</a> -is the freedom that allows developers to brighten a user’s day by adding an -optional feature that may not be for everyone, but allows a small portion of users -to engage with a project in a specific way. While it may seem like a great idea -to cater to individual needs, there are several disadvantages to making something -an option.</p> - -<h3 id="it-creates-more-work-for-developers">It creates more work for developers</h3> - -<p>Creating extra options means more work for both frontend and backend teams. -These features add additional code, tests, and documentation for each setting, -and the various states alter the UI. Adding options hurts you in every step of -the development process.</p> - -<h3 id="it-places-a-burden-on-the-user-to-choose">It places a burden on the user to choose</h3> - -<p>When we solve problems by including options, we force a user to think about the -function and consider its purpose and drawbacks, placing a burden on them to -control how they use an application. A user hesitates and has to make a decision -about whether this is something that should be enabled. After all, if an option -significantly enhanced the user experience, then wouldn’t it have been automatically -integrated?</p> - -<h3 id="it-makes-future-functionality-more-difficult-to-implement">It makes future functionality more difficult to implement</h3> - -<p>There's also the long-term impact of additional options. Just one extra option can lead to one of two -paths, which might influence other parts of an application. So, every -time we add an option, the number of states of the application doubles. That's -exponential growth and it adds up quickly, making it harder to diagnose errors. Multiple -options can lead to the creation of states of which we’re unaware, so -it’s harder for the user to understand how an application should behave, because -they don't know whether errors are due to an option or not. And, if it is an -option causing the error, <em>which</em> option is the problem?</p> - -<h2 id="how-we-avoid-adding-options-bask-in-the-glow-of-iteration">How we avoid adding options: Bask in the glow of iteration</h2> - -<p>So, how do you know if a feature should be optional or not? At GitLab, we ship -the first <a href="/handbook/values/#iteration">iteration</a> and keep delivering based on -user feedback. Some of the features that we anticipated may never roll out, -because users didn’t request them. Iteration allows us to reduce the scope of -development and avoid including features that aren’t popular or useable.</p> - -<div class="newsletter-cta-b panel panel-default panel-newsletter-cta"> -<div class="panel-body newsletter-cta"> -<div class="panel-header"> -<?xml version="1.0" encoding="UTF-8"?> -<svg width="56px" height="52px" viewBox="0 0 56 52" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> - <defs></defs> - <g id="Desktop" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> - <g id="blog-newsletter-cta-graphic-v2" transform="translate(-1070.000000, -383.000000)" fill="#FFFFFF"> - <g id="gitlab-newsletter-cta-b" transform="translate(948.000000, 363.000000)"> - <g id="Page-1" transform="translate(122.000000, 20.000000)"> - <path d="M53.1397841,30.8022957 L34.558125,44.3561117 L51.1622841,22.9844307 L53.4156477,29.9385534 C53.5192159,30.2590074 53.4081705,30.6062589 53.1397841,30.8022957 Z M2.86117045,30.8027742 C2.59198864,30.6062589 2.48094318,30.2590074 2.58419318,29.9395104 L4.83819318,22.9833141 L21.4412386,44.3634491 L2.86117045,30.8027742 Z M11.2584659,3.11293374 L16.410625,19.0155227 L6.12523864,19.0155227 L11.2584659,3.11293374 Z M36.0973295,21.5676699 L28.0054886,46.5780748 L19.9136477,21.5676699 L36.0973295,21.5676699 Z M44.7420114,3.11277423 L49.8844659,19.0155227 L39.5995568,19.0155227 L44.7420114,3.11277423 Z M31.4494886,44.2040994 L33.126625,39.0203693 L38.7700568,21.578038 L49.0266477,21.578038 L32.9091477,42.3254 L31.4494886,44.2040994 Z M17.2337614,21.578038 L24.5527386,44.1996331 L6.98544318,21.578038 L17.2337614,21.578038 Z M55.8366932,29.1508969 L52.8941477,20.069719 C52.8793523,19.9864552 52.8535795,19.904946 52.8220795,19.8248724 L46.9193295,1.57207485 C46.5984432,0.615657669 45.7433295,-4.78527557e-05 44.7385114,-4.78527557e-05 L44.725625,-4.78527557e-05 C43.7206477,0.00521595093 42.8707841,0.62730184 42.5600795,1.58547362 L36.9236477,19.0155227 L19.0866932,19.0155227 L13.4396023,1.58483558 C13.1295341,0.62746135 12.2796705,0.00537546013 11.2746932,-4.78527557e-05 C10.2687614,-0.00563067484 9.40314773,0.611669939 9.07589773,1.58611166 L3.17648864,19.8628356 C3.17092045,19.8781485 3.16344318,19.8923448 3.15851136,19.9076577 L0.163147727,29.151854 C-0.280556818,30.5249092 0.201329545,32.0172773 1.36269318,32.8658663 L27.2447159,51.755584 C27.4696705,51.919719 27.7320114,51.9999521 27.9932386,51.9999521 C28.2622614,51.9999521 28.5292159,51.9133387 28.7525795,51.746492 C28.753375,51.745854 28.7543295,51.745535 28.755125,51.7448969 L54.6377841,32.8655472 C55.7988295,32.0172773 56.2807159,30.5249092 55.8366932,29.1508969 Z" id="Fill-1"></path> - </g> - </g> - </g> - </g> -</svg> -<div id="above-cta-form"> -<div class="newsletter-preamble"> -New blog posts directly to your inbox -</div> -<div class="newsletter-sub-preamble"> -Sign up for our bi-monthly newsletter -</div> -</div> -<div id="confirm-cta-form" style="display: none;"> -<div class="newsletter-preamble"> -Thanks, you’re -<br /> -signed up! -</div> -<div class="newsletter-sub-preamble"> -GitLab is coming to your inbox -</div> -<img class="success-image" src="/images/emojis/newsletter-signup-success.png" /> -</div> -</div> -<div class="newsletter-form"> -<form class="notdefined" id="mktoForm_1547"> -<script src="//app-ab13.marketo.com/js/forms2/js/forms2.min.js"></script> -<script type="text/javascript"> -MktoForms2.loadForm("//app-ab13.marketo.com", "194-VVC-221", 1547, function(form) { - form.onSuccess(function(values, followUpUrl) { - - form.getFormElem().hide(); - document.getElementById('above-cta-form').style.display = 'none'; - document.getElementById('confirm-cta-form').style.display = 'block'; - - dataLayer.push({event: 'mktoLead',mktoFormId: form.getId()}); - return false; - }); - function getgacid() { - try { - var tracker = ga.getAll()[0]; - return tracker.get('clientId'); - } catch (e) { - return 'n/a'; - } - } - form.vals({ - 'gacid': getgacid() - }); -}); - -</script> -</form> -</div> -</div> - -</div> - -<p>Whenever users need something new, try to create a solution that's acceptable -for the most number of people. Rely on your development and operations teams to -provide feedback and ask them to relate to the end user. Conducting -<a href="/handbook/engineering/ux/ux-research/#ux-research">UX research</a> with your users -also helps identify pain points and needs.</p> - -<p>Teams are continually constrained by development capacity, and adding options to -applications can absorb previous time and effort. We suggest shipping your -application without an option and waiting to see whether people request it or -make a -<a href="https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name%5B%5D=feature+proposal">feature proposal</a> -for it. In the end, our role is to solve users’ problems, and our goal is to -identify the underlying cause of a challenge and fix it in a way that doesn't -need an option.</p> - -<p class="note"><a href="https://unsplash.com/photos/pKeF6Tt3c08">Cover image</a> by <a href="https://unsplash.com/@bdchu614">Brendan Church</a> on Unsplash</p> -<img src='https://about.gitlab.com/images/blogimages/options.jpg' class='webfeedsFeaturedVisual' style='display: none;' /> - - -Git Protocol v2 now enabled for SSH on GitLab.com - -https://about.gitlab.com/2018/12/10/git-protocol-v2-enabled-for-ssh-on-gitlab-dot-com/ -2018-12-10T00:00:00+00:00 -2018-12-10T00:00:00+00:00 - -James Ramsay - -<p>GitLab added support for <a href="/2018/10/22/gitlab-11-4-released/#git-protocol-v2">Git Protocol v2 over HTTP and SSH in GitLab 11.4</a>, and enabled Protocol v2 over HTTP on GitLab.com, but not for SSH. On Nov. 23, we enabled <a href="https://gitlab.com/gitlab-com/gl-infra/infrastructure/issues/5244">Git Protocol v2 over SSH on GitLab.com</a>. You can view Git Protocol usage on our <a href="https://dashboards.gitlab.com/d/pqlQq0xik/git-protocol-versions?refresh=5m&amp;orgId=1">public dashboard</a>.</p> - -<p>Git Protocol v2 is supported from Git v2.18.0 and is opt-in. To enable globally, run <code>git config --global protocol.version 2</code>.</p> - -<h2 id="what-git-protocol-v2-means-for-you">What Git Protocol v2 means for you</h2> - -<p>Git 2.18 introduced support for Protocol v2, which defines how clones, fetches, and pushes are communicated between the client (your computer) and the server (GitLab). The new <a href="https://www.kernel.org/pub/software/scm/git/docs/technical/pack-protocol.html">wire protocol</a> improves the performance of fetch commands and enables future protocol improvements. <a href="https://opensource.googleblog.com/2018/05/introducing-git-protocol-version-2.html">Read more about Protocol v2</a> in the release post by the author of the change.</p> - -<p>To see the reduction in network traffic with Protocol v2 you can run the commands below:</p> - -<pre class="highlight plaintext"><code># Original Git wire protocol -GIT_TRACE_PACKET=1 git -c protocol.version=0 ls-remote git@gitlab.com:gitlab-org/gitlab-ce.git master - -# New Git wire protocol v2 -GIT_TRACE_PACKET=1 git -c protocol.version=2 ls-remote git@gitlab.com:gitlab-org/gitlab-ce.git master -</code></pre> -<p>In moving from Protocol v0 to v2, on this repo the number of lines ("packets") sent behind the scenes drops from over 36,000 to fewer than 30.</p> -<img src='https://about.gitlab.com/images/default-blog-image.png' class='webfeedsFeaturedVisual' style='display: none;' /> - - -Highlights from AWS re:Invent 2018 - -https://about.gitlab.com/2018/12/06/aws-reinvent-recap/ -2018-12-06T00:00:00+00:00 -2018-12-06T00:00:00+00:00 - -Priyanka Sharma - -<p>Last week GitLab was at AWS re:Invent 2018, the marquee event for cloud computing in the US. As the frontrunner in the space, Amazon has built re:Invent to be a juggernaut. This year it commanded most of the Las Vegas strip and had over 50,000 attendees. As a first-time visitor myself, I was impressed by the sheer scale and efficiency of the event. I was also thrilled to achieve my personal goal of giving my first talk with a live demo using code and GitLab. As for GitLab, we saw that our company emerged as a leader in the DevOps space with a single application for the whole software development lifecycle.</p> - -<h2 id="highlights">Highlights</h2> - -<h3 id="reinventing-cicd-pipelines">Reinventing CI/CD pipelines</h3> - -<p>Our CEO <a href="/company/team/#sytses">Sid Sijbrandij</a> and I did a talk and live demo about reinventing CI/CD pipelines using GitLab, <a href="/kubernetes">Kubernetes</a>, and EKS. This was our first hint that this re:Invent was going to be special. The talk was bursting at the seams with attendees, as we shared both the challenges of the toolchain crisis engulfing our ecosystem, and about how a single application for the entire DevOps lifecycle can make an improvement of over 200 percent in cycle times. You can <a href="https://docs.google.com/presentation/d/1x1g4pfpoaav9lhcYkjAJylLMl-9S0JFTeKXlNF98O-I/edit?usp=sharing">check out the presentation here</a>.</p> - -<p><img src="/images/blogimages/aws-2018/aws_2018_sid_talk_stage.jpeg" alt="Sid Sijbrandij and Priyanka Sharma on stage at AWS re:Invent" class="shadow medium center" /></p> - -<p>The demo, which showed us running a CI/CD pipeline and deploying code to Kubernetes on EKS, is an example of the <a href="/cloud-native/">cloud native workflows</a> users can push via GitLab. It is such competency that makes Kubernetes on EKS a breeze and is the reason GitLab was awarded the <a href="/2018/11/28/gitlab-achieves-aws-devops-competency-certification/">AWS Partner DevOps Competency Certification</a> to confirm our viability and excellence as a DevOps solution for companies using AWS Cloud.</p> - -<h3 id="validation-for-our-vision">Validation for our vision</h3> - -<p>Our experience at re:Invent was one of validation and emergence. As a company, we saw that our efforts to build the first single application for the entire DevOps lifecycle have paid off and our users resonated with our message. Most folks who came to our booth were aware that GitLab played a part in multiple stages (if not all) of their workflow and many were avid <a href="/product/continuous-integration/">GitLab CI</a> fans. Gone are the days when <a href="https://docs.gitlab.com/ee/workflow/gitlab_flow.html">version control</a> was the only thing GitLab was associated with.</p> - -<p><img src="/images/blogimages/aws-2018/aws_booth_collage.jpeg" alt="Collage from GitLab at AWS re:Invent" class="medium center" /></p> - -<p>Our VP of Alliances, <a href="/company/team/#brandoncjung">Brandon Jung</a>, <a href="https://www.youtube.com/watch?v=Ejs5xGAhL8s">appeared on theCUBE</a> with a company called Beacon. As the former head of partnerships at Google Cloud, Brandon has a long history with GitLab. He has seen the company grow over the years and shared how our rocketship ascent across the DevOps lifecycle convinced him of the potential. He said, "In just over two years, <a href="/2017/09/27/gitlab-leader-continuous-integration-forrester-wave/">GitLab became the frontrunner for continuous integration</a>, according to Forrester. That's impressive."</p> - -<h3 id="livestream-with-the-new-stack">Livestream with The New Stack</h3> - -<p>I also represented GitLab on <a href="https://www.pscp.tv/w/1eaJbODAepnxX">a livestream podcast</a> with <a href="https://thenewstack.io/">The New Stack</a>, <a href="https://twitter.com/biilmann?lang=en">Matt Biilmann</a>, CEO of <a href="/2018/06/13/netlify-launches-gitlab-support/">Netlify</a>, and <a href="https://twitter.com/jbeda">Joe Beda</a>, founder of <a href="https://heptio.com/">Heptio</a> and creator of Kubernetes. We discussed GitOps, NoOps, and the toolchain crisis. As Matt wisely said, "Trust in open source is critical to cloud computing and the ecosystem. Companies like GitLab will keep the players honest."</p> - -<div class="center"> - - <blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">GitOps, NoOps and the tool chain crisis. <a href="https://t.co/mtfm8OaYYD">https://t.co/mtfm8OaYYD</a></p>&mdash; The New Stack (@thenewstack) <a href="https://twitter.com/thenewstack/status/1067881587214184448?ref_src=twsrc%5Etfw">November 28, 2018</a></blockquote> - <script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> - -</div> - -<p>We thank AWS for creating this amazing ecosystem of end users and practitioners who came together in Vegas last week. Next year will be bigger, better. Until then, see you all at <a href="/events/">KubeCon</a>! 😃</p> -<img src='https://about.gitlab.com/images/blogimages/aws-2018/aws_booth_2018.jpeg' class='webfeedsFeaturedVisual' style='display: none;' /> - - -GitLab Critical Security Release: 11.5.3, 11.4.10, 11.3.12 - -https://about.gitlab.com/2018/12/06/critical-security-release-gitlab-11-dot-5-dot-3-released/ -2018-12-06T00:00:00+00:00 -2018-12-06T00:00:00+00:00 - -Ethan Strike - -<p>Today we are releasing versions 11.5.3, 11.4.10, and 11.3.12 for GitLab Community Edition (CE) and Enterprise Edition (EE).</p> - -<p>These versions contain an important security fix, and we strongly recommend that all GitLab installations be upgraded to one of these versions immediately.</p> - - - -<p>The vulnerability details will be made public on our issue tracker in approximately 30 days.</p> - -<p>Please read on for more information regarding this release.</p> - -<h2 id="directory-traversal-in-templates-api">Directory Traversal in Templates API</h2> - -<p>The templates api was vulnerable to a directory traversal issue which could allow an attacker to read arbitrary files on a GitLab server. The issue is now mitigated in the latest release and is assigned <a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-19856">CVE-2018-19856</a>.</p> - -<p>Thanks to <a href="https://hackerone.com/nyangawa">@nyangawa</a> of Chaitin Tech for responsibly reporting this vulnerability to us.</p> - -<h3 id="versions-affected">Versions Affected</h3> - -<p>Affects GitLab CE/EE 8.11 and later.</p> - -<h3 id="remediation">Remediation</h3> - -<p>We <strong>strongly recommend</strong> that all installations running an affected version above to be upgraded to the latest version as soon as possible.</p> - -<h2 id="updating">Updating</h2> - -<p>To update, check out our <a href="/update">update page</a>.</p> -<img src='https://about.gitlab.com/images/default-blog-image.png' class='webfeedsFeaturedVisual' style='display: none;' /> - - -GitLab Runner update required to use SAST in Auto DevOps - -https://about.gitlab.com/2018/12/06/gitlab-runner-update-required-to-use-auto-devops-and-sast/ -2018-12-06T00:00:00+00:00 -2018-12-06T00:00:00+00:00 - -Fabio Busatto - -<p>We are introducing a major change for the <a href="https://docs.gitlab.com/ee/user/project/merge_requests/sast.html">SAST</a> job definition for <a href="https://docs.gitlab.com/ee/topics/autodevops/">Auto DevOps</a> with <strong>GitLab 11.6</strong>, shipping Dec. 22. -As a result, SAST jobs will fail after the upgrade to GitLab 11.6 if they are picked up by a version of <a href="https://docs.gitlab.com/runner/">GitLab Runner</a> -prior to 11.5. The jobs will fail, but they will not block pipelines. However, you won't see results -for SAST in the merge request or at the pipeline level anymore.</p> - -<p>The same change will happen for <a href="https://docs.gitlab.com/ee/user/project/merge_requests/dependency_scanning.html">Dependency Scanning</a>, <a href="https://docs.gitlab.com/ee/user/project/merge_requests/container_scanning.html">Container Scanning</a>, <a href="https://docs.gitlab.com/ee/user/project/merge_requests/dast.html">DAST</a>, and <a href="https://docs.gitlab.com/ee/user/project/merge_requests/license_management.html">License Management</a> in future releases.</p> - -<h2 id="why-did-this-happen">Why did this happen?</h2> - -<p>The <a href="https://docs.gitlab.com/ee/ci/examples/sast.html">new job definition</a> uses the <a href="https://docs.gitlab.com/ee/ci/yaml/README.html#artifactsreportssast-ultimate"><code>reports</code> syntax</a>, which is necessary to show SAST results in the <a href="https://docs.gitlab.com/ee/user/group/security_dashboard/">Group Security Dashboard</a>. -Unfortunately, this syntax is not supported by GitLab Runner prior to 11.5.</p> - -<h2 id="who-is-affected">Who is affected?</h2> - -<p>You are affected by this change if you meet <strong>all</strong> the requirements in the following list:</p> -<ol> - <li>You are using Auto DevOps <strong>AND</strong></li> - <li>you have at least one GitLab Runner 11.4 or older set up for your projects <strong>AND</strong></li> - <li>you are interested in security reports.</li> -</ol> - -<h2 id="who-is-not-affected">Who is not affected?</h2> - -<p>You are <strong>not</strong> affected by this change if you meet <strong>at least one</strong> of the requirements in the following list:</p> -<ol> - <li>You are not using Auto DevOps <strong>OR</strong></li> - <li>you are using only GitLab Runner 11.5 or newer <strong>OR</strong></li> - <li>you are using only shared runners on GitLab.com (we already upgraded them) <strong>OR</strong></li> - <li>you are not interested in security reports.</li> -</ol> - -<h2 id="how-to-solve-the-problem">How to solve the problem</h2> - -<p>If you are not affected by the change, you don't need to take any action.</p> - -<p>If you are affected, you should upgrade your GitLab Runners to version 11.5 or newer as soon as possible. -If you don't, you will not have new SAST reports until you do upgrade. If you upgrade your runners later, SAST will -start to work again correctly.</p> - -<h2 id="which-is-the-expected-timeline">Which is the expected timeline?</h2> - -<p>GitLab 11.6 will be released on <strong>Dec. 22</strong>. This change may also be shipped in an early release -candidate (RC) version.</p> - -<p>If you are using a <strong>self-managed</strong> GitLab instance, and you don't install RC versions, you will be affected when -you'll upgrade to GitLab 11.6.</p> - -<p>If you are using <strong>GitLab.com</strong>, you will be affected as soon as the RC version with the change will be deployed.</p> - -<p>Feel free to reach out to us with any further questions!</p> - -<img src='https://about.gitlab.com/images/default-blog-image.png' class='webfeedsFeaturedVisual' style='display: none;' /> - - -Introducing Patroni as the Postgres Failover Manager on GitLab.com - -https://about.gitlab.com/2018/12/05/availability-postgres-patroni/ -2018-12-05T00:00:00+00:00 -2018-12-05T00:00:00+00:00 - -Gerardo Lopez-Fernandez - -<h2 id="upcoming-maintenance-windows-for-patroni-deployment">Upcoming Maintenance Windows for Patroni Deployment</h2> - -<p>We are writing this post to let our community know we are planning on performing the work necessary -to deploy <a href="https://github.com/zalando/patroni">Patroni</a> as the Postgres Failover Manager on GitLab.com over two weekends: a dry-run to test -our migration plan and tools on Saturday, Dec 8, 2018, and the actual deployment on Saturday, December -15, 2018.</p> - -<p>During the maintenance windows, the following services will be unavailable:</p> - -<ul> - <li>SaaS website (<a href="https://gitlab.com/">GitLab.com</a> will be offline, but <a href="https://about.gitlab.com/">about.gitlab.com</a> and <a href="https://docs.gitlab.com/">docs.gitlab.com</a> will still be available)</li> - <li>Git ssh</li> - <li>Git https</li> - <li>registry</li> - <li>CI/CD</li> - <li>Pages</li> -</ul> - -<h3 id="maintenance-window---dry-run---saturday-december-8-at-1300-utc">Maintenance Window - Dry run - Saturday, December 8 at 13:00 UTC</h3> - -<p>We will perform testing and validation of our deployment procedures and tools during this maintenance -window to do final readiness checks. This maintenance window should last 30 minutes.</p> - -<h3 id="maintenance-window---actual-cutover---saturday-december-15-at-1300-utc">Maintenance Window - Actual Cutover - Saturday, December 15 at 13:00 UTC</h3> - -<p>On the day of the cutover, we are planning to start at 13:00 UTC. The time window for GitLab.com to be -in maintenance is currently planned to be 30 minutes. Should any times for this change, we will be updating -on the channels listed below. When this window is completed GitLab.com will be running Patroni.</p> - -<ul> - <li><a href="https://status.gitlab.com/">GitLab Status page</a></li> - <li><a href="https://twitter.com/gitlabstatus">GitLab Status Twitter</a></li> -</ul> - -<img src='https://about.gitlab.com/images/blogimages/gitlab-gke-integration-cover.png' class='webfeedsFeaturedVisual' style='display: none;' /> - - -GitLab Patch Release: 11.5.2 - -https://about.gitlab.com/2018/12/04/gitlab-11-5-2-released/ -2018-12-04T00:00:00+00:00 -2018-12-04T00:00:00+00:00 - -Cindy Pallares - -<p>Today we are releasing version 11.5.2 for GitLab Community Edition and Enterprise Edition.</p> - -<p>This version resolves a number of regressions and bugs in -<a href="/2018/11/22/gitlab-11-5-released/">this month's 11.5.0 release</a> and -prior versions.</p> - -<h2 id="gitlab-community-edition-and-enterprise-edition">GitLab Community Edition and Enterprise Edition</h2> - -<p>Available in GitLab Core, Starter, Premium, and Ultimate:</p> - -<ul> - <li><a href="https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22916">Fix impersonation token value not displaying after creation</a></li> - <li><a href="https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/23112">Fix emoji not rendering in filter dropdown</a></li> - <li><a href="https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/23195">Fix the dimensions of image diffs</a></li> - <li><a href="https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/23306">Correctly handle data-loss scenarios when encrypting columns</a></li> - <li><a href="https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/23244">Fix stuck tooltip on stop env button</a></li> - <li><a href="https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/23279">Allow commenting to resolved non-diff discussions</a></li> - <li><a href="https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/23314">Remove Site Statistic</a></li> - <li><a href="https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/23308">Clear BatchLoader context between Sidekiq jobs</a></li> - <li><a href="https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/23321">Update issue boards images for recent cards redesign</a></li> - <li><a href="https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/23247">New Crowdin translations</a></li> -</ul> - -<p>Available in GitLab Starter, Premium, and Ultimate:</p> - -<ul> - <li><a href="https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/8543">Fill timestamp for Approver bulk insertion</a></li> - <li><a href="https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/8509">Fix issues analytics query</a></li> - <li><a href="https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/8466">Exclude code owner from merge request participants to avoid spam</a></li> -</ul> - -<p>Available in GitLab Ultimate:</p> - -<ul> - <li><a href="https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/8494">Add additional requirements to Security Dashboard</a></li> - <li><a href="https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/8459">Resolve inability to scroll operations dashboard</a></li> -</ul> - -<h2 id="omnibus-gitlab">Omnibus GitLab</h2> - -<ul> - <li><a href="https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests/2871">Make remote-syslog template use correct log directory</a></li> -</ul> - -<h2 id="upgrade-barometer">Upgrade barometer</h2> - -<p>Please be aware that by default the Omnibus packages will stop, run migrations, -and start again, no matter how “big” or “small” the upgrade is. This behavior -can be changed by adding a <a href="http://docs.gitlab.com/omnibus/update/README.html"><code>/etc/gitlab/skip-auto-migrations</code></a> file, -which is only used for <a href="https://docs.gitlab.com/omnibus/update/README.html">updates</a>.</p> - -<h2 id="updating">Updating</h2> - -<p>To update, check out our <a href="/update/">update page</a>.</p> - -<h2 id="gitlab-subscriptions">GitLab subscriptions</h2> - -<p>Access to GitLab Starter, Premium, and Ultimate features is granted by a paid <a href="/pricing/">subscription</a>.</p> - -<p>Alternativelly, <a href="https://gitlab.com/users/sign_in">sign up for GitLab.com</a> -to use GitLab's own infrastructure.</p> -<img src='https://about.gitlab.com/images/default-blog-image.png' class='webfeedsFeaturedVisual' style='display: none;' /> - - -Crossplane lowers the barrier to a multi-cloud future - -https://about.gitlab.com/2018/12/04/opensource-multi-cloud-crossplane/ -2018-12-04T00:00:00+00:00 -2018-12-04T00:00:00+00:00 - -Sid Sijbrandij - -<p>Cloud computing has become the dominant IT paradigm and multi-cloud looks poised to be the primary approach, with <a href="https://www.rightscale.com/blog/cloud-industry-insights/cloud-computing-trends-2018-state-cloud-survey">81 percent of enterprises</a> already adopting a multi-cloud strategy.</p> - -<p>A multi-cloud strategy prevents vendor lock-in, which is increasingly important as three major providers (AWS, GCP, and Azure) dominate the market. Despite the many benefits of a multi-cloud strategy, deploying across multiple clouds is still incredibly complex. While Kubernetes has emerged as the standard container orchestration platform, most organizations are running more than just container workloads, and there’s currently no standard for workload portability across managed services. What’s needed is a consistent, multi-cloud, open source interface, and we think there’s a new, interesting project up for the challenge.</p> - -<h2 id="crossplane-aims-to-simplify-multi-cloud-strategy">Crossplane aims to simplify multi-cloud strategy</h2> - -<p>Crossplane, <a href="https://crossplane.io/">announced today</a>, is an open source multi-cloud control plane sponsored by <a href="https://upbound.io">Upbound</a>. Crossplane introduces a set of workload resource abstractions on top of existing managed services and cloud offerings to enable an unprecedented degree of workload portability across cloud providers. There are <a href="https://medium.com/gitlab-magazine/multi-cloud-maturity-model-2de185c01dd7">six levels of multi-cloud maturity</a> and until today, application portability (i.e. the ability to run an app on any cloud) is incredibly rare and has been difficult to achieve.</p> - -<p>Upbound is the sponsoring company behind <a href="https://rook.io">Rook.io</a>, a cloud native storage service for Kubernetes, and are experts in running managed services the cloud native way. With this project, Upbound strives for Crossplane to become a universal API for cloud computing, and a control plane for smart controllers that can work across clouds. The end goal is to enable a clean separation of concerns between developers who want to consume resources without knowing the details of how they are provisioned or managed, and administrators who want to tightly control the details of implementation and policies.</p> - -<h2 id="how-does-crossplane-compare-to-existing-tools">How does Crossplane compare to existing tools?</h2> - -<p>Similar projects exist, but are not nearly as flexible in their ability to support workload portability across multiple clouds. For example, Terraform and <a href="https://github.com/awslabs/aws-service-operator">AWS Service Operator</a> are similar infrastructure provisioning tools, but they do not support workload portability across cloud providers. Terraform can dynamically provision infrastructure and typically performs changes only when the tool is run by a human, and AWS Service Operator can only provision managed services in AWS.</p> - -<p>As a result of an open API approach, Crossplane has an opportunity to change the cloud industry as we know it, and we’re excited that they've chosen GitLab to be the first complex app deployed with them.</p> - -<h2 id="why-crossplane--gitlab">Why Crossplane + GitLab?</h2> - -<p>"GitLab has a proven track record supporting multi-cloud DevOps,” says Bassam Tabbara, founder and CEO at Upbound. “Customers value the simplicity of the toolchain and the flexibility of the diverse deployment environments that GitLab offers them. Their open collaboration and culture made them the natural fit to be the first complex app deployed with Crossplane."</p> - -<p>At GitLab, we’ve committed to multi-cloud DevOps, as detailed in my recent post on <a href="https://medium.com/gitlab-magazine/there-are-3-public-clouds-left-and-well-use-all-of-them-214858d793e9">why GitLab will use all three public clouds</a>. Most of our customers are already leveraging a multi-cloud strategy using <a href="/product/continuous-integration/">GitLab CI/CD</a> and are increasingly looking for more ways to deploy their code across multiple cloud environments. The choices available today are too complex and vendor driven, but with Crossplane the ability to orchestrate clouds becomes simple. We look forward to collaborating with them on this vision and as the first complex app deployed with Crossplane.</p> - -<p>Once GitLab has been successfully deployed with Crossplane, the next step is to use the project to deploy applications from GitLab. We’ll provide updates as they become available.</p> -<img src='https://about.gitlab.com/images/blogimages/crossplane.png' class='webfeedsFeaturedVisual' style='display: none;' /> - - -GitLab Patch Release: 11.4.9 - -https://about.gitlab.com/2018/12/04/gitlab-11-4-9-released/ -2018-12-04T00:00:00+00:00 -2018-12-04T00:00:00+00:00 - -Steve Azzopardi - -<!-- For detailed instructions on how to complete this, please see https://gitlab.com/gitlab-org/release/docs/blob/master/general/patch/blog-post.md --> - -<p>Today we are releasing version 11.4.9 for GitLab Community Edition and Enterprise Edition.</p> - -<p>This version resolves a number of regressions and bugs in -<a href="/2018/10/22/gitlab-11-4-released">last month's 11.4 release</a> and -prior versions.</p> - -<h2 id="gitlab-community-edition-and-enterprise-edition">GitLab Community Edition and Enterprise Edition</h2> - -<p>Available in GitLab Core, Starter, Premium, and Ultimate:</p> - -<ul> - <li><a href="https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22916">Display impersonation token value after creation</a></li> - <li><a href="https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/23306">Correctly handle data-loss scenarios when encrypting columns</a></li> -</ul> - -<h2 id="upgrade-barometer">Upgrade barometer</h2> - -<p>This version does not include any new migrations, and should not require any -downtime.</p> - -<p>Please be aware that by default the Omnibus packages will stop, run migrations, -and start again, no matter how “big” or “small” the upgrade is. This behavior -can be changed by adding a <a href="http://docs.gitlab.com/omnibus/update/README.html"><code>/etc/gitlab/skip-auto-migrations</code></a> file, -which is only used for <a href="https://docs.gitlab.com/omnibus/update/README.html">updates</a>.</p> - -<h2 id="updating">Updating</h2> - -<p>To update, check out our <a href="/update/">update page</a>.</p> - -<h2 id="gitlab-subscriptions">GitLab subscriptions</h2> - -<p>Access to GitLab Starter, Premium, and Ultimate features is granted by a paid <a href="/pricing/">subscription</a>.</p> - -<p>Alternativelly, <a href="https://gitlab.com/users/sign_in">sign up for GitLab.com</a> -to use GitLab's own infrastructure.</p> -<img src='https://about.gitlab.com/images/default-blog-image.png' class='webfeedsFeaturedVisual' style='display: none;' /> - - -What went down at the Q4'2018 GitLab Hackathon - -https://about.gitlab.com/2018/11/29/q4-hackathon-recap/ -2018-11-29T00:00:00+00:00 -2018-11-29T00:00:00+00:00 - -Ray Paik - -<p>Following the success of the <a href="/2018/10/09/hackathon-recap/">inaugural GitLab Hackathon in September</a>, the GitLab community again gathered on Nov. 14-15 for the Q4 hackathon. Many first-time contributors also participated in this event and the community contribution far exeeded what we saw from the first Hackathon.</p> - -<h2 id="so-what-did-we-accomplish">So what did we accomplish?</h2> - -<p>One of the key goals of the event was to encourage community members to contribute Merge Requests (MRs), and the community delivered 65 of them, with 46 merged as of Nov. 26. You can check out the status of MRs at <a href="https://gitlab.com/gitlab-com/marketing/community-relations/contributor-program/gitlab-hackathon/q4-2018-hackathon/issues/1">Hackathon Community MRs</a>. This is almost the triple the number of MRs from the September Hackathon, as we easily surpassed the September total by the end of Day 1. Beyond the number of MRs, what was also impressive was community's participation across a wide variety of GitLab projects. In addition to GitLab <a href="https://gitlab.com/gitlab-org/gitlab-ce">Community</a> and <a href="https://gitlab.com/gitlab-org/gitlab-ee">Enterprise</a> editions, we saw MRs for <a href="https://gitlab.com/gitlab-org/gitlab-development-kit">GitLab Development Kit (GDK)</a>, <a href="https://gitlab.com/gitlab-org/gitlab-shell">GitLab Shell</a>, <a href="https://gitlab.com/gitlab-org/gitter/webapp">Gitter</a>, <a href="https://gitlab.com/gitlab-com/www-gitlab-com">the GitLab website</a>, and more.</p> - -<h2 id="what-else-happened-during-the-event">What else happened during the event?</h2> - -<p>In addition to hacking, we had several community experts deliver tutorial sessions on topics ranging from <a href="https://www.youtube.com/watch?v=0WatxtwgLDE">Meltano</a>, <a href="https://www.youtube.com/watch?v=mCec7g6Ml70">Omnibus</a>, <a href="https://www.youtube.com/watch?v=0GVtrxZ5_a8">GitLab Architecture</a>, and <a href="https://www.youtube.com/watch?v=LFWTW6PbJOQ">Gitter</a>. Recordings/slides from all the sessions can also be found on the <a href="https://gitlab.com/gitlab-com/marketing/community-relations/contributor-program/gitlab-hackathon/q4-2018-hackathon/wikis/home">Hackathon wiki page</a>.</p> - -<h2 id="when-is-the-next-hackathon">When is the next Hackathon?</h2> - -<p>We will be having another Hackathon in mid-Q1'2019, and will announce the dates in January. Please stay tuned for further announcements in another blog post and discussions on the -<a href="https://gitter.im/gitlabhq/community">GitLab Community room in Gitter</a> and on the <a href="https://forum.gitlab.com/c/announcements">GitLab forum</a>. More importantly, if you have any suggestions for topics and/or feedback on last month's event, -please mention them on the <a href="https://gitter.im/gitlabhq/community">GitLab Community room in Gitter</a> to help us improve future Hackathons.</p> - -<h2 id="hackathon-prizes">Hackathon prizes</h2> - -<p>As we announced at the Hackathon kickoff, everyone who had MRs merged will receive a token of our appreciation for their contribution. During the Hackathon period, 19 people had MRs merged and the "grand prize" winner with most MRs merged is once again <a href="https://gitlab.com/gtsiolis">George Tsiolis</a>, with 13 merged MRs! -Congratulations to everyone! I will reach out to all winners shortly.</p> - -<h2 id="how-do-i-get-started-with-contributing">How do I get started with contributing?</h2> - -<p>A good place to start is the <a href="/community/contribute/">Contributing to GitLab page</a>, where you can learn how you can -contribute to GitLab code, documentation, translation, and UX design.</p> - -<p>If you have any questions, you are always welcome to reach me at rpaik@gitlab.com.</p> - -<p class="note"><a href="https://unsplash.com/photos/ZV_64LdGoao">"Gitlab application screengrab"</a> by <a href="https://unsplash.com/@pankajpatel">Pankaj Patel</a> on Unsplash</p> -<img src='https://about.gitlab.com/images/blogimages/2018-09-13-gitlab-hackathon-cover.jpg' class='webfeedsFeaturedVisual' style='display: none;' /> - - -GitLab Security Release: 11.5.1, 11.4.8, and 11.3.11 - -https://about.gitlab.com/2018/11/28/security-release-gitlab-11-dot-5-dot-1-released/ -2018-11-28T00:00:00+00:00 -2018-11-28T00:00:00+00:00 - -Ethan Strike - -<p>Today we are releasing versions 11.5.1, 11.4.8, and 11.3.11 for GitLab Community Edition (CE) and Enterprise Edition (EE).</p> - -<p>These versions contain a number of important security fixes, and we strongly recommend that all GitLab installations be upgraded to one of these versions immediately.</p> - - - -<p>The vulnerability details will be made public on our issue tracker in approximately 30 days.</p> - -<p>Please read on for more information regarding this release.</p> - -<h2 id="view-names-of-private-groups">View Names of Private Groups</h2> - -<p>The Todos dashboard permitted an unauthorized user to view the names of private groups. The issue is now mitigated in the latest release and is assigned <a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-19494">CVE-2018-19494</a>.</p> - -<p>Thanks to <a href="https://hackerone.com/ashish_r_padelkar">@ashish_r_padelkar</a> for responsibly reporting this vulnerability to us.</p> - -<h3 id="versions-affected">Versions Affected</h3> - -<p>Affects GitLab CE/EE 11.2 and later.</p> - -<h3 id="remediation">Remediation</h3> - -<p>We <strong>strongly recommend</strong> that all installations running an affected version above to be upgraded to the latest version as soon as possible.</p> - -<h2 id="persistent-xss-in-environments">Persistent XSS in Environments</h2> - -<p>The Environments page contained a lack of input validation and output encoding issue which resulted in a persistent XSS. The issue is now mitigated in the latest release and is assigned <a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-19493">CVE-2018-19493</a>.</p> - -<p>Thanks to <a href="https://hackerone.com/xanbanx">@xanbanx</a> for responsibly reporting this vulnerability to us.</p> - -<h3 id="versions-affected-1">Versions Affected</h3> - -<p>Affects GitLab CE/EE 11.0 and later.</p> - -<h3 id="remediation-1">Remediation</h3> - -<p>We <strong>strongly recommend</strong> that all installations running an affected version above to be upgraded to the latest version as soon as possible.</p> - -<h2 id="ssrf-in-prometheus-integration">SSRF in Prometheus integration</h2> - -<p>The Prometheus integration was vulnerable to an SSRF issue which allowed an attacker to make requests to any local network resource accessible from the GitLab server. The issue is now mitigated in the latest release and is assigned <a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-19495">CVE-2018-19495</a>.</p> - -<p>Thanks to <a href="https://hackerone.com/bull">@bull</a> for responsibly reporting this vulnerability to us.</p> - -<h3 id="versions-affected-2">Versions Affected</h3> - -<p>Affects GitLab CE/EE 9.0 and later.</p> - -<h3 id="remediation-2">Remediation</h3> - -<p>We <strong>strongly recommend</strong> that all installations running an affected version above to be upgraded to the latest version as soon as possible.</p> - -<h2 id="unauthorized-promotion-of-milestones">Unauthorized Promotion of Milestones</h2> - -<p>Milestones were vulnerable to an insecure object reference issue where a user with insufficient privilieges could promote a project milestone to a group milestone. The issue is now mitigated in the latest release and is assigned <a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-19496">CVE-2018-19496</a>.</p> - -<p>Thanks to <a href="https://hackerone.com/sandeep_hodkasia">@sandeep_hodkasia</a> for responsibly reporting this vulnerability to us.</p> - -<h3 id="versions-affected-3">Versions Affected</h3> - -<p>Affects GitLab CE/EE 10.2 and later.</p> - -<h3 id="remediation-3">Remediation</h3> - -<p>We <strong>strongly recommend</strong> that all installations running an affected version above to be upgraded to the latest version as soon as possible.</p> - -<h2 id="exposure-of-confidential-issue-title">Exposure of Confidential Issue Title</h2> - -<p>The commits listing page in a project permitted an unauthorized user to view the title of a confidential issue. The issue is now mitigated in the latest release and is assigned <a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-19577">CVE-2018-19577</a>.</p> - -<p>Thanks to <a href="https://hackerone.com/ngalog">@ngalog</a> for responsibly reporting this vulnerability to us.</p> - -<h3 id="versions-affected-4">Versions Affected</h3> - -<p>Affects GitLab CE/EE 8.6 and later.</p> - -<h3 id="remediation-4">Remediation</h3> - -<p>We <strong>strongly recommend</strong> that all installations running an affected version above to be upgraded to the latest version as soon as possible.</p> - -<h2 id="persisent-xss-in-markdown-fields-via-mermaid-script">Persisent XSS in Markdown Fields via Mermaid Script</h2> - -<p>Fields that accept Markdown contained incomplete input validation and output encoding when accepting Mermaid script, which resulted in a persistent XSS. The issue is now mitigated in the latest release and is assigned <a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-19573">CVE-2018-19573</a>.</p> - -<p>Thanks to <a href="https://hackerone.com/fransrosen">@fransrosen</a> for responsibly reporting this vulnerability to us.</p> - -<h3 id="versions-affected-5">Versions Affected</h3> - -<p>Affects GitLab CE/EE 10.3 and later.</p> - -<h3 id="remediation-5">Remediation</h3> - -<p>We <strong>strongly recommend</strong> that all installations running an affected version above to be upgraded to the latest version as soon as possible.</p> - -<h2 id="persistent-xss-in-markdown-fields-via-unrecognized-html-tags">Persistent XSS in Markdown Fields via Unrecognized HTML Tags</h2> - -<p>Fields that accept Markdown contained incomplete input validation and output encoding when accepting unrecognized HTML tags, which resulted in a persistent XSS. The issue is now mitigated in the latest release and is assigned <a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-19570">CVE-2018-19570</a>.</p> - -<p>Thanks to <a href="https://hackerone.com/otr">@otr</a> for responsibly reporting this vulnerability to us.</p> - -<h3 id="versions-affected-6">Versions Affected</h3> - -<p>Affects GitLab CE/EE 11.3 and later.</p> - -<h3 id="remediation-6">Remediation</h3> - -<p>We <strong>strongly recommend</strong> that all installations running an affected version above to be upgraded to the latest version as soon as possible.</p> - -<h2 id="symlink-race-condition-in-pages">Symlink Race Condition in Pages</h2> - -<p>GitLab Pages had a symlink race condition that would allow unauthorized access to files in the Pages chroot. The issue is now mitigated in the latest release and is assigned <a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-19572">CVE-2018-19572</a>.</p> - -<p>Thanks to <a href="https://gitlab.com/waldi">Bastian Blank</a> for responsibly reporting this vulnerability to us.</p> - -<h3 id="versions-affected-7">Versions Affected</h3> - -<p>Affects GitLab CE 8.17 &amp; EE 8.3 and later.</p> - -<h3 id="remediation-7">Remediation</h3> - -<p>We <strong>strongly recommend</strong> that all installations running an affected version above to be upgraded to the latest version as soon as possible.</p> - -<h2 id="unauthorized-changes-by-guest-user-in-issues">Unauthorized Changes by Guest User in Issues</h2> - -<p>GitLab issues were vulnerable to an insecure object reference issue that allowed a Guest user to make changes to, or delete their own comments after an issue had been made confidential. The issue is now mitigated in the latest release and is assigned <a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-19576">CVE-2018-19576</a>.</p> - -<p>Thanks to <a href="https://hackerone.com/sandeep_hodkasia">@sandeep_hodkasia</a> for responsibly reporting this vulnerability to us.</p> - -<h3 id="versions-affected-8">Versions Affected</h3> - -<p>Affects GitLab CE/EE 8.6 and later.</p> - -<h3 id="remediation-8">Remediation</h3> - -<p>We <strong>strongly recommend</strong> that all installations running an affected version above to be upgraded to the latest version as soon as possible.</p> - -<h2 id="unauthorized-comments-on-locked-issues">Unauthorized Comments on Locked Issues</h2> - -<p>GitLab issues were vulnerable to an insecure object reference issue that allowed an unauthorized user to make comments after an issue had been locked. The issue is now mitigated in the latest release and is assigned <a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-19575">CVE-2018-19575</a>.</p> - -<p>Thanks to <a href="https://hackerone.com/ngalog">@ngalog</a> for responsibly reporting this vulnerability to us.</p> - -<h3 id="versions-affected-9">Versions Affected</h3> - -<p>Affects GitLab CE/EE 10.1 and later.</p> - -<h3 id="remediation-9">Remediation</h3> - -<p>We <strong>strongly recommend</strong> that all installations running an affected version above to be upgraded to the latest version as soon as possible.</p> - -<h2 id="improper-enforcement-of-token-scope">Improper Enforcement of Token Scope</h2> - -<p>The GitLab web interface was vulnerable to an authorization issue that allowed access to the web-UI as a user using their Personal Access Token (PAT) of any scope. The issue is now mitigated in the latest release and is assigned <a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-19569">CVE-2018-19569</a>.</p> - -<p>With this fix, the use of PATs is limited to the API, the RSS feed, and the registry, which could break any existing automation scripts that don't use the API. The impact is expected to be limited.</p> - -<p>Thanks to Jan Alsenz of Oneconsult AG for responsibly reporting this vulnerability to us.</p> - -<p><em>Updated: 2018-11-28:</em> We have received reports that this change has impacted how repo files and job artifacts are downloaded for some users. For instructions on how to do so through the API, please see <a href="https://gitlab.com/gitlab-org/gitlab-ce/issues/54572#note_120859334">our support issue</a>. Thank you to the users participating in this issue. Your feedback is important to us.</p> - -<h3 id="versions-affected-10">Versions Affected</h3> - -<p>Affects GitLab CE/EE 8.8 and later.</p> - -<h3 id="remediation-10">Remediation</h3> - -<p>We <strong>strongly recommend</strong> that all installations running an affected version above to be upgraded to the latest version as soon as possible.</p> - -<h2 id="crlf-injection-in-project-mirroring">CRLF Injection in Project Mirroring</h2> - -<p>When using the Git protocol, project mirroring was vulnerable to a CRLF injection vulnerability. The issue is now mitigated in the latest release and is assigned <a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-19585">CVE-2018-19585</a>.</p> - -<p>Thanks to <a href="https://hackerone.com/chromium1337">@chromium1337</a> for responsibly reporting this vulnerability to us.</p> - -<h3 id="versions-affected-11">Versions Affected</h3> - -<p>Affects GitLab CE/EE 8.18 and later.</p> - -<h3 id="remediation-11">Remediation</h3> - -<p>We <strong>strongly recommend</strong> that all installations running an affected version above to be upgraded to the latest version as soon as possible.</p> - -<h2 id="xss-in-oauth-authorization">XSS in OAuth Authorization</h2> - -<p>The OAuth authorization process contained a lack of input validation and output encoding which resulted in an XSS. The issue is now mitigated in the latest release and is assigned <a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-19574">CVE-2018-19574</a>.</p> - -<p>Thanks to <a href="https://hackerone.com/fransrosen">@fransrosen</a> for responsibly reporting this vulnerability to us.</p> - -<h3 id="versions-affected-12">Versions Affected</h3> - -<p>Affects GitLab CE/EE 7.6 and later.</p> - -<h3 id="remediation-12">Remediation</h3> - -<p>We <strong>strongly recommend</strong> that all installations running an affected version above to be upgraded to the latest version as soon as possible.</p> - -<h2 id="ssrf-in-webhooks">SSRF in Webhooks</h2> - -<p>Webhooks were vulnerable to an SSRF vulnerability that allowed an attacker to make requests to any local network resource accessible from the GitLab server. The issue is now mitigated in the latest release and is assigned <a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-19571">CVE-2018-19571</a>.</p> - -<p>Thanks to <a href="https://hackerone.com/nyangawa">@nyangawa</a> of Chaitin Tech for responsibly reporting this vulnerability to us.</p> - -<h3 id="versions-affected-13">Versions Affected</h3> - -<p>Affects GitLab CE/EE 8.18 and later.</p> - -<h3 id="remediation-13">Remediation</h3> - -<p>We <strong>strongly recommend</strong> that all installations running an affected version above to be upgraded to the latest version as soon as possible.</p> - -<h2 id="send-email-on-email-address-change">Send Email on Email Address Change</h2> - -<p>Previously, GitLab did not send an email to the old email address when an email address change was made. The issue is now mitigated in the latest release and is assigned <a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-19580">CVE-2018-19580</a>.</p> - -<p>Thanks to <a href="https://hackerone.com/muon4">@muon4</a> for responsibly reporting this vulnerability to us.</p> - -<h3 id="versions-affected-14">Versions Affected</h3> - -<p>Affects all versions of GitLab CE/EE.</p> - -<h3 id="remediation-14">Remediation</h3> - -<p>We <strong>strongly recommend</strong> that all installations running an affected version above to be upgraded to the latest version as soon as possible.</p> - -<h2 id="workhorse-logs-contained-tokens">Workhorse Logs Contained Tokens</h2> - -<p>Workhorse was logging access tokens, which allowed administrators with access to the logs to see the tokens of other users. The issue is now mitigated in the latest release and is assigned <a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-19583">CVE-2018-19583</a>.</p> - -<h3 id="versions-affected-15">Versions Affected</h3> - -<p>Affects GitLab CE/EE 8.0 and later.</p> - -<h3 id="remediation-15">Remediation</h3> - -<p>We <strong>strongly recommend</strong> that all installations running an affected version above to be upgraded to the latest version as soon as possible.</p> - -<h2 id="unauthorized-publishing-of-draft-comments">Unauthorized Publishing of Draft Comments</h2> - -<p>The discussion drafts endpoint, used in merge requests, contained an insecure object reference vulnerability that permitted an unauthorized user to publish the drafts of another user. The issue is now mitigated in the latest release and is assigned <a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-19582">CVE-2018-19582</a>.</p> - -<p>Thanks to <a href="https://hackerone.com/lucky_sen">@lucky_sen</a> for responsibly reporting this vulnerability to us.</p> - -<h3 id="versions-affected-16">Versions Affected</h3> - -<p>Affects GitLab EE 11.4 and later.</p> - -<h3 id="remediation-16">Remediation</h3> - -<p>We <strong>strongly recommend</strong> that all installations running an affected version above to be upgraded to the latest version as soon as possible.</p> - -<h2 id="guest-can-set-weight-of-a-new-issue">Guest Can Set Weight of a New Issue</h2> - -<p>GitLab issues were vulnerable to an insecure object reference issue that allowed a Guest user to set the weight of an issue they created. The issue is now mitigated in the latest release and is assigned <a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-19581">CVE-2018-19581</a>.</p> - -<p>Thanks to <a href="https://hackerone.com/ngalog">@ngalog</a> for responsibly reporting this vulnerability to us.</p> - -<h3 id="versions-affected-17">Versions Affected</h3> - -<p>Affects GitLab EE 8.3 and later.</p> - -<h3 id="remediation-17">Remediation</h3> - -<p>We <strong>strongly recommend</strong> that all installations running an affected version above to be upgraded to the latest version as soon as possible.</p> - -<h2 id="disclosure-of-private-groups-members-and-milestones">Disclosure of Private Group's Members and Milestones</h2> - -<p>An insecure direct object reference vulnerability in issue boards allowed authenticated, but unauthorized users to view members and milestone details of private groups. The issue is now mitigated in the latest release and is assigned <a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-19584">CVE-2018-19584</a>.</p> - -<p>Thanks to <a href="https://hackerone.com/ngalog">@ngalog</a> for responsibly reporting this vulnerability to us.</p> - -<h3 id="versions-affected-18">Versions Affected</h3> - -<p>Affects GitLab EE 11.0 and later.</p> - -<h3 id="remediation-18">Remediation</h3> - -<p>We <strong>strongly recommend</strong> that all installations running an affected version above to be upgraded to the latest version as soon as possible.</p> - -<h2 id="persisent-xss-in-operations">Persisent XSS in Operations</h2> - -<p>The Operations page contained a lack of input validation and output encoding which resulted in a persistent XSS. The issue is now mitigated in the latest release and is assigned <a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-19579">CVE-2018-19579</a>.</p> - -<p>Thanks to <a href="https://hackerone.com/ngalog">@ngalog</a> for responsibly reporting this vulnerability to us.</p> - -<h3 id="versions-affected-19">Versions Affected</h3> - -<p>Affects GitLab EE 11.5.</p> - -<h3 id="remediation-19">Remediation</h3> - -<p>We <strong>strongly recommend</strong> that all installations running an affected version above to be upgraded to the latest version as soon as possible.</p> - -<h2 id="reporter-can-view-operations-page">Reporter Can View Operations Page</h2> - -<p>Due to incomplete permissions validation, a user with Reporter privileges was permitted to view the Jaeger Tracing Operations page. The issue is now mitigated in the latest release and is assigned <a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-19578">CVE-2018-19578</a>.</p> - -<p>Thanks to <a href="https://hackerone.com/vijay_kumar1110">@vijay_kumar1110</a> for responsibly reporting this vulnerability to us.</p> - -<h3 id="versions-affected-20">Versions Affected</h3> - -<p>Affects GitLab EE 11.5.</p> - -<h3 id="remediation-20">Remediation</h3> - -<p>We <strong>strongly recommend</strong> that all installations running an affected version above to be upgraded to the latest version as soon as possible.</p> - -<h2 id="upgrade-to-redis-3212">Upgrade to Redis 3.2.12</h2> - -<p>The version of Redis used in the Omnibus package was upgraded in the GitLab 11.3 release. This upgrade was previously included in GitLab 11.4 and 11.5 Omnibus packages, and includes several security fixes. -The upgrade to Redis was incorrectly reported in the <a href="https://about.gitlab.com/2018/10/29/security-release-gitlab-11-dot-4-dot-3-released/">October security release</a>.</p> - -<h2 id="updating">Updating</h2> - -<p>To update, check out our <a href="/update">update page</a>.</p> -<img src='https://about.gitlab.com/images/default-blog-image.png' class='webfeedsFeaturedVisual' style='display: none;' /> - - -GitLab achieves AWS DevOps Competency certification - -https://about.gitlab.com/2018/11/28/gitlab-achieves-aws-devops-competency-certification/ -2018-11-28T00:00:00+00:00 -2018-11-28T00:00:00+00:00 - -Tina Sturgis and Eliran Mesika - -<p>Today, we are proud to announce GitLab has been certified with <a href="https://aws.amazon.com/devops/partner-solutions/">AWS DevOps Competency</a>, affirming our further commitment as a technology partner with Amazon Web Services (AWS).</p> - -<p>Building on the foundation of our AWS partnership over the last three years, with this DevOps certification we’ve now received the highest level of accreditation available from AWS. We bring proven customer success with <a href="/customers/axway/">measurable return on investment</a> for customers running GitLab on AWS and <a href="/solutions/aws/">using GitLab to deploy their software to AWS</a>.</p> - -<p><img src="/images/blogimages/DevOps_competency_badge.png" alt="AWS DevOps Competency badge" class="small right wrap-text" /></p> - -<h3 id="why-the-aws-devops-competency-matters">Why the AWS DevOps Competency matters</h3> - -<p>Achieving this certification sets GitLab apart as an AWS Partner Network (APN) member that provides demonstrated DevOps technical proficiency and proven customer success, with specific focus in the <a href="/product/continuous-integration/">Continuous Integration</a> and <a href="/product/continuous-delivery/">Continuous Delivery</a> category.</p> - -<p>This is important for our own customers who are either looking to move to AWS or are already using it, as well as for current AWS customers. Potential users of GitLab with AWS can be assured that the GitLab solution has been reviewed and approved by an AWS Architect Review Board and that it meets <a href="https://d0.awsstatic.com/whitepapers/Security/AWS_Security_Best_Practices.pdf">AWS Security Best Practices</a>.</p> - -<p>Through this process we were able to demonstrate our product is production ready on AWS for DevOps, specifically for improving application delivery, application build/test, or infrastructure/configuration management.</p> - -<h3 id="gitlab-and-aws-customer-success">GitLab and AWS customer success</h3> - -<p>To learn more about the GitLab customer case studies considered for this competency, please review both the <a href="/customers/axway/">Axway </a> and <a href="/customers/trek10/">Trek10</a> case studies. You can also access information about other customers on the <a href="/customers/">GitLab customers page</a>.</p> - -<h3 id="more-about-the-aws-competency-program">More about the AWS Competency Program</h3> - -<p>AWS established the program to help customers identify, through the AWS Partner Network, partners with deep industry experience and expertise in specialized solution areas. Attaining an AWS Competency allows partners to differentiate themselves to customers by showcasing expertise in a specific solution area.</p> - -<p>We are honored to obtain this AWS DevOps Competency status, and believe this helps advance <a href="/company/strategy/#mission">our mission to allow everyone to contribute</a>. Our definition of everyone now extends further, to those who are small and large users of AWS and AWS Services on their DevOps journey.   </p> - -<p>For more information on GitLab’s partnership with AWS, check out <a href="/solutions/aws/">about.gitlab.com/solutions/aws</a>.</p> - -<p>To learn more about GitLab’s Technology Partners, visit <a href="/partners/">about.gitlab.com/partners</a>.</p> -<img src='https://about.gitlab.com/images/blogimages/gitlab-aws-cover.png' class='webfeedsFeaturedVisual' style='display: none;' /> - - -It's raining repos: The microservices repo explosion, and what we're doing about it - -https://about.gitlab.com/2018/11/26/microservices-integrated-solution/ -2018-11-26T00:00:00+00:00 -2018-11-26T00:00:00+00:00 - -Aricka Flowers - -<p>Gone are the days of "set it and forget it"-style software development. The increased demand for code and operations on all projects, especially microservices, means more repos. This calls for a more integrated solution to incorporate testing, security updates, monitoring, and more, says GitLab CEO <a href="/company/team/#sytses">Sid Sijbrandij</a>:</p> - -<blockquote> - <p>"The bar's going up for software development. It's no longer enough to just write the code; you also have to write the tests. It's no longer enough to just ship it; you also have to monitor it. You can no longer make it once and forget about it; you have to stay current with security updates. For every product you make you have to integrate more of these tools. It used to be that only the big projects got all these things, but now every single service you ship should have these features, because other projects are dependent on it. One security vulnerability can be enough to take a company down."</p> -</blockquote> - -<p>An increasing number of project repos means exponential growth in the number of tools needed to handle them – bad news for those saddled managing project dependencies. A streamlined workflow is essential to alleviate this burden – here's how we want to help you get there.</p> - -<h3 id="everything-under-one-roof">Everything under one roof</h3> - -<p>"With GitLab, we want to enable you to simply commit your code and have all the tools you need integrated out of the box," Sid said. "You don't have to do anything else. It's monitored; we measure whether your dependencies have a vulnerability and fix it for you automatically. I think that's the big benefit of GitLab; that you don't have to go into stitching together 10 tools for every project that you make."</p> - -<p>By using an integrated solution to manage an ever-growing number of microservices, you can avoid having engineers siloed off with their respective teams and tools. Creating visibility among teams and getting rid of the need for handoffs leads to a faster DevOps lifecycle while also ensuring that your projects deploy and remain stable, Sid explains.</p> - -<div class="newsletter-cta-b panel panel-default panel-newsletter-cta"> -<div class="panel-body newsletter-cta"> -<div class="panel-header"> -<?xml version="1.0" encoding="UTF-8"?> -<svg width="56px" height="52px" viewBox="0 0 56 52" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> - <defs></defs> - <g id="Desktop" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> - <g id="blog-newsletter-cta-graphic-v2" transform="translate(-1070.000000, -383.000000)" fill="#FFFFFF"> - <g id="gitlab-newsletter-cta-b" transform="translate(948.000000, 363.000000)"> - <g id="Page-1" transform="translate(122.000000, 20.000000)"> - <path d="M53.1397841,30.8022957 L34.558125,44.3561117 L51.1622841,22.9844307 L53.4156477,29.9385534 C53.5192159,30.2590074 53.4081705,30.6062589 53.1397841,30.8022957 Z M2.86117045,30.8027742 C2.59198864,30.6062589 2.48094318,30.2590074 2.58419318,29.9395104 L4.83819318,22.9833141 L21.4412386,44.3634491 L2.86117045,30.8027742 Z M11.2584659,3.11293374 L16.410625,19.0155227 L6.12523864,19.0155227 L11.2584659,3.11293374 Z M36.0973295,21.5676699 L28.0054886,46.5780748 L19.9136477,21.5676699 L36.0973295,21.5676699 Z M44.7420114,3.11277423 L49.8844659,19.0155227 L39.5995568,19.0155227 L44.7420114,3.11277423 Z M31.4494886,44.2040994 L33.126625,39.0203693 L38.7700568,21.578038 L49.0266477,21.578038 L32.9091477,42.3254 L31.4494886,44.2040994 Z M17.2337614,21.578038 L24.5527386,44.1996331 L6.98544318,21.578038 L17.2337614,21.578038 Z M55.8366932,29.1508969 L52.8941477,20.069719 C52.8793523,19.9864552 52.8535795,19.904946 52.8220795,19.8248724 L46.9193295,1.57207485 C46.5984432,0.615657669 45.7433295,-4.78527557e-05 44.7385114,-4.78527557e-05 L44.725625,-4.78527557e-05 C43.7206477,0.00521595093 42.8707841,0.62730184 42.5600795,1.58547362 L36.9236477,19.0155227 L19.0866932,19.0155227 L13.4396023,1.58483558 C13.1295341,0.62746135 12.2796705,0.00537546013 11.2746932,-4.78527557e-05 C10.2687614,-0.00563067484 9.40314773,0.611669939 9.07589773,1.58611166 L3.17648864,19.8628356 C3.17092045,19.8781485 3.16344318,19.8923448 3.15851136,19.9076577 L0.163147727,29.151854 C-0.280556818,30.5249092 0.201329545,32.0172773 1.36269318,32.8658663 L27.2447159,51.755584 C27.4696705,51.919719 27.7320114,51.9999521 27.9932386,51.9999521 C28.2622614,51.9999521 28.5292159,51.9133387 28.7525795,51.746492 C28.753375,51.745854 28.7543295,51.745535 28.755125,51.7448969 L54.6377841,32.8655472 C55.7988295,32.0172773 56.2807159,30.5249092 55.8366932,29.1508969 Z" id="Fill-1"></path> - </g> - </g> - </g> - </g> -</svg> -<div id="above-cta-form"> -<div class="newsletter-preamble"> -New blog posts directly to your inbox -</div> -<div class="newsletter-sub-preamble"> -Sign up for our bi-monthly newsletter -</div> -</div> -<div id="confirm-cta-form" style="display: none;"> -<div class="newsletter-preamble"> -Thanks, you’re -<br /> -signed up! -</div> -<div class="newsletter-sub-preamble"> -GitLab is coming to your inbox -</div> -<img class="success-image" src="/images/emojis/newsletter-signup-success.png" /> -</div> -</div> -<div class="newsletter-form"> -<form class="notdefined" id="mktoForm_1547"> -<script src="//app-ab13.marketo.com/js/forms2/js/forms2.min.js"></script> -<script type="text/javascript"> -MktoForms2.loadForm("//app-ab13.marketo.com", "194-VVC-221", 1547, function(form) { - form.onSuccess(function(values, followUpUrl) { - - form.getFormElem().hide(); - document.getElementById('above-cta-form').style.display = 'none'; - document.getElementById('confirm-cta-form').style.display = 'block'; - - dataLayer.push({event: 'mktoLead',mktoFormId: form.getId()}); - return false; - }); - function getgacid() { - try { - var tracker = ga.getAll()[0]; - return tracker.get('clientId'); - } catch (e) { - return 'n/a'; - } - } - form.vals({ - 'gacid': getgacid() - }); -}); - -</script> -</form> -</div> -</div> - -</div> - -<p>"Our customers that switched from a fragmented setup and were only able to get projects through that cycle a few times a year are now deploying a few times a week," Sid said. "The ability to go from planning to monitoring it in production is what GitLab brings to the table. We have an ample amount of customer case studies showing how we helped improve their speed."</p> - -<h3 id="better-support-for-microservices">Better support for microservices</h3> - -<p>We are boning up our support of microservices, and have a number of features in the works to improve this area, including <a href="https://gitlab.com/gitlab-org/gitlab-ce/issues/34758">group level Kubernetes clusters</a>, a <a href="https://gitlab.com/gitlab-org/gitlab-ce/issues/49336">global Docker registry browser</a>, and adding the <a href="https://gitlab.com/gitlab-org/gitlab-ce/issues/22972">ability to define multiple pipelines</a>. This is to build on what's already there:</p> - -<p>"We have great support for microservices. GitLab has <a href="/2018/10/31/use-multiproject-pipelines-with-gitlab-cicd/">multi-project pipelines</a> and <a href="https://docs.gitlab.com/ee/ci/triggers/README.html#ci-job-token">can trigger pipelines from multi-projects via API</a>," Sid detailed. "The CI Working Group of the CNCF (Cloud Native Computing Foundation), the most cloud native organization in the world probably, uses GitLab to test their projects. We've got great support for things like <a href="/kubernetes">Kubernetes</a> and cloud native technologies. In GitLab, every project you have can be attached to a Kubernetes cluster, and GitLab uses that to run everything that’s going on. We know that a lot of our users and customers are using microservices, and we work great with them."</p> - -<h3 id="future-focus-best-in-class-solutions">Future focus: best-in-class solutions</h3> - -<p>GitLab is much more than just version control. Having started with the planning, creating and verifying stages in 2011 and 2012, we’ve had time to make those capabilities very strong. We are now strengthening our offerings in the other steps of the DevOps lifecycle: managing, packaging, releasing, configuring, monitoring and security.</p> - -<p>"We are seeing enormous progress in those areas, but they can't go head to head with the best-in-class solutions just yet. So that's going be the theme for GitLab next year, to make sure each of our solutions is best in class instead of just the three things we started with," Sid says. "And we won't take our eyes off the ball."</p> - -<p class="note"><a href="https://unsplash.com/photos/wplxPRCF7gA">Cover image</a> by <a href="https://unsplash.com/@rubavi78">Ruben Bagues</a> on Unsplash</p> -<img src='https://about.gitlab.com/images/blogimages/microservices-explosion.jpg' class='webfeedsFeaturedVisual' style='display: none;' /> - - -GitLab 11.5 released with Group Security and Operations Dashboards, and Access Control for Pages - -https://about.gitlab.com/2018/11/22/gitlab-11-5-released/ -2018-11-22T00:00:00+00:00 -2018-11-22T00:00:00+00:00 - -Fabio Busatto - - -<h2 class="intro-header" id="group-dashboard-for-security-teams">Group dashboard for security teams</h2> - -<p>For a long time, developers have used GitLab as a tool to secure their code. But now, -GitLab is making security teams first-class citizens so they can use GitLab to effect better application security and ensure compliance. With 11.5, the -<a href="#group-security-dashboard">Group Security Dashboard</a> pulls together all of the information security personnel need into one place, so folks like CISOs, -CIOs, and application security leaders get a specific view designed for them. -The group dashboard has a redesigned look and new visualizations, bringing together -security information across multiple projects and providing a high-level view while -also enabling the ability to drill down into specific reports. With 11.5, we're -starting with SAST reports, and we'll be adding more to the group dashboard in -the future. Our goal is to build a single tool that security teams can use -instead of needing to switch back and forth between multiple tools.</p> - -<h2 class="intro-header" id="new-dashboard-for-operations-teams">New dashboard for operations teams</h2> - -<p>In the same way that the Group Security Dashboard makes security teams first-class citizens, the <a href="#operations-dashboard">Operations Dashboard</a> provides a -tailored experience for operations professionals. This instance-wide dashboard -provides a single view across projects to get a summary of each project’s -operational health, including pipeline and alert status.</p> - -<h2 class="intro-header" id="control-access-to-gitlab-pages">Control access to GitLab Pages</h2> - -<p><a href="/product/pages/">GitLab Pages</a> is an easy way to -serve static content on the web, making it perfect for use cases such as -documentation for your project. But what about private projects where -documentation and other static artifacts should only be accessed by project -members? In the past, you'd either have to make your assets public to take -advantage of Pages, or you would not be able to use the feature at all.</p> - -<p>Now, in GitLab 11.5, the same access control permissions that apply to your -issues and code can also be applied to static webpages served by GitLab Pages. -Unauthenticated users will get a 404 when visiting the link. As of today, -<a href="#access-control-for-pages">access controls for GitLab pages</a> is available for self-managed GitLab, -with GitLab.com support coming soon.</p> - -<p>This is a unique feature that we're particularly proud of because it comes -from our open source community. Access control for Pages has been one of our -<a href="https://gitlab.com/gitlab-org/gitlab-ce/issues/33422">most requested features</a> -and <a href="https://gitlab.com/gitlab-org/gitlab-pages/merge_requests/94">the code has been community contributed</a> as well!</p> - -<h2 class="intro-header" id="knative-for-kubernetes">Knative for Kubernetes</h2> - -<p>“Serverless” is a popular, yet often misunderstood industry term. Some folks equate -serverless with "Function as a Service," or FaaS, but this <a href="https://martinfowler.com/articles/serverless.html">isn't quite accurate</a>. In a nutshell, serverless enables a programming paradigm where you are able -to focus on writing business logic without having to understand or even -worry about the underlying infrastructure where your software is deployed. -As such, both functions and applications can be serverless.</p> - -<p><a href="https://cloud.google.com/knative/">Knative</a> is a Kubernetes-based platform -to build, deploy, and manage modern serverless workloads, and GitLab 11.5 -comes with the ability to <a href="#easily-deploy-and-integrate-knative-with-gitlab">easily deploy and integrate Knative with GitLab</a>. You can now install Knative to your <a href="/solutions/kubernetes/">connected Kubernetes cluster</a> with a single click. With GitLab 11.5, you'll be able to use Knative for your serverless applications, with -<a href="https://gitlab.com/gitlab-org/gitlab-ce/issues/43959">serverless functions coming in 11.6</a>.</p> - -<p>Today, Knative is still in alpha, but there are some compelling reasons to deploy applications using Knative as it comes with some powerful functionality out-of-the-box. In particular, Knative manages pod scaling for you so you can automatically scale up, or even scale down to zero without additional configuration. Additionally, Knative comes with eventing built in so using it to deploy microservices makes it easier to manage inter-process communication between your producer and consumer services.</p> - -<h2 class="intro-header" id="and-so-much-more">And so much more!</h2> - -<p>With so many great features in this release, we couldn't pack them all into -the intro. Be sure to read up on other exciting new features like -<a href="#parallel-attribute-for-faster-pipelines">the parallel attribute for faster pipelines</a>, -<a href="#issue-board-cards-redesigned">redesigned Issue Board cards</a>, and an initial -<a href="#open-jaeger-from-gitlab">Jaeger integration</a>. -We’ve made big improvements in this release to make code review easier and more useful, including the ability to -<a href="#comment-on-unchanged-lines-in-merge-request">comment on unchanged lines in merge requests</a>, -<a href="#preview-merge-request-review-before-submitting-it">preview merge request reviews before submitting</a>, and -<a href="#assign-approvers-based-on-code-owners">assign approvers based on Code Owners</a> along with -<a href="#review-app-direct-link">Review App direct links</a>. -Keep reading to see all of the features that are part of this release.</p> -<img src='https://about.gitlab.com/images/11_5/11_5-cover-image.jpg' class='webfeedsFeaturedVisual' style='display: none;' /> -<!-- CTA --> -<p class='cta text-center'> -<a href="/events/" class="btn btn-red webcast-button" target="_blank">Join us for an upcoming event</a> -</p> -<!-- MVP --> -<section class='mvp gray-section' id='mvp'> -<div class='release-post-section'> -<img alt='GitLab MVP badge' src='/images/mvp_badge.png' /> -<h2 id='mvp'> -<a class='header-link' href='#mvp'> -<i class='fas fa-link'></i> -</a> -This month's Most Valuable Person (<a href='/community/mvp/'>MVP</a>) is -<a href="https://gitlab.com/tuomoa">Tuomo Ala-Vannesluoma</a> -</h2> -<p>Tuomo did an amazing job by implementing <a href="#access-control-for-pages">Access control for Pages</a>, a highly requested feature. -Private projects can now restrict access to their content to authorized users. This enables groups of -people to host internal web pages that may contain sensitive information, for example.</p> - -<p>Thank you, Tuomo! This feature required a significant amount of work across -<a href="https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/18589"><code>gitlab-ce</code></a>, -<a href="https://gitlab.com/gitlab-org/gitlab-pages/merge_requests/94"><code>gitlab-pages</code></a>, -and <a href="https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests/2583"><code>omnibus-gitlab</code></a> GitLab projects.</p> - -</div> -</section> -<!-- top feature --> -<section class='release-post-section' id='top-feature'> -<div class='release-post-section text-center'> -<h2 class='features-released' id='key-features-released'> -<a class='header-link' href='#key-features'> -<i class='fas fa-link'></i> -</a> -Key features released in GitLab 11.5 -</h2> -</div> -<h2 id='group-security-dashboard'> -<a class='header-link' href='#group-security-dashboard'> -<i class='fas fa-link'></i> -</a> -Group Security Dashboard -</h2> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Core'> -<div class='badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Starter'> -<div class='badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Premium'> -<div class='badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Free'> -<div class='badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Bronze'> -<div class='badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Silver'> -<div class='badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>Security teams need to easily access information about the security status of all their projects, -so they know which is the most important task to take next. This is even more important for Directors -of Security that need to have a high-level view of possible critical issues affecting the -entire development.</p> - -<p>With GitLab 11.5, a first iteration of a new Security Dashboard is available at group level. It -provides a summary for all the <a href="https://docs.gitlab.com/ee/user/project/merge_requests/sast.html">SAST</a> -vulnerabilities in all the projects in that group, and a list of -actionable entries that can be used to start a remediation process. For example, you can open an issue -with a suggested solution, or simply dismiss the entry if you classify it as a false positive. -Support for other tests (Dependency Scanning, Container Scanning, DAST) will be added in the future.</p> - -<p><strong>Note:</strong> The Group Security Dashboard requires the new <a href="https://docs.gitlab.com/ee/ci/yaml/README.html#artifactsreports"><code>reports</code></a> -syntax and GitLab Runner 11.5 or higher in order to display results. -<a href="https://docs.gitlab.com/ee/topics/autodevops/">Auto DevOps</a> will be supported in a future release.</p> - -<div class='column'> -<img alt='Group Security Dashboard' class='shadow' src='/images/11_5/group-security-dashboard.png' /> -</div> -<div class='row reference-buttons'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-sm product-icon' href='https://docs.gitlab.com/ee/user/group/security_dashboard/' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-sm product-icon' href='https://gitlab.com/gitlab-org/gitlab-ee/issues/6709' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -</section> -<hr /> -<!-- primary features --> -<section id='primary-features'> -<div class='release-row'> -<div class='column'> -<h2 id='operations-dashboard'> -<a class='header-link' href='#operations-dashboard'> -<i class='fas fa-link'></i> -</a> -Operations Dashboard -</h2> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Core'> -<div class='badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Starter'> -<div class='badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Premium'> -<div class='badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Free'> -<div class='badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Bronze'> -<div class='badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Silver'> -<div class='badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>For organizations who have embraced DevOps, and for teams with more operations-leaning members, it is important to be able to quickly -ascertain the health of the projects in your organization.</p> - -<p>GitLab 11.5 introduces a new, operations-focused dashboard, providing a summary of the key operational metrics of each project -a user is interested in. This includes the time since the last deployment, most recent commit, as well as whether there are any active alerts.</p> - -<p>The dashboard can be set as a user’s preferred homepage, or accessed via clicking on the new dashboard icon in the top bar.</p> - -<div class='row reference-buttons'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-sm product-icon' href='https://docs.gitlab.com/ee/user/operations_dashboard/' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-sm product-icon' href='https://gitlab.com/gitlab-org/gitlab-ee/issues/5781' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -</div> -<div class='column'> -<img alt='Operations Dashboard' class='shadow' src='/images/11_5/ops-dashboard.png' /> -</div> -</div> -<hr /> -<div class='release-row image-left'> -<div class='column text-column'> -<h2 id='access-control-for-pages'> -<a class='header-link' href='#access-control-for-pages'> -<i class='fas fa-link'></i> -</a> -Access control for Pages -</h2> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Core'> -<div class='available badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Starter'> -<div class='available badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Free'> -<div class='badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Bronze'> -<div class='badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Silver'> -<div class='badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Gold'> -<div class='badge'>GOLD</div> -</a> -</div> -</div> - -<p>The 11.5 release introduces a fantastic new community-contributed feature which enables -access control for Pages. Now, instead of only supporting use cases where the content -associated with the product is public, you can use Pages to build and publish protected -content that should only be accessible by project members. Operational documentation, internal -secrets, or even just private planning or other information can now be confidently published -automatically in an easy-to-access way, while ensuring only the right people are able to see -it.</p> - -<p>This is currently not enabled on GitLab.com, you can follow -<a href="https://gitlab.com/gitlab-com/gl-infra/infrastructure/issues/5576">issue 5576</a> -for more information.</p> - -<div class='row reference-buttons'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-sm product-icon' href='https://docs.gitlab.com/ee/user/project/pages/introduction.html#gitlab-pages-access-control-core-only' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-sm product-icon' href='https://gitlab.com/gitlab-org/gitlab-ce/issues/33422' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -</div> -<div class='column image-column'> -<img alt='Access control for Pages' class='shadow' src='/images/11_5/access-control-pages.png' /> -</div> -</div> -<hr /> -<div class='release-row'> -<div class='column'> -<h2 id='easily-deploy-and-integrate-knative-with-gitlab'> -<a class='header-link' href='#easily-deploy-and-integrate-knative-with-gitlab'> -<i class='fas fa-link'></i> -</a> -Easily deploy and integrate Knative with GitLab -</h2> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Core'> -<div class='available badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Starter'> -<div class='available badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Free'> -<div class='available badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Bronze'> -<div class='available badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Silver'> -<div class='available badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>Building serverless applications enables teams to focus their time on making a great product -and eliminates the need of provisioning, managing, and operating servers.</p> - -<p>Starting in GitLab 11.5, you can now deploy <a href="https://cloud.google.com/knative/">Knative</a> to your -existing Kubernetes cluster with a single click using the GitLab Kubernetes integration. Knative -is a Kubernetes-based platform to build, deploy, and manage modern serverless workloads. Tasks that -were once difficult, such as source-to-container builds, routing and managing traffic, -and scaling-to-zero, now work effortlessly out of the box.</p> - -<div class='row reference-buttons'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-sm product-icon' href='https://docs.gitlab.com/ee/user/project/clusters/serverless/' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-sm product-icon' href='https://gitlab.com/gitlab-org/gitlab-ce/issues/54027' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -</div> -<div class='column'> -<img alt='Easily deploy and integrate Knative with GitLab' class='shadow' src='/images/11_5/knative.png' /> -</div> -</div> -<hr /> -<div class='release-row image-left'> -<div class='column text-column'> -<h2 id='assign-approvers-based-on-code-owners'> -<a class='header-link' href='#assign-approvers-based-on-code-owners'> -<i class='fas fa-link'></i> -</a> -Assign approvers based on Code Owners -</h2> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Core'> -<div class='badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Starter'> -<div class='available badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Free'> -<div class='badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Bronze'> -<div class='available badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Silver'> -<div class='available badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>Knowing who to ask to review your merge request isn’t always obvious. -Code Owners, which allow files to be assigned to the responsible team -members, are now automatically assigned as merge request approvers.</p> - -<p>Assigning approvers automatically based on Code Owners will notify the -relevant Code Owners of impending changes so that they are able to -review and approve the changes.</p> - -<p>Support for defining Code Owners was introduced in -<a href="/2018/09/22/gitlab-11-3-released/#code-owners">GitLab 11.3</a>. In -upcoming releases, Code Owners will be further integrated into the -merge request workflow with -<a href="https://gitlab.com/gitlab-org/gitlab-ee/issues/4418">required approvals</a>.</p> - -<div class='row reference-buttons'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-sm product-icon' href='https://docs.gitlab.com/ee/user/project/merge_requests/merge_request_approvals.html#eligible-approvers' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-sm product-icon' href='https://gitlab.com/gitlab-org/gitlab-ee/issues/1012' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -</div> -<div class='column image-column'> -<img alt='Assign approvers based on Code Owners' class='shadow' src='/images/11_5/approvals.png' /> -</div> -</div> -<hr /> -<div class='release-row'> -<div class='column'> -<h2 id='parallel-attribute-for-faster-pipelines'> -<a class='header-link' href='#parallel-attribute-for-faster-pipelines'> -<i class='fas fa-link'></i> -</a> -Parallel attribute for faster pipelines -</h2> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Core'> -<div class='available badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Starter'> -<div class='available badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Free'> -<div class='available badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Bronze'> -<div class='available badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Silver'> -<div class='available badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>The speed of pipelines is an important factor for any team, and running tests or other parallelizable tasks -tends to take a big chunk of the time for any build. Adding this new keyword gives teams the ability to -simply parallelize tests, allowing everyone to accelerate their software delivery process. To use this -feature, simply set the parallel attribute to how many copies of the task you’d like to split it into, -and GitLab will handle the work of automatically creating the appropriate number of jobs running your task.</p> - -<div class='row reference-buttons'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-sm product-icon' href='https://docs.gitlab.com/ee/ci/yaml/#parallel' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-sm product-icon' href='https://gitlab.com/gitlab-org/gitlab-ce/issues/21480' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -</div> -<div class='column'> -<img alt='Parallel attribute for faster pipelines' class='shadow' src='/images/11_5/parallel-keyword.png' /> -</div> -</div> -</section> -<!-- secondary features --> -<section id='secodary-features'> -<div class='release-post-section text-center zero-bottom-margin'> -<h2 class='features-released' id='other-improvements-in-gitlab'> -<a class='header-link' href='#other-improvements-in-gitlab'> -<i class='fas fa-link'></i> -</a> -Other improvements in GitLab 11.5 -</h2> -</div> -<div class='release-row align-top divider'> -<div class='secondary-release-column'> -<div class='secondary-column-feature'> -<h3 id='comment-on-unchanged-lines-in-merge-request'> -<a class='header-link' href='#comment-on-unchanged-lines-in-merge-request'> -<i class='fas fa-link'></i> -</a> -Comment on unchanged lines in merge request -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Core'> -<div class='available badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Starter'> -<div class='available badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Free'> -<div class='available badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Bronze'> -<div class='available badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Silver'> -<div class='available badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>An important purpose of code review is to draw attention to aspects of -the proposed change that may not have been considered. Often this means -pointing out unforseen consequences in areas of the code base that are -unchanged.</p> - -<p>GitLab now supports commenting on both changed and unchanged lines in -merge request diffs, so that you can directly draw the attention of the -author to changes that are required that have not yet been made. When -reviewing a merge request diff you can expand collapsed, unchanged lines -using the ellipsis (<strong>…</strong>) button.</p> - -<p>In upcoming releases, support for commenting on unchanged lines will be -expanded from changed files to -<a href="https://gitlab.com/gitlab-org/gitlab-ce/issues/52501">unchanged files</a>.</p> - -<img alt='Comment on unchanged lines in merge request' class='shadow' src='/images/11_5/unchanged-comment.png' /> -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/ee/user/discussions/index.html#resolvable-discussions' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/gitlab-org/gitlab-ce/issues/13950' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -</div> -<hr class='hidden-lg' /> -<div class='hidden-lg secondary-column-feature'> -<h3 id='group-file-templates'> -<a class='header-link' href='#group-file-templates'> -<i class='fas fa-link'></i> -</a> -Group file templates -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Core'> -<div class='badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Starter'> -<div class='badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Free'> -<div class='badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Bronze'> -<div class='badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Silver'> -<div class='available badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>File templates for <code>LICENSE</code>, <code>.gitignore</code>, <code>Dockerfile</code>, and -<code>.gitlab-ci.yml</code> files make it easy to add these common files to -projects. Custom file templates can now be shared with all the projects -in a group and sub-groups, by configuring a template repository for the -group.</p> - -<p>Custom templates are useful when the templates provided by GitLab are -too generic, for example a custom license that should be used for every -project in the company, or a complex Dockerfile that should be used for -every microservice.</p> - -<p>Support for instance-wide template repositories was <a href="/2018/09/22/gitlab-11-3-released/#custom-file-templates-for-self-managed-instances">introduced -in GitLab 11.3</a>.</p> - -<img alt='Group file templates' class='shadow' src='/images/11_5/group-templates.png' /> -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/ee/user/group/#group-level-file-templates-premium' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/gitlab-org/gitlab-ee/issues/5987' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -</div> -<hr class='hidden-lg' /> -<div class='secondary-column-feature'> -<h3 id='review-app-direct-link'> -<a class='header-link' href='#review-app-direct-link'> -<i class='fas fa-link'></i> -</a> -Review App direct link -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Core'> -<div class='available badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Starter'> -<div class='available badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Free'> -<div class='available badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Bronze'> -<div class='available badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Silver'> -<div class='available badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>When you’re working on a branch and have only changed a few files, it’s not very helpful for the -Review App link to take you to the root of the website. To make this more useful, we’ve added a -dropdown selector to the Review App link which can now take you directly to the page(s) that you’ve -changed.</p> - -<img alt='Review App direct link' class='shadow' src='/images/11_5/direct-page-link.png' /> -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/ee/ci/environments.html#go-directly-from-source-files-to-public-pages-on-the-environment' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/gitlab-org/gitlab-ce/issues/33418' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -</div> -<hr class='hidden-lg' /> -<div class='hidden-lg secondary-column-feature'> -<h3 id='issue-analytics'> -<a class='header-link' href='#issue-analytics'> -<i class='fas fa-link'></i> -</a> -Issue Analytics -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Core'> -<div class='badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Starter'> -<div class='badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Free'> -<div class='badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Bronze'> -<div class='badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Silver'> -<div class='available badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>In this release, we have provided a dynamic chart showing the number of -issues created in your group, per month, for the past year. There is even -a filter that allows you to filter down to a particular scope of issues.</p> - -<p>This will help teams dig more deeply into their issue analytics. For example, -you can quickly see how many bug issues have been created, if you use a -bug label.</p> - -<p>See how we plan to <a href="https://gitlab.com/groups/gitlab-org/-/epics/313">expand on charting capabilities</a> -and please participate in the discussion.</p> - -<img alt='Issue Analytics' class='shadow' src='/images/11_5/issue-analytics.png' /> -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/ee/user/group/issues_analytics/index.html' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/gitlab-org/gitlab-ee/issues/7478' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -</div> -<hr class='hidden-lg' /> -<div class='secondary-column-feature'> -<h3 id='preview-merge-request-review-before-submitting-it'> -<a class='header-link' href='#preview-merge-request-review-before-submitting-it'> -<i class='fas fa-link'></i> -</a> -Preview merge request review before submitting it -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Core'> -<div class='badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Starter'> -<div class='badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Free'> -<div class='badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Bronze'> -<div class='badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Silver'> -<div class='available badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>Code review is an essential practice of successful projects, but -providing clear and actionable feedback can be difficult. A particular -challenge is avoiding leaving comments that become irrelevant or -incomplete as one’s understanding of the changes improves as one reads -more of the diff.</p> - -<p>With this release you are now able to preview your merge request review -before submitting. Merge request reviews, introduced in GitLab 11.4, -allow reviewers to draft many items of feedback and submit them all as -a single action.</p> - -<p>In future iterations, we will improve the feature to send -<a href="https://gitlab.com/gitlab-org/gitlab-ee/issues/4326">one email notification</a> -per merge request review.</p> - -<img alt='Preview merge request review before submitting it' class='shadow' src='/images/11_5/review-preview.png' /> -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/ee/user/discussions/index.html#merge-request-reviews-premium' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/gitlab-org/gitlab-ee/issues/4327' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -</div> -<hr class='hidden-lg' /> -<div class='hidden-lg secondary-column-feature'> -<h3 id='keep-your-email-address-private'> -<a class='header-link' href='#keep-your-email-address-private'> -<i class='fas fa-link'></i> -</a> -Keep your email address private -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Core'> -<div class='available badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Starter'> -<div class='available badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Free'> -<div class='available badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Bronze'> -<div class='available badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Silver'> -<div class='available badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>It’s important to know who is contributing code to your project and be -able to look up a commit author in the GitLab interface, using Git locally, -or on a fork hosted elsewhere, but this exposes your email publicly.</p> - -<p>GitLab now provides a <code>noreply</code> email address that can be used locally -and for web commits to help make it easier to keep your email address -private.</p> - -<img alt='Keep your email address private' class='shadow' src='/images/11_5/noreply-email.png' /> -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/ee/user/profile/#private-commit-email' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/gitlab-org/gitlab-ce/issues/43521' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -</div> -<hr class='hidden-lg' /> -<div class='secondary-column-feature'> -<h3 id='new-cicd-syntax-for-security-quality-and-performance-report-types'> -<a class='header-link' href='#new-cicd-syntax-for-security-quality-and-performance-report-types'> -<i class='fas fa-link'></i> -</a> -New CI/CD syntax for security, quality, and performance report types -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Core'> -<div class='badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Starter'> -<div class='badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Premium'> -<div class='badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Free'> -<div class='badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Bronze'> -<div class='badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Silver'> -<div class='badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>Before GitLab 11.5, reports like SAST or DAST relied on a combination -of job and artifacts names to be recognized as such by the system. This -was not optimal to scale and to support more advanced features -like the Group Security Dashboard, because of the performance implications to access artifacts. With the previous syntax you needed to use specific job names (like <code>sast</code>) but now you can specify custom job names.</p> - -<p>In GitLab 11.5 a new implementation has been introduced to leverage the new <code>reports</code> syntax. New job -definitions are now available for -<a href="https://docs.gitlab.com/ee/ci/examples/sast.html">SAST</a>, -<a href="https://docs.gitlab.com/ee/ci/examples/dast.html">DAST</a>, -<a href="https://docs.gitlab.com/ee/ci/examples/dependency_scanning.html">Dependency Scanning</a>, -<a href="https://docs.gitlab.com/ee/ci/examples/container_scanning.html">Container Scanning</a>, -<a href="https://docs.gitlab.com/ee/ci/examples/license_management.html">License Management</a>, -<a href="https://docs.gitlab.com/ee/ci/examples/code_quality.html">Code Quality</a>, and -<a href="https://docs.gitlab.com/ee//ci/examples/browser_performance.html">Browser Performance Testing</a>. -The <a href="#old-ci/cd-syntax-for-security,-quality,-and-performance-report-types">old syntax has been deprecated</a> and could be removed in a future release. -You are encouraged to upgrade your definitions in order to benefit from improved -performances and the Group Security Dashboard, even if the old syntax is still working. -The new syntax requires GitLab Runner 11.5 or above.</p> - -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/ee/ci/yaml/README.html#artifactsreports' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/gitlab-org/gitlab-ce/issues/52323' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -</div> -<hr class='hidden-lg' /> -<div class='hidden-lg secondary-column-feature'> -<h3 id='open-a-merge-request-with-a-patch-via-email'> -<a class='header-link' href='#open-a-merge-request-with-a-patch-via-email'> -<i class='fas fa-link'></i> -</a> -Open a merge request with a patch via email -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Core'> -<div class='available badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Starter'> -<div class='available badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Free'> -<div class='available badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Bronze'> -<div class='available badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Silver'> -<div class='available badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>GitLab has supported opening a merge request via email for a long time, -but before sending the email the branch must already exist on the -server. Now you can open a merge request with only an email by -attaching one or more patch files (<code>.patch</code>).</p> - -<p>Patch files are the standard for sharing and transmitting changes -between systems. In future releases of GitLab we will build on this -foundation for -<a href="https://gitlab.com/groups/gitlab-org/-/epics/260">distributed merge requests</a>, -which will allow merge requests between GitLab instances, and other -Git hosting tools too.</p> - -<figure class='video_container'> -<iframe allowfullscreen='true' frameborder='0' src='https://www.youtube.com/embed/Y6jb_3hV8Po'></iframe> -</figure> -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/ee/user/project/merge_requests/#adding-patches-when-creating-a-merge-request-via-e-mail' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/gitlab-org/gitlab-ce/issues/40830' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -</div> -<hr class='hidden-lg' /> -<div class='secondary-column-feature'> -<h3 id='empty-state-for-wiki-only-projects'> -<a class='header-link' href='#empty-state-for-wiki-only-projects'> -<i class='fas fa-link'></i> -</a> -Empty state for Wiki-only projects -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Core'> -<div class='available badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Starter'> -<div class='available badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Free'> -<div class='available badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Bronze'> -<div class='available badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Silver'> -<div class='available badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>We’ve improved the experience for Wiki-only projects without a default -project overview page. -The empty state for this project setup now better encourages users to add -a page to the relevant Wiki and get these projects off to a great start.</p> - -<img alt='Empty state for Wiki-only projects' class='shadow' src='/images/11_5/wiki-project-empty-state.png' /> -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/ee/user/project/wiki/index.html' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/gitlab-org/gitlab-ce/issues/48731' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -</div> -<hr class='hidden-lg' /> -<div class='hidden-lg secondary-column-feature'> -<h3 id='open-jaeger-from-gitlab'> -<a class='header-link' href='#open-jaeger-from-gitlab'> -<i class='fas fa-link'></i> -</a> -Open Jaeger from GitLab -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Core'> -<div class='badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Starter'> -<div class='badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Premium'> -<div class='badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Free'> -<div class='badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Bronze'> -<div class='badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Silver'> -<div class='badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>Tracing provides deep introspection into the performance and health of a deployed application, tracking each function or microservice -which handles a given request. This makes it easy to understand the end-to-end flow of a request, regardless of whether you are using -a monolithic or distributed system.</p> - -<p>GitLab 11.5 includes an initial integration with <a href="https://www.jaegertracing.io">Jaeger</a>, the <a href="https://www.cncf.io">CNCF</a>-hosted tracing project, -allowing users to easily open the Jaeger UI from GitLab.</p> - -<img alt='Open Jaeger from GitLab' class='shadow' src='/images/11_5/jaeger.png' /> -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/ee/user/project/operations/tracing.html' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/gitlab-org/gitlab-ee/issues/4753' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -</div> -<hr class='hidden-lg' /> -<div class='secondary-column-feature'> -<h3 id='consistent-status-check-names-for-github-integration'> -<a class='header-link' href='#consistent-status-check-names-for-github-integration'> -<i class='fas fa-link'></i> -</a> -Consistent status-check names for GitHub integration -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Core'> -<div class='badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Starter'> -<div class='badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Free'> -<div class='badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Bronze'> -<div class='badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Silver'> -<div class='available badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>It is now possible to configure status checks on the GitHub side that can be marked as “required” -without having to configure this one by one, based on their name. Previously, the check -names included the branch name, so it was not possible to do this easily. This feature is -enabled via the GitHub integration configuration section.</p> - -<img alt='Consistent status-check names for GitHub integration' class='shadow' src='/images/11_5/consistent-check-names.png' /> -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/ee/user/project/integrations/github.html#static--dynamic-status-check-names' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/gitlab-org/gitlab-ee/issues/6696' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -</div> -<hr class='hidden-lg' /> -<div class='hidden-lg secondary-column-feature'> -<h3 id='omnibus-go-apps-now-use-the-gitlab-cert-directory'> -<a class='header-link' href='#omnibus-go-apps-now-use-the-gitlab-cert-directory'> -<i class='fas fa-link'></i> -</a> -Omnibus Go apps now use the GitLab cert directory -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Core'> -<div class='available badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Starter'> -<div class='available badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Free'> -<div class='badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Bronze'> -<div class='badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Silver'> -<div class='badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Gold'> -<div class='badge'>GOLD</div> -</a> -</div> -</div> - -<p>GitLab includes a number of Go-based applications. Prior to 11.5, these applications utilized the standard OS -system location for trusted certificates, instead of the Omnibus GitLab directory.</p> - -<p>With this release, Go applications now use the same directory for trusted certificates as the rest of GitLab, -by default <code>/opt/gitlab/embedded/ssl/certs/</code>, making certificate management easier and more straightforward.</p> - -<p>GitLab installations which depended upon the Go applications using the system directory should move those certificates -to the standard Omnibus GitLab location.</p> - -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/omnibus/settings/ssl.html#install-custom-public-certificates' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/gitlab-org/omnibus-gitlab/issues/3701' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -</div> -<hr class='hidden-lg' /> -<div class='secondary-column-feature'> -<h3 id='close-epic-notification'> -<a class='header-link' href='#close-epic-notification'> -<i class='fas fa-link'></i> -</a> -Close epic notification -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Core'> -<div class='badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Starter'> -<div class='badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Premium'> -<div class='badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Free'> -<div class='badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Bronze'> -<div class='badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Silver'> -<div class='badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>We recently released the ability to close epics, namely having different -open and closed states for epics. In this release, we are adding notifications -for closing and reopening epics, to help users follow more closely on work -they are interested in.</p> - -<img alt='Close epic notification' class='shadow' src='/images/11_5/epic-closed-notification.png' /> -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/ee/workflow/notifications.html' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/gitlab-org/gitlab-ee/issues/7272' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -</div> -<hr class='hidden-lg' /> -<div class='hidden-lg secondary-column-feature'> -<h3 id='json-logging-for-audit-events'> -<a class='header-link' href='#json-logging-for-audit-events'> -<i class='fas fa-link'></i> -</a> -JSON logging for audit events -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Core'> -<div class='available badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Starter'> -<div class='available badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Free'> -<div class='badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Bronze'> -<div class='badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Silver'> -<div class='badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Gold'> -<div class='badge'>GOLD</div> -</a> -</div> -</div> - -<p>In order to make audit events easier to analyze and ingest outside of GitLab, we’ve added <code>audit_json.log</code> to -capture audit events in a structured log file. With this change, shipping and parsing logs becomes much easier – -especially for visualization and analysis in other tools.</p> - -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/ee/administration/audit_events.html' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/gitlab-org/gitlab-ce/issues/54244' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -</div> -<hr class='hidden-lg' /> -<div class='secondary-column-feature'> -<h3 id='autocomplete-epic-in-issue-and-merge-request'> -<a class='header-link' href='#autocomplete-epic-in-issue-and-merge-request'> -<i class='fas fa-link'></i> -</a> -Autocomplete epic in issue and merge request -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Core'> -<div class='badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Starter'> -<div class='badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Premium'> -<div class='badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Free'> -<div class='badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Bronze'> -<div class='badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Silver'> -<div class='badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>You can now more easily search and refer to epics while working in an issue -or merge request. Just type <code>&amp;</code> and enter a few numbers or characters in -the issue or merge request’s description or a comment. GitLab’s autocomplete -will search for epics in the immediate parent group, allowing you to select -one easily all without leaving the current page.</p> - -<img alt='Autocomplete epic in issue and merge request' class='shadow' src='/images/11_5/autocomplete-epic.png' /> -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/ee/user/markdown.html#special-gitlab-references' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/gitlab-org/gitlab-ee/issues/7472' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -</div> -<hr class='hidden-lg' /> -<div class='hidden-lg secondary-column-feature'> -<h3 id='file-list-for-browsing-merge-request-diff'> -<a class='header-link' href='#file-list-for-browsing-merge-request-diff'> -<i class='fas fa-link'></i> -</a> -File list for browsing merge request diff -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Core'> -<div class='available badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Starter'> -<div class='available badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Free'> -<div class='available badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Bronze'> -<div class='available badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Silver'> -<div class='available badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>Moving backwards and forwards between files in the merge request diff -is necessary in all but the smallest of changes. In addition to the -<a href="/2018/10/22/gitlab-11-4-released/#file-tree-for-browsing-merge-request-diff">file tree added in -GitLab 11.4</a>, -GitLab now includes a searchable file list of changes to -make it easy to see which files have changed and jump between them, -whether you prefer a tree or a list.</p> - -<img alt='File list for browsing merge request diff' class='shadow' src='/images/11_5/mr-tree-list.png' /> -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/ee/user/project/merge_requests/index.html#merge-request-diff-file-navigation' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/gitlab-org/gitlab-ce/issues/51859' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -</div> -<hr class='hidden-lg' /> -<div class='secondary-column-feature'> -<h3 id='more-information-about-deployments-in-merge-requests'> -<a class='header-link' href='#more-information-about-deployments-in-merge-requests'> -<i class='fas fa-link'></i> -</a> -More information about deployments in merge requests -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Core'> -<div class='available badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Starter'> -<div class='available badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Free'> -<div class='available badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Bronze'> -<div class='available badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Silver'> -<div class='available badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>Currently, environment information is hidden when a newer pipeline is running. With this change -we are adding information on in-progress deployments to the widget, so you know that an update -is on its way.</p> - -<p>One of the most exciting results of this functionality in this release is that the link to the -current deployment will remain available in cases where a new deployment is running, allowing -you to still find the link to the Review App. In cases where lots of deployments were constantly -running, this previously made it quite difficult to get the timing right in some cases.</p> - -<img alt='More information about deployments in merge requests' class='shadow' src='/images/11_5/enhanced-deploy-information-MR.png' /> -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/ee/user/project/merge_requests/index.html#pipeline-status-in-merge-requests' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/gitlab-org/gitlab-ce/issues/25140' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -</div> -<hr class='hidden-lg' /> -<div class='hidden-lg secondary-column-feature'> -<h3 id='authenticate-with-jira-cloud-using-email-address-and-api-token'> -<a class='header-link' href='#authenticate-with-jira-cloud-using-email-address-and-api-token'> -<i class='fas fa-link'></i> -</a> -Authenticate with Jira Cloud using email address and API token -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Core'> -<div class='available badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Starter'> -<div class='available badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Free'> -<div class='available badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Bronze'> -<div class='available badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Silver'> -<div class='available badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>Jira Cloud is <a href="https://confluence.atlassian.com/cloud/blog/2018/06/say-goodbye-to-usernames-in-atlassian-cloud">removing usernames for authentication</a>. -So to support this change, we now allow you to use an email address and -API token to authenticate with Jira Cloud instead.</p> - -<img alt='Authenticate with Jira Cloud using email address and API token' class='shadow' src='/images/11_5/jira-email-api-token.png' /> -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/ee/user/project/integrations/jira.html#configuring-gitlab' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/gitlab-org/gitlab-ce/issues/49936' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -</div> -<hr class='hidden-lg' /> -<div class='secondary-column-feature'> -<h3 id='automatically-navigate-to-last-visited-board'> -<a class='header-link' href='#automatically-navigate-to-last-visited-board'> -<i class='fas fa-link'></i> -</a> -Automatically navigate to last visited board -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Core'> -<div class='badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Starter'> -<div class='available badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Free'> -<div class='badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Bronze'> -<div class='available badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Silver'> -<div class='available badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>As teams use more and more issue boards, it can become cumbersome to navigate -among many of them in the dropdown navigation. With this release, GitLab -will automatically send you to the last visited board, whenever you access -the boards navigation from the sidebar menu of a given project or a group. -This is saved to the system, so even if you use GitLab between different -browsers and devices, the last visited board will be saved.</p> - -<p>Note that you can still directly link to a specific board by saving the -URL of the board when you are viewing it.</p> - -<p>See upcoming planned improvements to <a href="https://gitlab.com/groups/gitlab-org/-/epics/336">managing multiple boards</a> -and participate in the comments.</p> - -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/ee/user/project/issue_board.html#multiple-issue-boards-starter' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/gitlab-org/gitlab-ee/issues/7760' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -</div> -<hr class='hidden-lg' /> -<div class='hidden-lg secondary-column-feature'> -<h3 id='filter-by-open-or-closed-epics-in-api'> -<a class='header-link' href='#filter-by-open-or-closed-epics-in-api'> -<i class='fas fa-link'></i> -</a> -Filter by open or closed epics in API -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Core'> -<div class='badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Starter'> -<div class='badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Premium'> -<div class='badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Free'> -<div class='badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Bronze'> -<div class='badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Silver'> -<div class='badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>We recently released the ability to close epics, namely having different -open and closed states for epics. In this release, we are exposing that -state in the API itself, so that you can filter on open or closed epics -when retrieving a list of them, as well as see the state in a single epic -retrieved itself.</p> - -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/ee/api/epics.html' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/gitlab-org/gitlab-ee/issues/7615' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -</div> -<hr class='hidden-lg' /> -<div class='secondary-column-feature'> -<h3 id='milestone-changed-notification'> -<a class='header-link' href='#milestone-changed-notification'> -<i class='fas fa-link'></i> -</a> -Milestone changed notification -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Core'> -<div class='available badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Starter'> -<div class='available badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Free'> -<div class='available badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Bronze'> -<div class='available badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Silver'> -<div class='available badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>GitLab milestones are useful for teams to plan and track work to be done -in a time-boxed period or to associate with a code release. These dates -are important for teams to communicate timelines with each other and -stakeholders in general. So when milestones change, it is critical that -people are updated.</p> - -<p>With this release, we’ve added email notifications for changing milestones -in issues and merge requests, so that people can stay updated if a piece -of work has been delayed, moved earlier, or just de-scoped.</p> - -<img alt='Milestone changed notification' class='shadow' src='/images/11_5/milestone-changed-notification.png' /> -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/ee/workflow/notifications.html#issue--merge-request-events' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/gitlab-org/gitlab-ce/issues/51520' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -</div> -<hr class='hidden-lg' /> -<div class='hidden-lg secondary-column-feature'> -<h3 id='epic-keyboard-shortcuts'> -<a class='header-link' href='#epic-keyboard-shortcuts'> -<i class='fas fa-link'></i> -</a> -Epic keyboard shortcuts -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Core'> -<div class='badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Starter'> -<div class='badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Premium'> -<div class='badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Free'> -<div class='badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Bronze'> -<div class='badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Silver'> -<div class='badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>Similar to issues and merge requests, you can perform basic operations in -an epic page with keyboard shortcuts, helping those users who want to get -more done, more quickly, without leaving the keyboard.</p> - -<p>Use <kbd>r</kbd> to start a new comment. (It will even quote selected text.) -Use <kbd>e</kbd> to edit the description. And use <kbd>l</kbd> to change -labels.</p> - -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/ee/workflow/shortcuts.html#epics' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/gitlab-org/gitlab-ee/issues/4187' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -</div> -<hr class='hidden-lg' /> -<div class='secondary-column-feature'> -<h3 id='issue-board-cards-redesigned'> -<a class='header-link' href='#issue-board-cards-redesigned'> -<i class='fas fa-link'></i> -</a> -Issue Board cards redesigned -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Core'> -<div class='available badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Starter'> -<div class='available badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Free'> -<div class='available badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Bronze'> -<div class='available badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Silver'> -<div class='available badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>A central place of collaboration in GitLab is Issue Boards, where teams -can organize and view planned and ongoing work in one location. With this -release, we’ve improved the design of issue cards, showing relevant information -in a simple and organized manner. We are showing the issue title, time-tracking -information, confidentiality, labels, due date, weight, and assignee, all -in the card.</p> - -<img alt='Issue Board cards redesigned' class='shadow' src='/images/11_5/board-card-design.png' /> -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/ee/user/project/issue_board.html' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/gitlab-org/gitlab-ce/issues/47008' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -</div> -<hr class='hidden-lg' /> -<div class='hidden-lg secondary-column-feature'> -<h3 id='render-index-files-like-readmes-in-repositories'> -<a class='header-link' href='#render-index-files-like-readmes-in-repositories'> -<i class='fas fa-link'></i> -</a> -Render 'index' files like 'README's in repositories -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Core'> -<div class='available badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Starter'> -<div class='available badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Free'> -<div class='available badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Bronze'> -<div class='available badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Silver'> -<div class='available badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>When a <code>README.*</code> file is present in a directory of a repository, it’s -rendered automatically by GitLab without the need to explicitly -open it. With GitLab 11.5, it’s now possible to do the same thing with -an <code>index.*</code> file.</p> - -<p>This is particularly useful when you also deploy your content online -using a static site generator. Previously, if you used <code>README.md</code> it -would render to <code>README.html</code>, whereas with <code>index.html</code> you can now -have clean URLs since most web servers treat -<code>http://example.com/page/index.html</code> and <code>http://example.com/page/</code> the -same.</p> - -<p>This is not limited to Markdown files as GitLab supports a number of -<a href="https://docs.gitlab.com/ee/user/project/repository/index.html#supported-markup-languages-and-extensions">markup languages</a>.</p> - -<img alt='Render &#39;index&#39; files like &#39;README&#39;s in repositories' class='shadow' src='/images/11_5/index-file-repository.png' /> -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/ee/user/project/repository/index.html#repository-readme-and-index-files' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/gitlab-org/gitlab-ce/issues/18933' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -</div> -<hr class='hidden-lg' /> -<div class='secondary-column-feature'> -<h3 id='rbac-creates-service-account-restricted-to-projects-namespace'> -<a class='header-link' href='#rbac-creates-service-account-restricted-to-projects-namespace'> -<i class='fas fa-link'></i> -</a> -RBAC creates service account restricted to project's namespace -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Core'> -<div class='available badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Starter'> -<div class='available badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Free'> -<div class='available badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Bronze'> -<div class='available badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Silver'> -<div class='available badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>Securing Kubernetes instances is paramount for running production-ready, mission-critical apps. RBAC -provides great power and flexibility in securing your cluster.</p> - -<p>Starting in GitLab 11.5, our Kubernetes integration will create a dedicated service account and role -binding for each project’s namespace which will be used in GitLab CI jobs. This eliminates the need to -use the <code>cluster-admin</code> token when interacting with GitLab CI runners.</p> - -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/ee/user/project/clusters/#role-based-access-control-rbac' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/gitlab-org/gitlab-ce/issues/51716' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -</div> -<hr class='hidden-lg' /> -<div class='hidden-lg secondary-column-feature'> -<h3 id='discussion-activity-filter-in-issues-and-merge-requests'> -<a class='header-link' href='#discussion-activity-filter-in-issues-and-merge-requests'> -<i class='fas fa-link'></i> -</a> -Discussion activity filter in issues and merge requests -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Core'> -<div class='available badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Starter'> -<div class='available badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Free'> -<div class='available badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Bronze'> -<div class='available badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Silver'> -<div class='available badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>We are glad to see teams collaborating actively in issue and merge request -comments. For more involved discussions and longer-lived issues and merge -requests, the discussion activity can become very long, with a lot of generated -system notes.</p> - -<p>With this release, we’ve implemented a filter to allow you to focus on just -comments or system activity in the discussion area of an issue or merge request. -Your selection is saved for all issues or all merge requests in GitLab. -So if you prefer one mode, you can just make the selection once, and it -will persist forever.</p> - -<p>We are planning to bring <a href="https://gitlab.com/gitlab-org/gitlab-ee/issues/7526">the same functionality to epics</a> -too.</p> - -<img alt='Discussion activity filter in issues and merge requests' class='shadow' src='/images/11_5/discussion-activity-filter.png' /> -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/ee/user/discussions/' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/gitlab-org/gitlab-ce/issues/51323' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -</div> -<hr class='hidden-lg' /> -<div class='secondary-column-feature'> -<h3 id='update-git-submodules-via-api'> -<a class='header-link' href='#update-git-submodules-via-api'> -<i class='fas fa-link'></i> -</a> -Update Git submodules via API -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Core'> -<div class='available badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Starter'> -<div class='available badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Free'> -<div class='available badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Bronze'> -<div class='available badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Silver'> -<div class='available badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>Git submodules allow you to include a Git repository within another Git -repository. GitLab now supports updating the submodule reference via -the API. This is particularly useful for automation, allowing you to -keep your project up to date with the latest dependencies using the -API.</p> - -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/ee/api/repository_submodules.html' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/gitlab-org/gitlab-ce/issues/41213' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -</div> -<hr class='hidden-lg' /> -<div class='hidden-lg secondary-column-feature'> -<h3 id='show-feedback-if-git-push-validation-takes-too-long'> -<a class='header-link' href='#show-feedback-if-git-push-validation-takes-too-long'> -<i class='fas fa-link'></i> -</a> -Show feedback if Git push validation takes too long -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Core'> -<div class='available badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Starter'> -<div class='available badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Free'> -<div class='available badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Bronze'> -<div class='available badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Silver'> -<div class='available badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>Every time you push changes to a Git repository on GitLab, GitLab -performs checks on each commit to enforce permissions, repository size -restrictions and validates the presence of LFS objects. In some cases -large pushes can fail without feedback when validation takes too long.</p> - -<p>GitLab now provides feedback when Git push operations time out because -validation is taking too long. This will help debug the source of the -problem by providing better feedback to the user.</p> - -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/ee/topics/git/troubleshooting_git.html#timeout-during-git-pushpull' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/gitlab-org/gitlab-ce/issues/42790' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -</div> -<hr class='hidden-lg' /> -<div class='secondary-column-feature'> -<h3 id='discussion-activity-redesign-in-issues-merge-requests-and-epics'> -<a class='header-link' href='#discussion-activity-redesign-in-issues-merge-requests-and-epics'> -<i class='fas fa-link'></i> -</a> -Discussion activity redesign in issues, merge requests, and epics -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Core'> -<div class='available badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Starter'> -<div class='available badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Free'> -<div class='available badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Bronze'> -<div class='available badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Silver'> -<div class='available badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>In this release, we’ve improved the design of discussion activity in issues, -merge requests, and epics. We’ve made it easier to read comments and parse -system note activity, so you can focus on the information that’s relevant to -you at the given moment.</p> - -<img alt='Discussion activity redesign in issues, merge requests, and epics' class='shadow' src='/images/11_5/discussion-activity-design.png' /> -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/ee/user/discussions/' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/gitlab-org/gitlab-ce/issues/29294' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -</div> -<hr class='hidden-lg' /> -<div class='hidden-lg secondary-column-feature'> -<h3 id='quick-access-to-prioritized-group-settings'> -<a class='header-link' href='#quick-access-to-prioritized-group-settings'> -<i class='fas fa-link'></i> -</a> -Quick access to prioritized Group settings -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Core'> -<div class='available badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Starter'> -<div class='available badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Free'> -<div class='available badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Bronze'> -<div class='available badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Silver'> -<div class='available badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>With GitLab 11.5, we are iterating on the settings page of Groups to -prioritize the most sought-after configuration options. The top-most -section is expanded by default, and we’ve clarified labels and links to -provide clear direction on where to find settings and what they do. -We’re continuously working on this – Project and Admin settings improvements -are coming soon!</p> - -<img alt='Quick access to prioritized Group settings' class='shadow' src='/images/11_5/group-settings-quick-access.png' /> -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/ee/user/group/' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/gitlab-org/gitlab-ce/issues/49417' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -</div> -<hr class='hidden-lg' /> -<div class='secondary-column-feature'> -<h3 id='create-new-group-page-redesign'> -<a class='header-link' href='#create-new-group-page-redesign'> -<i class='fas fa-link'></i> -</a> -'Create new group' page redesign -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Core'> -<div class='available badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Starter'> -<div class='available badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Free'> -<div class='available badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Bronze'> -<div class='available badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Silver'> -<div class='available badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>With this release, we are aligning the ‘New group’ page with the ‘New -project’ page, consolidating and repositioning relevant fields for clarity -and consistency.</p> - -<img alt='&#39;Create new group&#39; page redesign' class='shadow' src='/images/11_5/create-new-group-redesign.png' /> -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/ee/user/group/' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/gitlab-org/gitlab-ce/issues/50962' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -</div> -<hr class='hidden-lg' /> -<div class='hidden-lg secondary-column-feature'> -<h3 id='help-menu-in-top-navigation'> -<a class='header-link' href='#help-menu-in-top-navigation'> -<i class='fas fa-link'></i> -</a> -Help menu in top navigation -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Core'> -<div class='available badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Starter'> -<div class='available badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Free'> -<div class='available badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Bronze'> -<div class='available badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Silver'> -<div class='available badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>With this release, we are updating the top navigation bar by moving two -items into a new, dedicated Help menu section. -We’ll continue to add additional items there related to instance-level -support and feedback in future iterations coming soon!</p> - -<img alt='Help menu in top navigation' class='shadow' src='/images/11_5/top-navigation-help-item.png' /> -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/gitlab-org/gitlab-ce/issues/50728' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -</div> -<hr class='hidden-lg' /> -<div class='secondary-column-feature'> -<h3 id='remediation-info-for-gemnasium'> -<a class='header-link' href='#remediation-info-for-gemnasium'> -<i class='fas fa-link'></i> -</a> -Remediation info for Gemnasium -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Core'> -<div class='badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Starter'> -<div class='badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Premium'> -<div class='badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Free'> -<div class='badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Bronze'> -<div class='badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Silver'> -<div class='badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p><a href="https://docs.gitlab.com/ee/user/project/merge_requests/dependency_scanning.html">Dependency Scanning</a> -relies on the <a href="https://gitlab.com/gitlab-org/security-products/gemnasium">Gemnasium service</a> for the -majority of supported languages. This allows GitLab to report known vulnerabilities in packages, but -this information was missing a remediation that helps developers to easily fix the problem.</p> - -<p>With GitLab 11.5, Gemnasium service provides remediations every time the information is available. -This is then reported in the vulnerability details window, and in the related issue. For example, the -remediation could report the minimum version a library should be updated to in order to fix the security -problem.</p> - -<img alt='Remediation info for Gemnasium' class='shadow' src='/images/11_5/gemnasium-remediation.png' /> -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/ee/user/project/merge_requests/dependency_scanning.html' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/gitlab-org/gitlab-ee/issues/7069' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -</div> -<hr class='hidden-lg' /> -<div class='hidden-lg secondary-column-feature'> -<h3 id='audit-event-logging-for-project-features-and-group-settings'> -<a class='header-link' href='#audit-event-logging-for-project-features-and-group-settings'> -<i class='fas fa-link'></i> -</a> -Audit event logging for project features and group settings -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Core'> -<div class='badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Starter'> -<div class='badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Free'> -<div class='badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Bronze'> -<div class='badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Silver'> -<div class='badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Gold'> -<div class='badge'>GOLD</div> -</a> -</div> -</div> - -<p>Audit Events captures important events that take place on your GitLab instance, and we’re now capturing additional changes in 11.5:</p> - -<ul> - <li><a href="https://gitlab.com/gitlab-org/gitlab-ee/issues/8027">Project-level feature settings changes</a></li> - <li><a href="https://gitlab.com/gitlab-org/gitlab-ee/issues/8051">Group settings changes</a></li> -</ul> - -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/ee/administration/audit_events.html' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -</div> -</div> -</div> -<hr class='hidden-lg' /> -<div class='secondary-column-feature'> -<h3 id='gitlab-helm-chart-improvements'> -<a class='header-link' href='#gitlab-helm-chart-improvements'> -<i class='fas fa-link'></i> -</a> -GitLab Helm chart improvements -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Core'> -<div class='available badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Starter'> -<div class='available badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Free'> -<div class='badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Bronze'> -<div class='badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Silver'> -<div class='badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Gold'> -<div class='badge'>GOLD</div> -</a> -</div> -</div> - -<ul> - <li>LDAP and OmniAuth settings have been <a href="https://gitlab.com/charts/gitlab/blob/master/doc/charts/globals.md#omniauth">unified in the <code>global</code> settings</a>, making it easier to configure. Users currently configuring it individually for each subchart will need to update their settings to upgrade to 11.5.</li> - <li>Git protocol v2 is now enabled.</li> - <li>The <a href="https://docs.gitlab.com/ee/administration/pseudonymizer.html">GitLab Pseudonymizer</a> is <a href="https://gitlab.com/charts/gitlab/blob/master/doc/charts/globals.md#pseudonymizer-settings">now supported</a>.</li> - <li>Maven package support is <a href="https://gitlab.com/charts/gitlab/tree/master/doc/advanced/external-object-storage#lfs-artifacts-uploads-packages">now available</a>.</li> -</ul> - -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/charts/gitlab/tree/master/doc' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -</div> -</div> -</div> -<hr class='hidden-lg' /> -<div class='hidden-lg secondary-column-feature'> -<h3 id='activity-dashboard-redesign'> -<a class='header-link' href='#activity-dashboard-redesign'> -<i class='fas fa-link'></i> -</a> -Activity dashboard redesign -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Core'> -<div class='available badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Starter'> -<div class='available badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Free'> -<div class='available badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Bronze'> -<div class='available badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Silver'> -<div class='available badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>With this release, we are updating the activity dashboard design to give a better view into who is -doing what in your GitLab instance. The new activity feed gives a reader more context on what -actions have taken place to keep you always up to date.</p> - -<img alt='Activity dashboard redesign' class='shadow' src='/images/11_5/activity-dashboard-redesign.png' /> -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/gitlab-org/gitlab-ce/issues/49403' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -</div> -<hr class='hidden-lg' /> -<div class='secondary-column-feature'> -<h3 id='gitlab-runner-115'> -<a class='header-link' href='#gitlab-runner-115'> -<i class='fas fa-link'></i> -</a> -GitLab Runner 11.5 -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Core'> -<div class='available badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Starter'> -<div class='available badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Free'> -<div class='available badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Bronze'> -<div class='available badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Silver'> -<div class='available badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>We’re also releasing GitLab Runner 11.5 today! GitLab Runner is the open source project -that is used to run your CI/CD jobs and send the results back to GitLab.</p> - -<h4 id="most-interesting-changes">Most interesting changes:</h4> - -<ul> - <li><a href="https://gitlab.com/gitlab-org/gitlab-runner/merge_requests/1057">Support RAW artifacts</a>.</li> - <li><a href="https://gitlab.com/gitlab-org/gitlab-runner/merge_requests/1051">Add failure reason for execution timeout</a>.</li> -</ul> - -<p>A list of all changes can be found in GitLab Runner’s <a href="https://gitlab.com/gitlab-org/gitlab-runner/blob/v11.5.0/CHANGELOG.md">CHANGELOG</a>.</p> - -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/runner' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -</div> -</div> -</div> -<hr class='hidden-lg' /> -<div class='hidden-lg secondary-column-feature'> -<h3 id='geo-improvements'> -<a class='header-link' href='#geo-improvements'> -<i class='fas fa-link'></i> -</a> -Geo improvements -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Core'> -<div class='badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Starter'> -<div class='badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Free'> -<div class='badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Bronze'> -<div class='badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Silver'> -<div class='badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Gold'> -<div class='badge'>GOLD</div> -</a> -</div> -</div> - -<p>We continually focus on improving our <a href="/solutions/geo/">Geo</a> feature for distributed teams. Some of the additional noteworthy improvements in GitLab 11.5 include:</p> - -<ul> - <li><a href="https://gitlab.com/gitlab-org/gitlab-ee/issues/7963">Rails console now always displays primary/secondary state correctly</a>.</li> - <li><a href="https://gitlab.com/gitlab-org/gitlab-ee/issues/8124">Secondary instances now show a more specific flash message on actionable pages</a>.</li> - <li><a href="https://gitlab.com/gitlab-org/gitlab-ee/issues/8121">Geo nodes projects list is now searchable</a>.</li> - <li><a href="https://gitlab.com/gitlab-org/gitlab-ee/issues/8120">Recheck/resync of projects can now be triggered for all projects</a>.</li> - <li><a href="https://gitlab.com/gitlab-org/gitlab-ee/issues/6070">Improved performance of Geo SQL queries</a>.</li> - <li><a href="https://docs.gitlab.com/ee/administration/geo/replication/">Major documentation improvements</a>.</li> -</ul> - -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/ee/administration/geo/replication/configuration.html' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/groups/gitlab-org/-/boards/805065?milestone_title=11.5&amp;label_name[]=Geo' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h6a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H5zm1 3a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm0 3a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm3-5h1a1 1 0 0 1 0 2H9a1 1 0 1 1 0-2zm0 3h1a1 1 0 0 1 0 2H9a1 1 0 1 1 0-2zm-3 5a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm3-2h1a1 1 0 0 1 0 2H9a1 1 0 0 1 0-2z"/></svg> - -Issue Board -</a> -</div> -</div> -</div> -<hr class='hidden-lg' /> -<div class='secondary-column-feature'> -<h3 id='omnibus-improvements'> -<a class='header-link' href='#omnibus-improvements'> -<i class='fas fa-link'></i> -</a> -Omnibus improvements -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Core'> -<div class='available badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Starter'> -<div class='available badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Free'> -<div class='badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Bronze'> -<div class='badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Silver'> -<div class='badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Gold'> -<div class='badge'>GOLD</div> -</a> -</div> -</div> - -<ul> - <li>GitLab 11.5 includes <a href="https://mattermost.com/blog/mattermost-5-4-user-focused-features-new-data-export-tool-mobile-enhancements-and-more/">Mattermost 5.4</a>, an <a href="https://mattermost.com/">open source Slack-alternative</a> whose newest release includes user-focused features, new data export tool, plus much more. This version also includes <a href="http://about.mattermost.com/security-updates/">security updates</a> and upgrade is recommended.</li> - <li>It is now possible to set the <a href="https://docs.gitlab.com/omnibus/settings/configuration.html#disable-user-and-group-account-management">desired group name</a> for each GitLab services to run as.</li> - <li>Go-based applications included in GitLab Omnibus now utilize the standard Omnibus Gitlab directory for trusted certificates.</li> - <li>The maximum number of concurrent connections to GitLab Pages can now be configured using <code>gitlab_pages['max_connections']</code>.</li> - <li><code>bundler</code> has been updated to 1.16.6, <code>unicode-display_width</code> to 1.4.0, <code>gitlab-monitor</code> to 2.19.1, and <code>gitlab-elasticsearch-indexer</code> to 0.3.0</li> - <li>We have improved the readability of the <a href="http://gitlab-org.gitlab.io/omnibus-gitlab/licenses.html">list of open source licenses in use by GitLab</a>.</li> -</ul> - -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/omnibus/' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -</div> -</div> -</div> -<hr class='hidden-lg' /> -<div class='hidden-lg secondary-column-feature'> -<h3 id='performance-improvements'> -<a class='header-link' href='#performance-improvements'> -<i class='fas fa-link'></i> -</a> -Performance improvements -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Core'> -<div class='available badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Starter'> -<div class='available badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Free'> -<div class='available badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Bronze'> -<div class='available badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Silver'> -<div class='available badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>Some of the more noteworthy performance improvements in GitLab 11.5 include:</p> - -<ul> - <li><a href="https://gitlab.com/gitlab-org/gitlab-ce/issues/43034">Issue board lists perform fewer SQL queries</a>.</li> - <li><a href="https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22606">Improved performance of the snippets dashboards by a factor of 250</a>.</li> - <li><a href="https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22732">License Management doesn’t require Docker-in-Docker, and can now be cached by GitLab Runner</a>. See the <a href="https://docs.gitlab.com/ee/ci/examples/license_management.html">new job definition</a>.</li> - <li><a href="https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/8027">Improve performance of rendering large reports</a>.</li> - <li><a href="https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22725">Significantly cut memory and SQL queries when reloading diffs</a>.</li> - <li><a href="https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22325">Use cached readme blobs where appropriate</a>.</li> - <li><a href="https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22731">Optimize merge request refresh by using the database to check commit SHAs</a>.</li> - <li><a href="https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22709">Reduce SQL queries needed to load open merge requests</a>.</li> -</ul> - -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' data-placement='auto' data-toggle='tooltip' href='https://gitlab.com/groups/gitlab-org/merge_requests?scope=all&amp;utf8=%E2%9C%93&amp;state=merged&amp;label_name%5B%5D=performance&amp;milestone_title=11.5' target='_blank' title='See all the performance improvements in GitLab 11.5'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M3.161 8.425l-2.016.063a.3.3 0 0 1-.222-.512l2.415-2.414a.3.3 0 0 1 .145-.08l2.139-.492c-.072.097-.146.196-.221.3-.36.491-1.734 2.433-1.973 2.765l-.267.37zm7.82 1.922l-.492 2.14a.3.3 0 0 1-.08.146l-2.415 2.414a.3.3 0 0 1-.511-.221l.063-2.017.356-.258c.364-.261 2.295-1.628 2.778-1.982l.301-.222zm-3.13-6.47c1.445-1.445 3.306-1.892 5.584-1.341.54 2.288.093 4.15-1.342 5.584-1.19 1.19-3.234 2.47-5.729 4.315-.127.094-.366.32-.716.68a1 1 0 0 1-1.423.01l-1.379-1.38a1 1 0 0 1 .01-1.423c.359-.35.585-.588.68-.715C5.373 7.12 6.652 5.076 7.85 3.877zm1.341 2.901a1 1 0 1 0 1.415-1.414 1 1 0 0 0-1.415 1.414z"/></svg> - -Performance improvements -</a> -</div> -</div> -</div> -<hr class='hidden-lg' /> -</div> -<div class='secondary-release-column'> -<div class='visible-lg secondary-column-feature'> -<h3 id='group-file-templates'> -<a class='header-link' href='#group-file-templates'> -<i class='fas fa-link'></i> -</a> -Group file templates -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Core'> -<div class='badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Starter'> -<div class='badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Free'> -<div class='badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Bronze'> -<div class='badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Silver'> -<div class='available badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>File templates for <code>LICENSE</code>, <code>.gitignore</code>, <code>Dockerfile</code>, and -<code>.gitlab-ci.yml</code> files make it easy to add these common files to -projects. Custom file templates can now be shared with all the projects -in a group and sub-groups, by configuring a template repository for the -group.</p> - -<p>Custom templates are useful when the templates provided by GitLab are -too generic, for example a custom license that should be used for every -project in the company, or a complex Dockerfile that should be used for -every microservice.</p> - -<p>Support for instance-wide template repositories was <a href="/2018/09/22/gitlab-11-3-released/#custom-file-templates-for-self-managed-instances">introduced -in GitLab 11.3</a>.</p> - -<img alt='Group file templates' class='shadow' src='/images/11_5/group-templates.png' /> -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/ee/user/group/#group-level-file-templates-premium' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/gitlab-org/gitlab-ee/issues/5987' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -<hr class='hidden-lg' /> -</div> -<div class='visible-lg secondary-column-feature'> -<h3 id='issue-analytics'> -<a class='header-link' href='#issue-analytics'> -<i class='fas fa-link'></i> -</a> -Issue Analytics -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Core'> -<div class='badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Starter'> -<div class='badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Free'> -<div class='badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Bronze'> -<div class='badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Silver'> -<div class='available badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>In this release, we have provided a dynamic chart showing the number of -issues created in your group, per month, for the past year. There is even -a filter that allows you to filter down to a particular scope of issues.</p> - -<p>This will help teams dig more deeply into their issue analytics. For example, -you can quickly see how many bug issues have been created, if you use a -bug label.</p> - -<p>See how we plan to <a href="https://gitlab.com/groups/gitlab-org/-/epics/313">expand on charting capabilities</a> -and please participate in the discussion.</p> - -<img alt='Issue Analytics' class='shadow' src='/images/11_5/issue-analytics.png' /> -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/ee/user/group/issues_analytics/index.html' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/gitlab-org/gitlab-ee/issues/7478' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -<hr class='hidden-lg' /> -</div> -<div class='visible-lg secondary-column-feature'> -<h3 id='keep-your-email-address-private'> -<a class='header-link' href='#keep-your-email-address-private'> -<i class='fas fa-link'></i> -</a> -Keep your email address private -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Core'> -<div class='available badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Starter'> -<div class='available badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Free'> -<div class='available badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Bronze'> -<div class='available badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Silver'> -<div class='available badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>It’s important to know who is contributing code to your project and be -able to look up a commit author in the GitLab interface, using Git locally, -or on a fork hosted elsewhere, but this exposes your email publicly.</p> - -<p>GitLab now provides a <code>noreply</code> email address that can be used locally -and for web commits to help make it easier to keep your email address -private.</p> - -<img alt='Keep your email address private' class='shadow' src='/images/11_5/noreply-email.png' /> -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/ee/user/profile/#private-commit-email' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/gitlab-org/gitlab-ce/issues/43521' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -<hr class='hidden-lg' /> -</div> -<div class='visible-lg secondary-column-feature'> -<h3 id='open-a-merge-request-with-a-patch-via-email'> -<a class='header-link' href='#open-a-merge-request-with-a-patch-via-email'> -<i class='fas fa-link'></i> -</a> -Open a merge request with a patch via email -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Core'> -<div class='available badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Starter'> -<div class='available badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Free'> -<div class='available badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Bronze'> -<div class='available badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Silver'> -<div class='available badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>GitLab has supported opening a merge request via email for a long time, -but before sending the email the branch must already exist on the -server. Now you can open a merge request with only an email by -attaching one or more patch files (<code>.patch</code>).</p> - -<p>Patch files are the standard for sharing and transmitting changes -between systems. In future releases of GitLab we will build on this -foundation for -<a href="https://gitlab.com/groups/gitlab-org/-/epics/260">distributed merge requests</a>, -which will allow merge requests between GitLab instances, and other -Git hosting tools too.</p> - -<figure class='video_container'> -<iframe allowfullscreen='true' frameborder='0' src='https://www.youtube.com/embed/Y6jb_3hV8Po'></iframe> -</figure> -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/ee/user/project/merge_requests/#adding-patches-when-creating-a-merge-request-via-e-mail' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/gitlab-org/gitlab-ce/issues/40830' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -<hr class='hidden-lg' /> -</div> -<div class='visible-lg secondary-column-feature'> -<h3 id='open-jaeger-from-gitlab'> -<a class='header-link' href='#open-jaeger-from-gitlab'> -<i class='fas fa-link'></i> -</a> -Open Jaeger from GitLab -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Core'> -<div class='badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Starter'> -<div class='badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Premium'> -<div class='badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Free'> -<div class='badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Bronze'> -<div class='badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Silver'> -<div class='badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>Tracing provides deep introspection into the performance and health of a deployed application, tracking each function or microservice -which handles a given request. This makes it easy to understand the end-to-end flow of a request, regardless of whether you are using -a monolithic or distributed system.</p> - -<p>GitLab 11.5 includes an initial integration with <a href="https://www.jaegertracing.io">Jaeger</a>, the <a href="https://www.cncf.io">CNCF</a>-hosted tracing project, -allowing users to easily open the Jaeger UI from GitLab.</p> - -<img alt='Open Jaeger from GitLab' class='shadow' src='/images/11_5/jaeger.png' /> -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/ee/user/project/operations/tracing.html' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/gitlab-org/gitlab-ee/issues/4753' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -<hr class='hidden-lg' /> -</div> -<div class='visible-lg secondary-column-feature'> -<h3 id='omnibus-go-apps-now-use-the-gitlab-cert-directory'> -<a class='header-link' href='#omnibus-go-apps-now-use-the-gitlab-cert-directory'> -<i class='fas fa-link'></i> -</a> -Omnibus Go apps now use the GitLab cert directory -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Core'> -<div class='available badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Starter'> -<div class='available badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Free'> -<div class='badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Bronze'> -<div class='badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Silver'> -<div class='badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Gold'> -<div class='badge'>GOLD</div> -</a> -</div> -</div> - -<p>GitLab includes a number of Go-based applications. Prior to 11.5, these applications utilized the standard OS -system location for trusted certificates, instead of the Omnibus GitLab directory.</p> - -<p>With this release, Go applications now use the same directory for trusted certificates as the rest of GitLab, -by default <code>/opt/gitlab/embedded/ssl/certs/</code>, making certificate management easier and more straightforward.</p> - -<p>GitLab installations which depended upon the Go applications using the system directory should move those certificates -to the standard Omnibus GitLab location.</p> - -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/omnibus/settings/ssl.html#install-custom-public-certificates' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/gitlab-org/omnibus-gitlab/issues/3701' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -<hr class='hidden-lg' /> -</div> -<div class='visible-lg secondary-column-feature'> -<h3 id='json-logging-for-audit-events'> -<a class='header-link' href='#json-logging-for-audit-events'> -<i class='fas fa-link'></i> -</a> -JSON logging for audit events -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Core'> -<div class='available badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Starter'> -<div class='available badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Free'> -<div class='badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Bronze'> -<div class='badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Silver'> -<div class='badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Gold'> -<div class='badge'>GOLD</div> -</a> -</div> -</div> - -<p>In order to make audit events easier to analyze and ingest outside of GitLab, we’ve added <code>audit_json.log</code> to -capture audit events in a structured log file. With this change, shipping and parsing logs becomes much easier – -especially for visualization and analysis in other tools.</p> - -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/ee/administration/audit_events.html' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/gitlab-org/gitlab-ce/issues/54244' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -<hr class='hidden-lg' /> -</div> -<div class='visible-lg secondary-column-feature'> -<h3 id='file-list-for-browsing-merge-request-diff'> -<a class='header-link' href='#file-list-for-browsing-merge-request-diff'> -<i class='fas fa-link'></i> -</a> -File list for browsing merge request diff -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Core'> -<div class='available badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Starter'> -<div class='available badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Free'> -<div class='available badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Bronze'> -<div class='available badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Silver'> -<div class='available badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>Moving backwards and forwards between files in the merge request diff -is necessary in all but the smallest of changes. In addition to the -<a href="/2018/10/22/gitlab-11-4-released/#file-tree-for-browsing-merge-request-diff">file tree added in -GitLab 11.4</a>, -GitLab now includes a searchable file list of changes to -make it easy to see which files have changed and jump between them, -whether you prefer a tree or a list.</p> - -<img alt='File list for browsing merge request diff' class='shadow' src='/images/11_5/mr-tree-list.png' /> -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/ee/user/project/merge_requests/index.html#merge-request-diff-file-navigation' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/gitlab-org/gitlab-ce/issues/51859' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -<hr class='hidden-lg' /> -</div> -<div class='visible-lg secondary-column-feature'> -<h3 id='authenticate-with-jira-cloud-using-email-address-and-api-token'> -<a class='header-link' href='#authenticate-with-jira-cloud-using-email-address-and-api-token'> -<i class='fas fa-link'></i> -</a> -Authenticate with Jira Cloud using email address and API token -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Core'> -<div class='available badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Starter'> -<div class='available badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Free'> -<div class='available badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Bronze'> -<div class='available badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Silver'> -<div class='available badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>Jira Cloud is <a href="https://confluence.atlassian.com/cloud/blog/2018/06/say-goodbye-to-usernames-in-atlassian-cloud">removing usernames for authentication</a>. -So to support this change, we now allow you to use an email address and -API token to authenticate with Jira Cloud instead.</p> - -<img alt='Authenticate with Jira Cloud using email address and API token' class='shadow' src='/images/11_5/jira-email-api-token.png' /> -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/ee/user/project/integrations/jira.html#configuring-gitlab' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/gitlab-org/gitlab-ce/issues/49936' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -<hr class='hidden-lg' /> -</div> -<div class='visible-lg secondary-column-feature'> -<h3 id='filter-by-open-or-closed-epics-in-api'> -<a class='header-link' href='#filter-by-open-or-closed-epics-in-api'> -<i class='fas fa-link'></i> -</a> -Filter by open or closed epics in API -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Core'> -<div class='badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Starter'> -<div class='badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Premium'> -<div class='badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Free'> -<div class='badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Bronze'> -<div class='badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Silver'> -<div class='badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>We recently released the ability to close epics, namely having different -open and closed states for epics. In this release, we are exposing that -state in the API itself, so that you can filter on open or closed epics -when retrieving a list of them, as well as see the state in a single epic -retrieved itself.</p> - -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/ee/api/epics.html' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/gitlab-org/gitlab-ee/issues/7615' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -<hr class='hidden-lg' /> -</div> -<div class='visible-lg secondary-column-feature'> -<h3 id='epic-keyboard-shortcuts'> -<a class='header-link' href='#epic-keyboard-shortcuts'> -<i class='fas fa-link'></i> -</a> -Epic keyboard shortcuts -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Core'> -<div class='badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Starter'> -<div class='badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Premium'> -<div class='badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Free'> -<div class='badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Bronze'> -<div class='badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Silver'> -<div class='badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>Similar to issues and merge requests, you can perform basic operations in -an epic page with keyboard shortcuts, helping those users who want to get -more done, more quickly, without leaving the keyboard.</p> - -<p>Use <kbd>r</kbd> to start a new comment. (It will even quote selected text.) -Use <kbd>e</kbd> to edit the description. And use <kbd>l</kbd> to change -labels.</p> - -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/ee/workflow/shortcuts.html#epics' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/gitlab-org/gitlab-ee/issues/4187' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -<hr class='hidden-lg' /> -</div> -<div class='visible-lg secondary-column-feature'> -<h3 id='render-index-files-like-readmes-in-repositories'> -<a class='header-link' href='#render-index-files-like-readmes-in-repositories'> -<i class='fas fa-link'></i> -</a> -Render 'index' files like 'README's in repositories -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Core'> -<div class='available badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Starter'> -<div class='available badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Free'> -<div class='available badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Bronze'> -<div class='available badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Silver'> -<div class='available badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>When a <code>README.*</code> file is present in a directory of a repository, it’s -rendered automatically by GitLab without the need to explicitly -open it. With GitLab 11.5, it’s now possible to do the same thing with -an <code>index.*</code> file.</p> - -<p>This is particularly useful when you also deploy your content online -using a static site generator. Previously, if you used <code>README.md</code> it -would render to <code>README.html</code>, whereas with <code>index.html</code> you can now -have clean URLs since most web servers treat -<code>http://example.com/page/index.html</code> and <code>http://example.com/page/</code> the -same.</p> - -<p>This is not limited to Markdown files as GitLab supports a number of -<a href="https://docs.gitlab.com/ee/user/project/repository/index.html#supported-markup-languages-and-extensions">markup languages</a>.</p> - -<img alt='Render &#39;index&#39; files like &#39;README&#39;s in repositories' class='shadow' src='/images/11_5/index-file-repository.png' /> -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/ee/user/project/repository/index.html#repository-readme-and-index-files' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/gitlab-org/gitlab-ce/issues/18933' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -<hr class='hidden-lg' /> -</div> -<div class='visible-lg secondary-column-feature'> -<h3 id='discussion-activity-filter-in-issues-and-merge-requests'> -<a class='header-link' href='#discussion-activity-filter-in-issues-and-merge-requests'> -<i class='fas fa-link'></i> -</a> -Discussion activity filter in issues and merge requests -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Core'> -<div class='available badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Starter'> -<div class='available badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Free'> -<div class='available badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Bronze'> -<div class='available badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Silver'> -<div class='available badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>We are glad to see teams collaborating actively in issue and merge request -comments. For more involved discussions and longer-lived issues and merge -requests, the discussion activity can become very long, with a lot of generated -system notes.</p> - -<p>With this release, we’ve implemented a filter to allow you to focus on just -comments or system activity in the discussion area of an issue or merge request. -Your selection is saved for all issues or all merge requests in GitLab. -So if you prefer one mode, you can just make the selection once, and it -will persist forever.</p> - -<p>We are planning to bring <a href="https://gitlab.com/gitlab-org/gitlab-ee/issues/7526">the same functionality to epics</a> -too.</p> - -<img alt='Discussion activity filter in issues and merge requests' class='shadow' src='/images/11_5/discussion-activity-filter.png' /> -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/ee/user/discussions/' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/gitlab-org/gitlab-ce/issues/51323' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -<hr class='hidden-lg' /> -</div> -<div class='visible-lg secondary-column-feature'> -<h3 id='show-feedback-if-git-push-validation-takes-too-long'> -<a class='header-link' href='#show-feedback-if-git-push-validation-takes-too-long'> -<i class='fas fa-link'></i> -</a> -Show feedback if Git push validation takes too long -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Core'> -<div class='available badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Starter'> -<div class='available badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Free'> -<div class='available badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Bronze'> -<div class='available badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Silver'> -<div class='available badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>Every time you push changes to a Git repository on GitLab, GitLab -performs checks on each commit to enforce permissions, repository size -restrictions and validates the presence of LFS objects. In some cases -large pushes can fail without feedback when validation takes too long.</p> - -<p>GitLab now provides feedback when Git push operations time out because -validation is taking too long. This will help debug the source of the -problem by providing better feedback to the user.</p> - -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/ee/topics/git/troubleshooting_git.html#timeout-during-git-pushpull' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/gitlab-org/gitlab-ce/issues/42790' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -<hr class='hidden-lg' /> -</div> -<div class='visible-lg secondary-column-feature'> -<h3 id='quick-access-to-prioritized-group-settings'> -<a class='header-link' href='#quick-access-to-prioritized-group-settings'> -<i class='fas fa-link'></i> -</a> -Quick access to prioritized Group settings -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Core'> -<div class='available badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Starter'> -<div class='available badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Free'> -<div class='available badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Bronze'> -<div class='available badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Silver'> -<div class='available badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>With GitLab 11.5, we are iterating on the settings page of Groups to -prioritize the most sought-after configuration options. The top-most -section is expanded by default, and we’ve clarified labels and links to -provide clear direction on where to find settings and what they do. -We’re continuously working on this – Project and Admin settings improvements -are coming soon!</p> - -<img alt='Quick access to prioritized Group settings' class='shadow' src='/images/11_5/group-settings-quick-access.png' /> -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/ee/user/group/' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/gitlab-org/gitlab-ce/issues/49417' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -<hr class='hidden-lg' /> -</div> -<div class='visible-lg secondary-column-feature'> -<h3 id='help-menu-in-top-navigation'> -<a class='header-link' href='#help-menu-in-top-navigation'> -<i class='fas fa-link'></i> -</a> -Help menu in top navigation -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Core'> -<div class='available badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Starter'> -<div class='available badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Free'> -<div class='available badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Bronze'> -<div class='available badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Silver'> -<div class='available badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>With this release, we are updating the top navigation bar by moving two -items into a new, dedicated Help menu section. -We’ll continue to add additional items there related to instance-level -support and feedback in future iterations coming soon!</p> - -<img alt='Help menu in top navigation' class='shadow' src='/images/11_5/top-navigation-help-item.png' /> -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/gitlab-org/gitlab-ce/issues/50728' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -<hr class='hidden-lg' /> -</div> -<div class='visible-lg secondary-column-feature'> -<h3 id='audit-event-logging-for-project-features-and-group-settings'> -<a class='header-link' href='#audit-event-logging-for-project-features-and-group-settings'> -<i class='fas fa-link'></i> -</a> -Audit event logging for project features and group settings -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Core'> -<div class='badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Starter'> -<div class='badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Free'> -<div class='badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Bronze'> -<div class='badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Silver'> -<div class='badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Gold'> -<div class='badge'>GOLD</div> -</a> -</div> -</div> - -<p>Audit Events captures important events that take place on your GitLab instance, and we’re now capturing additional changes in 11.5:</p> - -<ul> - <li><a href="https://gitlab.com/gitlab-org/gitlab-ee/issues/8027">Project-level feature settings changes</a></li> - <li><a href="https://gitlab.com/gitlab-org/gitlab-ee/issues/8051">Group settings changes</a></li> -</ul> - -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/ee/administration/audit_events.html' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -</div> -</div> -<hr class='hidden-lg' /> -</div> -<div class='visible-lg secondary-column-feature'> -<h3 id='activity-dashboard-redesign'> -<a class='header-link' href='#activity-dashboard-redesign'> -<i class='fas fa-link'></i> -</a> -Activity dashboard redesign -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Core'> -<div class='available badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Starter'> -<div class='available badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Free'> -<div class='available badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Bronze'> -<div class='available badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Silver'> -<div class='available badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>With this release, we are updating the activity dashboard design to give a better view into who is -doing what in your GitLab instance. The new activity feed gives a reader more context on what -actions have taken place to keep you always up to date.</p> - -<img alt='Activity dashboard redesign' class='shadow' src='/images/11_5/activity-dashboard-redesign.png' /> -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/gitlab-org/gitlab-ce/issues/49403' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M10.892 3.072l1.048.185a3 3 0 0 1 2.433 3.476l-.868 4.924a3 3 0 0 1-3.12 2.474A3.98 3.98 0 0 0 11 12.03a.999.999 0 0 0 .535-.72l.869-4.924a1 1 0 0 0-.811-1.158L11 5.122V4c0-.32-.037-.63-.108-.928zM4 1h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4z"/></svg> - -Issue -</a> -</div> -</div> -<hr class='hidden-lg' /> -</div> -<div class='visible-lg secondary-column-feature'> -<h3 id='geo-improvements'> -<a class='header-link' href='#geo-improvements'> -<i class='fas fa-link'></i> -</a> -Geo improvements -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Core'> -<div class='badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Not available in GitLab Starter'> -<div class='badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Free'> -<div class='badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Bronze'> -<div class='badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Silver'> -<div class='badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Not available in GitLab.com Gold'> -<div class='badge'>GOLD</div> -</a> -</div> -</div> - -<p>We continually focus on improving our <a href="/solutions/geo/">Geo</a> feature for distributed teams. Some of the additional noteworthy improvements in GitLab 11.5 include:</p> - -<ul> - <li><a href="https://gitlab.com/gitlab-org/gitlab-ee/issues/7963">Rails console now always displays primary/secondary state correctly</a>.</li> - <li><a href="https://gitlab.com/gitlab-org/gitlab-ee/issues/8124">Secondary instances now show a more specific flash message on actionable pages</a>.</li> - <li><a href="https://gitlab.com/gitlab-org/gitlab-ee/issues/8121">Geo nodes projects list is now searchable</a>.</li> - <li><a href="https://gitlab.com/gitlab-org/gitlab-ee/issues/8120">Recheck/resync of projects can now be triggered for all projects</a>.</li> - <li><a href="https://gitlab.com/gitlab-org/gitlab-ee/issues/6070">Improved performance of Geo SQL queries</a>.</li> - <li><a href="https://docs.gitlab.com/ee/administration/geo/replication/">Major documentation improvements</a>.</li> -</ul> - -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' href='https://docs.gitlab.com/ee/administration/geo/replication/configuration.html' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h4.244a2 2 0 0 1 1.434.606l2.756 2.834A2 2 0 0 1 14 5.835V12a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V5.835L9.244 3H5zm1.5 7h3a.5.5 0 1 1 0 1h-3a.5.5 0 1 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1zM8 2l3 1.995L13 7H9a1 1 0 0 1-1-1V2z"/></svg> - -Documentation -</a> -<a class='btn btn-default btn-xs product-icon-xm' href='https://gitlab.com/groups/gitlab-org/-/boards/805065?milestone_title=11.5&amp;label_name[]=Geo' target='_blank'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M5 1h6a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V4a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H5zm1 3a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm0 3a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm3-5h1a1 1 0 0 1 0 2H9a1 1 0 1 1 0-2zm0 3h1a1 1 0 0 1 0 2H9a1 1 0 1 1 0-2zm-3 5a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm3-2h1a1 1 0 0 1 0 2H9a1 1 0 0 1 0-2z"/></svg> - -Issue Board -</a> -</div> -</div> -<hr class='hidden-lg' /> -</div> -<div class='visible-lg secondary-column-feature'> -<h3 id='performance-improvements'> -<a class='header-link' href='#performance-improvements'> -<i class='fas fa-link'></i> -</a> -Performance improvements -</h3> -<div class='badge-container dark'> -<div class='top-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Core'> -<div class='available badge'>CORE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Starter'> -<div class='available badge'>STARTER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Premium'> -<div class='available badge'>PREMIUM</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#self-managed' title='Available in GitLab Ultimate'> -<div class='available badge'>ULTIMATE</div> -</a> -</div> -<div class='bottom-row'> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Free'> -<div class='available badge'>FREE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Bronze'> -<div class='available badge'>BRONZE</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Silver'> -<div class='available badge'>SILVER</div> -</a> -<a data-placement='top' data-toggle='tooltip' href='/pricing/#gitlab-com' title='Available in GitLab.com Gold'> -<div class='available badge'>GOLD</div> -</a> -</div> -</div> - -<p>Some of the more noteworthy performance improvements in GitLab 11.5 include:</p> - -<ul> - <li><a href="https://gitlab.com/gitlab-org/gitlab-ce/issues/43034">Issue board lists perform fewer SQL queries</a>.</li> - <li><a href="https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22606">Improved performance of the snippets dashboards by a factor of 250</a>.</li> - <li><a href="https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22732">License Management doesn’t require Docker-in-Docker, and can now be cached by GitLab Runner</a>. See the <a href="https://docs.gitlab.com/ee/ci/examples/license_management.html">new job definition</a>.</li> - <li><a href="https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/8027">Improve performance of rendering large reports</a>.</li> - <li><a href="https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22725">Significantly cut memory and SQL queries when reloading diffs</a>.</li> - <li><a href="https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22325">Use cached readme blobs where appropriate</a>.</li> - <li><a href="https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22731">Optimize merge request refresh by using the database to check commit SHAs</a>.</li> - <li><a href="https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22709">Reduce SQL queries needed to load open merge requests</a>.</li> -</ul> - -<div class='row reference-buttons ref-buttons-second-features'> -<div class='col-md-12 col-sm-12'> -<a class='btn btn-default btn-xs product-icon-xm' data-placement='auto' data-toggle='tooltip' href='https://gitlab.com/groups/gitlab-org/merge_requests?scope=all&amp;utf8=%E2%9C%93&amp;state=merged&amp;label_name%5B%5D=performance&amp;milestone_title=11.5' target='_blank' title='See all the performance improvements in GitLab 11.5'> -<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M3.161 8.425l-2.016.063a.3.3 0 0 1-.222-.512l2.415-2.414a.3.3 0 0 1 .145-.08l2.139-.492c-.072.097-.146.196-.221.3-.36.491-1.734 2.433-1.973 2.765l-.267.37zm7.82 1.922l-.492 2.14a.3.3 0 0 1-.08.146l-2.415 2.414a.3.3 0 0 1-.511-.221l.063-2.017.356-.258c.364-.261 2.295-1.628 2.778-1.982l.301-.222zm-3.13-6.47c1.445-1.445 3.306-1.892 5.584-1.341.54 2.288.093 4.15-1.342 5.584-1.19 1.19-3.234 2.47-5.729 4.315-.127.094-.366.32-.716.68a1 1 0 0 1-1.423.01l-1.379-1.38a1 1 0 0 1 .01-1.423c.359-.35.585-.588.68-.715C5.373 7.12 6.652 5.076 7.85 3.877zm1.341 2.901a1 1 0 1 0 1.415-1.414 1 1 0 0 0-1.415 1.414z"/></svg> - -Performance improvements -</a> -</div> -</div> -<hr class='hidden-lg' /> -</div> -</div> -</div> -</section> -<!-- complementary information --> -<!-- deprecations --> -<section class='release-post-section' id='deprecations'> -<h2 class='text-center' id='release-deprecations'> -<a class='header-link' href='#release-deprecations'> -<i class='fas fa-link'></i> -</a> -Deprecations -</h2> -<h3 id='&lt;code&gt;sast_container&lt;/code&gt;-value-in-&lt;code&gt;gitlab_features&lt;/code&gt;-environment-variable'> -<a class='header-link' href='#&lt;code&gt;sast_container&lt;/code&gt;-value-in-&lt;code&gt;gitlab_features&lt;/code&gt;-environment-variable'> -<i class='fas fa-link'></i> -</a> -<code>sast_container</code> value in <code>GITLAB_FEATURES</code> environment variable -</h3> -<p>The <code>GITLAB_FEATURES</code> <a href="https://docs.gitlab.com/ee/ci/variables/#predefined-variables-environment-variables">environment variable</a>, -available to CI/CD jobs, lists all the available features based on the current license/tier.</p> - -<p>The <code>sast_container</code> value for <a href="https://docs.gitlab.com/ee/user/project/merge_requests/container_scanning.html">Container Scanning</a> -is now deprecated, and replaced with <code>container_scanning</code>. The old value could be removed in GitLab 12.0.</p> - -<p> -Removal date: -<strong>Mar. 22, 2019.</strong> -</p> -<h3 id='old-ci/cd-syntax-for-security,-quality,-and-performance-report-types'> -<a class='header-link' href='#old-ci/cd-syntax-for-security,-quality,-and-performance-report-types'> -<i class='fas fa-link'></i> -</a> -Old CI/CD syntax for security, quality, and performance report types -</h3> -<p>Before GitLab 11.5, jobs and artifacts had to be named specifically to automatically extract report data and show it in the merge request widget. -While these old job definitions are still working, they have been deprecated and may be removed in the next major release, GitLab 12.0.</p> - -<p>You are advised to update your current <code>.gitlab-ci.yml</code> configuration to reflect that change. You can find the new definitions in our -documentation for -<a href="https://docs.gitlab.com/ee/ci/examples/sast.html">SAST</a>, -<a href="https://docs.gitlab.com/ee/ci/examples/dast.html">DAST</a>, -<a href="https://docs.gitlab.com/ee/ci/examples/dependency_scanning.html">Dependency Scanning</a>, -<a href="https://docs.gitlab.com/ee/ci/examples/container_scanning.html">Container Scanning</a>, -<a href="https://docs.gitlab.com/ee/ci/examples/license_management.html">License Management</a>, -<a href="https://docs.gitlab.com/ee/ci/examples/code_quality.html">Code Quality</a>, and -<a href="https://docs.gitlab.com/ee//ci/examples/browser_performance.html">Browser Performance Testing</a>.</p> - -<p>The new syntax requires GitLab Runner 11.5 or newer to work correctly.</p> - -<p> -Removal date: -<strong>Mar. 22, 2019.</strong> -</p> -<h3 id='pipelines-older-than-three-months-are-no-longer-re-runnable'> -<a class='header-link' href='#pipelines-older-than-three-months-are-no-longer-re-runnable'> -<i class='fas fa-link'></i> -</a> -Pipelines older than three months are no longer re-runnable -</h3> -<p>As of this release, older jobs (&gt;3 months) will no longer be allowed to be “played” or “retried,” and rollback -will no longer be available. As of now we are not actually deleting this data so we can receive feedback on -potential problems with this change. Please join the discussion in <a href="https://gitlab.com/gitlab-org/gitlab-ce/issues/50939">#50939</a> if -you have concerns.</p> - -<p> -Removal date: -<strong>Nov. 22, 2018.</strong> -</p> -<h3 id='elasticsearch-5.5-and-earlier-not-supported-in-gitlab-11.5'> -<a class='header-link' href='#elasticsearch-5.5-and-earlier-not-supported-in-gitlab-11.5'> -<i class='fas fa-link'></i> -</a> -Elasticsearch 5.5 and earlier not supported in GitLab 11.5 -</h3> -<p>GitLab 11.5 will no longer support Elasticsearch 5.5 and below. It will only -support Elasticsearch 5.6 and 6.x. See the <a href="/2018/11/16/new-elasticsearch-version-requirements/">blog post</a> -for additional details.</p> - -<p> -Removal date: -<strong>Nov. 22, 2018.</strong> -</p> -<h3 id='support-for-prometheus-1.x-in-omnibus-gitlab'> -<a class='header-link' href='#support-for-prometheus-1.x-in-omnibus-gitlab'> -<i class='fas fa-link'></i> -</a> -Support for Prometheus 1.x in Omnibus GitLab -</h3> -<p>With GitLab 11.4 (Oct. 22, 2018) the bundled Prometheus 1.0 version is deprecated in Omnibus GitLab. Prometheus 2.0 is <a href="#prometheus-20-upgrade-for-omnibus-gitlab">now included</a>, -however the metrics format is incompatible with 1.0. Existing installations can upgrade to 2.0 and optionally migrate their data <a href="https://docs.gitlab.com/omnibus/update/gitlab_11_changes.html#11-4">using an included tool</a>.</p> - -<p>With GitLab 12.0 any installation not yet running Prometheus 2.0 will be automatically upgraded. Metric data from Prometheus 1.0 will not be migrated, and will be lost.</p> - -<p> -Removal date: -<strong>GitLab 12.0</strong> -</p> -</section> -<!-- Updgrade barometer --> -<section class='release-post-section' id='upgrade-barometer'> -<h2 class='text-center' id='barometer'> -<a class='header-link' href='#barometer'> -<i class='fas fa-link'></i> -</a> -Upgrade barometer -</h2> -<p>To upgrade to GitLab 11.5 from the latest 11.4 version, no downtime is required. To upgrade without downtime, please consult the <a href="https://docs.gitlab.com/ee/update/README.html#upgrading-without-downtime">documentation on downtimeless upgrades</a>.</p> - -<p>For this release we have migrations, post-deploy migrations, and to help with the larger migrations we have introduced background migrations.</p> - -<p>GitLab.com migrations took approximately 9 minutes and post-deploy migrations amounted for a total of around 32 minutes. Background migrations on the other hand are sidekiq jobs that will run synchronously, for this release these migrations took around 2 days to complete, no side effects were expected nor present, these target older kubernetes cluster integrations so newer kubernets cluster integrations are not affected.</p> - -<p>GitLab Geo users, please consult the documentation on <a href="https://docs.gitlab.com/ee/administration/geo/replication/updating_the_geo_nodes.html">upgrading Geo</a>.</p> - -<p>Go apps in Omnibus <a href="#go-apps-in-omnibus-now-use-standard-gitlab-certificate-directory">now use the standard GitLab certificate directory</a>. Installations which depended upon the Go applications using the system directory, should move those certificates to the standard Omnibus GitLab location.</p> - -</section> - - - - -GitLab Patch Release: 11.4.7 - -https://about.gitlab.com/2018/11/21/gitlab-11-4-7-released/ -2018-11-21T00:00:00+00:00 -2018-11-21T00:00:00+00:00 - -Jan Provaznik - -<!-- For detailed instructions on how to complete this, please see https://gitlab.com/gitlab-org/release/docs/blob/master/general/patch/blog-post.md --> - -<p>Today we are releasing version 11.4.7 for GitLab Community Edition and -Enterprise Edition. This release only contains a fix for GitLab Enterprise -Edition, GitLab Community Edition has no changes compared to 11.4.6.</p> - -<h2 id="gitlab-enterprise-edition">GitLab Enterprise Edition</h2> - -<p>Available in GitLab Starter, Premium, and Ultimate:</p> - -<ul> - <li><a href="https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/8248">Fix code owner suggestion missing in GitLab Starter</a></li> -</ul> - -<h2 id="upgrade-barometer">Upgrade barometer</h2> - -<p>This version does not include any new migrations, and should not require any -downtime.</p> - -<p>Please be aware that by default the Omnibus packages will stop, run migrations, -and start again, no matter how “big” or “small” the upgrade is. This behavior -can be changed by adding a <a href="http://docs.gitlab.com/omnibus/update/README.html"><code>/etc/gitlab/skip-auto-migrations</code></a> file, -which is only used for <a href="https://docs.gitlab.com/omnibus/update/README.html">updates</a>.</p> - -<h2 id="updating">Updating</h2> - -<p>To update, check out our <a href="/update/">update page</a>.</p> - -<h2 id="gitlab-subscriptions">GitLab subscriptions</h2> - -<p>Access to GitLab Starter, Premium, and Ultimate features is granted by a paid <a href="/pricing/">subscription</a>.</p> - -<p>Alternativelly, <a href="https://gitlab.com/users/sign_in">sign up for GitLab.com</a> -to use GitLab's own infrastructure.</p> -<img src='https://about.gitlab.com/images/default-blog-image.png' class='webfeedsFeaturedVisual' style='display: none;' /> - - -How we maintain product velocity with monthly releases - -https://about.gitlab.com/2018/11/21/why-gitlab-uses-a-monthly-release-cycle/ -2018-11-21T00:00:00+00:00 -2018-11-21T00:00:00+00:00 - -Suri Patel - -<p>We eagerly await the 22nd of each month, because we get to share the hard work of our team and community -with our users. Our <a href="/releases/">release</a> schedule illustrates our belief in the -<a href="/handbook/engineering/#the-importance-of-velocity">importance of velocity</a> and our -commitment to delivering value in the form of features. Monthly releases might -seem aggressive to outsiders, but we believe our ability to deliver -features quickly is a competitive advantage that has helped us find success.</p> - -<h2 id="three-cheers-for-monthly-releases">Three cheers for monthly releases!</h2> - -<p>A monthly release schedule is great for users, because it adds value at a -predictable pace. Most of GitLab's installations are self managed, helping users -identify when new functionality will arrive. As a user, you can look forward to the 22nd of -every month, knowing that's when new features become available.</p> - -<p><img src="/images/blogimages/releasebirthday.png" alt="A screenshot of a user's comment, which says that he is looking forward to February 22 more than 21, which is his birthday" class="shadow" /></p> - -<h3 id="a-predictable-schedule-helps-with-planning-team-capacity">A predictable schedule helps with planning team capacity</h3> - -<p>The team has also found that it's easier to determine how much capacity we have -when we're planning our workload, because there's no need to agree on -deadlines. GitLabbers know exactly how many days they have to work on something, -and we can plan in advance. Working with such a short timeframe forces us to -build features as small as possible. We can't say, "I need two releases for this," so we have to really think about how we -can make a feature smaller, an idea that's reinforced by our -<a href="/handbook/values/#iteration">iteration value</a>.</p> - -<div class="newsletter-cta-a panel panel-default panel-newsletter-cta"> -<div class="panel-body newsletter-cta"> -<div class="panel-header"> -<?xml version="1.0" encoding="UTF-8"?> -<svg width="56px" height="52px" viewBox="0 0 56 52" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> - <defs></defs> - <g id="Desktop" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> - <g id="blog-newsletter-cta-graphic-v2" transform="translate(-1070.000000, -383.000000)" fill="#FFFFFF"> - <g id="gitlab-newsletter-cta-b" transform="translate(948.000000, 363.000000)"> - <g id="Page-1" transform="translate(122.000000, 20.000000)"> - <path d="M53.1397841,30.8022957 L34.558125,44.3561117 L51.1622841,22.9844307 L53.4156477,29.9385534 C53.5192159,30.2590074 53.4081705,30.6062589 53.1397841,30.8022957 Z M2.86117045,30.8027742 C2.59198864,30.6062589 2.48094318,30.2590074 2.58419318,29.9395104 L4.83819318,22.9833141 L21.4412386,44.3634491 L2.86117045,30.8027742 Z M11.2584659,3.11293374 L16.410625,19.0155227 L6.12523864,19.0155227 L11.2584659,3.11293374 Z M36.0973295,21.5676699 L28.0054886,46.5780748 L19.9136477,21.5676699 L36.0973295,21.5676699 Z M44.7420114,3.11277423 L49.8844659,19.0155227 L39.5995568,19.0155227 L44.7420114,3.11277423 Z M31.4494886,44.2040994 L33.126625,39.0203693 L38.7700568,21.578038 L49.0266477,21.578038 L32.9091477,42.3254 L31.4494886,44.2040994 Z M17.2337614,21.578038 L24.5527386,44.1996331 L6.98544318,21.578038 L17.2337614,21.578038 Z M55.8366932,29.1508969 L52.8941477,20.069719 C52.8793523,19.9864552 52.8535795,19.904946 52.8220795,19.8248724 L46.9193295,1.57207485 C46.5984432,0.615657669 45.7433295,-4.78527557e-05 44.7385114,-4.78527557e-05 L44.725625,-4.78527557e-05 C43.7206477,0.00521595093 42.8707841,0.62730184 42.5600795,1.58547362 L36.9236477,19.0155227 L19.0866932,19.0155227 L13.4396023,1.58483558 C13.1295341,0.62746135 12.2796705,0.00537546013 11.2746932,-4.78527557e-05 C10.2687614,-0.00563067484 9.40314773,0.611669939 9.07589773,1.58611166 L3.17648864,19.8628356 C3.17092045,19.8781485 3.16344318,19.8923448 3.15851136,19.9076577 L0.163147727,29.151854 C-0.280556818,30.5249092 0.201329545,32.0172773 1.36269318,32.8658663 L27.2447159,51.755584 C27.4696705,51.919719 27.7320114,51.9999521 27.9932386,51.9999521 C28.2622614,51.9999521 28.5292159,51.9133387 28.7525795,51.746492 C28.753375,51.745854 28.7543295,51.745535 28.755125,51.7448969 L54.6377841,32.8655472 C55.7988295,32.0172773 56.2807159,30.5249092 55.8366932,29.1508969 Z" id="Fill-1"></path> - </g> - </g> - </g> - </g> -</svg> -<div id="above-cta-form"> -<div class="newsletter-preamble"> -New blog posts directly to your inbox -</div> -<div class="newsletter-sub-preamble"> -Sign up for our bi-monthly newsletter -</div> -</div> -<div id="confirm-cta-form" style="display: none;"> -<div class="newsletter-preamble"> -Thanks, you’re -<br /> -signed up! -</div> -<div class="newsletter-sub-preamble"> -GitLab is coming to your inbox -</div> -<img class="success-image" src="/images/emojis/newsletter-signup-success.png" /> -</div> -</div> -<div class="newsletter-form"> -<form class="notdefined" id="mktoForm_1546"> -<script src="//app-ab13.marketo.com/js/forms2/js/forms2.min.js"></script> -<script type="text/javascript"> -MktoForms2.loadForm("//app-ab13.marketo.com", "194-VVC-221", 1546, function(form) { - form.onSuccess(function(values, followUpUrl) { - - form.getFormElem().hide(); - document.getElementById('above-cta-form').style.display = 'none'; - document.getElementById('confirm-cta-form').style.display = 'block'; - - dataLayer.push({event: 'mktoLead',mktoFormId: form.getId()}); - return false; - }); - function getgacid() { - try { - var tracker = ga.getAll()[0]; - return tracker.get('clientId'); - } catch (e) { - return 'n/a'; - } - } - form.vals({ - 'gacid': getgacid() - }); -}); - -</script> -</form> -</div> -</div> - -</div> - -<blockquote> - <p>"Sometimes, team members will propose having longer release cycles, because -we'd be able to fit more into it, or we'd be able to do better quality control, -but I think that's short sighted. It's true that in a longer release cycle, you -can fit more in, but that will require bigger steps, and we know that -iteration is what makes us achieve velocity. So, the smaller the steps we take, -the faster we can go and the easier it is to do quality control. We think a -monthly release cycle is the optimal frequency." – <a href="/company/team/#sytses">Sid Sijbrandij</a>, GitLab CEO</p> -</blockquote> - -<h2 id="challenges-posed-by-monthly-releases">Challenges posed by monthly releases</h2> - -<h3 id="its-not-always-easy-to-stick-to-the-plan">It's not always easy to stick to the plan</h3> - -<p>It's not all sunshine and rainbows. While we're strong proponents of the monthly release, we realize that there are -quite a few challenges. A few of the drawbacks relate to our actual deadline -and staying on track with the <a href="/direction/">direction</a> of GitLab. For example, -a release might be far away, but we want to ship something now. Or, we want to -ship something, but the release just passed, and now we have to wait. Sometimes -we try to cram in something just before the merge window closes even -though it's not ready. When these situations arise, we remember to -<a href="/2015/12/07/why-we-shift-objectives-and-not-release-dates-at-gitlab/">shift objectives</a> -and focus on providing value to our users.</p> - -<h3 id="theres-a-big-impact-on-morale">There's a big impact on morale</h3> - -<p>One of the most bittersweet aspects of monthly releases is that morale can soar -or suffer, depending on the processes that are put in place. We're thrilled -when we make something and quickly see the benefits. With our schedule, GitLabbers see -their hard work in action within a month, which is way better than -in some enterprise organizations in which someone might make something that won't -get released for six months. At GitLab, people can rapidly effect change with -their contributions and feel like their work matters.</p> - -<p>There were times in the past, however, when our release schedule dampened morale. -In the early days, we had a few times when things came down to the wire, and we -battled bugs right until the end, making the 22nd look like an impossibility. -The rush towards the end caused quite a bit of stress on the team, so we decided -to create a bigger buffer between the release and the closing of our merge window. -We also developed a -<a href="https://gitlab.com/gitlab-org/release/docs/blob/master/README.md">release process</a> -to help keep us on track. Our -<a href="https://gitlab.com/gitlab-org/release-tools/blob/master/templates/monthly.md.erb">release template</a> -has helped us identify problems earlier so that we're not feeling pressured at -the end, which could be detrimental to everyone's motivation.</p> - -<h2 id="how-to-determine-the-right-cadence">How to determine the right cadence</h2> - -<p>While we've found success with monthly releases, we understand that it's not -right for everyone. If you're a SaaS provider, you don't need releases and can -just ship whenever something is finished. If you're shipping software that people -manage themselves, you're going to have to do versioning, so that people know -what version they're on and are aware of releases, patches, and upgrades. A -monthly release cycle forces you into this, so in that case, this cadence would -work well for your team. If there's hardware in the loop, extensive testing, or -human testing that's needed, then a longer release cadence is required, because -you have to factor in significant fixed costs.</p> - -<p>Identifying the right cadence for your organization comes down to experimentation -and what your users will accept. Some user bases may only want to update every -quarter or twice a year, while others want more frequent versions to stay current -with industry changes. Because we strongly believe that smaller steps let you -deliver faster, we encourage you to start with monthly releases and work towards -settling on the pacing that works best. <a href="/handbook/values/#collaboration">Collaborate</a> -with your team to create processes that simplify actions and hold -<a href="/handbook/engineering/management/team-retrospectives/">retrospectives</a> to make -adjustments. We've found that our -<a href="/2017/02/14/our-retrospective-and-kickoff-are-public/">retrospectives</a> are -extremely helpful in identifying consistent problem areas.</p> - -<p class="note"><a href="https://www.pexels.com/photo/22-apartment-architecture-building-210790/">Cover image</a> licensed under <a href="https://www.pexels.com/creative-commons-images/">CC 0</a></p> -<img src='https://about.gitlab.com/images/blogimages/monthlyrelease.jpg' class='webfeedsFeaturedVisual' style='display: none;' /> - - -GitLab Code Contributor: Hannes Rosenögger - -https://about.gitlab.com/2018/11/20/contributor-post-hannes/ -2018-11-20T00:00:00+00:00 -2018-11-20T00:00:00+00:00 - -Ray Paik - -<p>For this month's blog post, we're featuring another <a href="/community/core-team/">Core Team</a> member <a href="https://gitlab.com/haynes">Hannes Rosenögger</a>.</p> - -<h3 id="when-did-you-first-contribute-to-gitlab">When did you first contribute to GitLab?</h3> - -<p>My first <a href="https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/263">MR to close multiple issues with one commit</a> was back in December 2014. So that's almost four years ago!</p> - -<h3 id="why-and-how-did-you-decide-to-contribute-to-gitlab">Why and how did you decide to contribute to GitLab?</h3> - -<p>I used the Community Edition privately and noticed that mentioning multiple issues in an MR only closed the first issue. Since GitLab was open source and the fix was easy, I decided to fix it myself. GitLab's open policy about everything within the company was also a huge factor.</p> - -<div class="newsletter-cta-a panel panel-default panel-newsletter-cta"> -<div class="panel-body newsletter-cta"> -<div class="panel-header"> -<?xml version="1.0" encoding="UTF-8"?> -<svg width="56px" height="52px" viewBox="0 0 56 52" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> - <defs></defs> - <g id="Desktop" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> - <g id="blog-newsletter-cta-graphic-v2" transform="translate(-1070.000000, -383.000000)" fill="#FFFFFF"> - <g id="gitlab-newsletter-cta-b" transform="translate(948.000000, 363.000000)"> - <g id="Page-1" transform="translate(122.000000, 20.000000)"> - <path d="M53.1397841,30.8022957 L34.558125,44.3561117 L51.1622841,22.9844307 L53.4156477,29.9385534 C53.5192159,30.2590074 53.4081705,30.6062589 53.1397841,30.8022957 Z M2.86117045,30.8027742 C2.59198864,30.6062589 2.48094318,30.2590074 2.58419318,29.9395104 L4.83819318,22.9833141 L21.4412386,44.3634491 L2.86117045,30.8027742 Z M11.2584659,3.11293374 L16.410625,19.0155227 L6.12523864,19.0155227 L11.2584659,3.11293374 Z M36.0973295,21.5676699 L28.0054886,46.5780748 L19.9136477,21.5676699 L36.0973295,21.5676699 Z M44.7420114,3.11277423 L49.8844659,19.0155227 L39.5995568,19.0155227 L44.7420114,3.11277423 Z M31.4494886,44.2040994 L33.126625,39.0203693 L38.7700568,21.578038 L49.0266477,21.578038 L32.9091477,42.3254 L31.4494886,44.2040994 Z M17.2337614,21.578038 L24.5527386,44.1996331 L6.98544318,21.578038 L17.2337614,21.578038 Z M55.8366932,29.1508969 L52.8941477,20.069719 C52.8793523,19.9864552 52.8535795,19.904946 52.8220795,19.8248724 L46.9193295,1.57207485 C46.5984432,0.615657669 45.7433295,-4.78527557e-05 44.7385114,-4.78527557e-05 L44.725625,-4.78527557e-05 C43.7206477,0.00521595093 42.8707841,0.62730184 42.5600795,1.58547362 L36.9236477,19.0155227 L19.0866932,19.0155227 L13.4396023,1.58483558 C13.1295341,0.62746135 12.2796705,0.00537546013 11.2746932,-4.78527557e-05 C10.2687614,-0.00563067484 9.40314773,0.611669939 9.07589773,1.58611166 L3.17648864,19.8628356 C3.17092045,19.8781485 3.16344318,19.8923448 3.15851136,19.9076577 L0.163147727,29.151854 C-0.280556818,30.5249092 0.201329545,32.0172773 1.36269318,32.8658663 L27.2447159,51.755584 C27.4696705,51.919719 27.7320114,51.9999521 27.9932386,51.9999521 C28.2622614,51.9999521 28.5292159,51.9133387 28.7525795,51.746492 C28.753375,51.745854 28.7543295,51.745535 28.755125,51.7448969 L54.6377841,32.8655472 C55.7988295,32.0172773 56.2807159,30.5249092 55.8366932,29.1508969 Z" id="Fill-1"></path> - </g> - </g> - </g> - </g> -</svg> -<div id="above-cta-form"> -<div class="newsletter-preamble"> -New blog posts directly to your inbox -</div> -<div class="newsletter-sub-preamble"> -Sign up for our bi-monthly newsletter -</div> -</div> -<div id="confirm-cta-form" style="display: none;"> -<div class="newsletter-preamble"> -Thanks, you’re -<br /> -signed up! -</div> -<div class="newsletter-sub-preamble"> -GitLab is coming to your inbox -</div> -<img class="success-image" src="/images/emojis/newsletter-signup-success.png" /> -</div> -</div> -<div class="newsletter-form"> -<form class="notdefined" id="mktoForm_1546"> -<script src="//app-ab13.marketo.com/js/forms2/js/forms2.min.js"></script> -<script type="text/javascript"> -MktoForms2.loadForm("//app-ab13.marketo.com", "194-VVC-221", 1546, function(form) { - form.onSuccess(function(values, followUpUrl) { - - form.getFormElem().hide(); - document.getElementById('above-cta-form').style.display = 'none'; - document.getElementById('confirm-cta-form').style.display = 'block'; - - dataLayer.push({event: 'mktoLead',mktoFormId: form.getId()}); - return false; - }); - function getgacid() { - try { - var tracker = ga.getAll()[0]; - return tracker.get('clientId'); - } catch (e) { - return 'n/a'; - } - } - form.vals({ - 'gacid': getgacid() - }); -}); - -</script> -</form> -</div> -</div> - -</div> - -<h3 id="which-areas-of-the-gitlab-product-have-you-been-contributing-to">Which area(s) of the GitLab product have you been contributing to?</h3> - -<p>I guess it's been pretty random for me. Most of my contributions have been on the backend side and documentation fixes, but if I see something that I can easily fix or I need a feature for my work, I try to make a contribution. I also provide support on the #gitlab IRC channel on freenode. My IRC handle is <code>haynes</code>.</p> - -<h3 id="can-you-tell-us-what-you-do-professionally">Can you tell us what you do professionally?</h3> - -<p>I am a Java software developer for a public sector organization in Germany.</p> - -<h3 id="what-do-you-like-to-do-when-youre-not-working">What do you like to do when you're not working?</h3> - -<p>When I'm not working, I'm probably doing something for my local scout group. I enjoy working with the kids and teaching. I also like to fix things from coffee machines to cars. Basically anything that I can fix with a bit of work.</p> - -<!-- carousel --> - -<div id="carousel-example-generic-5" class="carousel slide medium center" data-ride="carousel" data-interval="10000"> - <!-- Indicators --> - <ol class="carousel-indicators"> - <li data-target="#carousel-example-generic-5" data-slide-to="0" class="active"></li> - <li data-target="#carousel-example-generic-5" data-slide-to="1"></li> - <li data-target="#carousel-example-generic-5" data-slide-to="2"></li> - </ol> - - <!-- Wrapper for slides --> - <div class="carousel-inner" role="listbox"> - <div class="item active"> - <img src="/images/blogimages/Hannes-blogpost/workbench.jpg" alt="Hannes on workbench" /> - </div> - <div class="item"> - <img src="/images/blogimages/Hannes-blogpost/dishwasher.jpg" alt="Hannes working on his dishwasher" /> - </div> - <div class="item"> - <img src="/images/blogimages/Hannes-blogpost/washing_machine.jpg" alt="Washing machine repair" /> - </div> - - </div> - - <!-- Controls --> - <a class="left carousel-control" href="#carousel-example-generic-5" role="button" data-slide="prev"> - <svg class="glyphicon glyphicon-chevron-left" width="11" height="19" viewBox="0 0 11 19" xmlns="http://www.w3.org/2000/svg"><path d="M.44 10.13l8.345 8.345 2.007-2.007-6.814-6.814 6.814-6.815L8.785.832.44 9.177a.652.652 0 0 0-.202.477c0 .183.067.343.202.477z" fill-rule="evenodd" /></svg> - <span class="sr-only">Previous</span> - </a> - <a class="right carousel-control" href="#carousel-example-generic-5" role="button" data-slide="next"> - <svg class="glyphicon glyphicon-chevron-right" width="11" height="19" viewBox="0 0 11 19" xmlns="http://www.w3.org/2000/svg"><path d="M10.59 10.13l-8.344 8.345L.24 16.468l6.814-6.814L.24 2.839 2.246.832l8.345 8.345a.652.652 0 0 1 .201.477.652.652 0 0 1-.201.477z" fill-rule="evenodd" /></svg> - <span class="sr-only">Next</span> - </a> -</div> - -<h3 id="what-advice-do-you-have-for-others-who-may-be-interested-in-contributing-to-gitlab">What advice do you have for others who may be interested in contributing to GitLab?</h3> - -<p>Contributing to GitLab is easier than it looks at a first glance and you can contribute to the community in many different ways. For example, if you want to help out translating the GitLab user interface to your native language on <a href="https://translate.gitlab.com/">CrowdIn</a>, this does not require programming skills or any special setup on your laptop. Also when you want to contribute code, reviewers are normally quite fast in getting back to you and are more than happy to help if you have any questions.</p> - -<p>If you are unsure how to get started or you need help, anyone should feel free to ping me on Twitter (<a href="https://twitter.com/hrosenoegger">@hrosenoegger</a>) or in the #gitlab IRC channel on <a href="http://freenode.net/">freenode</a>.</p> - -<h3 id="anything-else-you-want-to-share-with-the-community">Anything else you want to share with the community?</h3> - -<p>I love the fact that GitLab actually listens to the community. Even after they make a decision to add a new, paid feature, when community members believe it makes more sense to have the feature in <a href="/pricing/#self-managed">GitLab Core</a> or the free tier of <a href="/pricing/">GitLab.com</a>, they will actually port it back. The <a href="/2018/06/22/gitlab-11-0-released/#squash-and-merge-in-gitlab-core-and-gitlabcom-free">Squash and Merge feature</a> is a good example of that.</p> - -<h2 id="interested-in-learning-how-you-can-contribute">Interested in learning how you can contribute?</h2> - -<p>A good place to start is the <a href="/community/contribute/">Contributing to GitLab page</a>, where you can learn how you can contribute to GitLab code, documentation, translation, and UX design.</p> - -<p>If you have any questions, you are always welcome to reach me at rpaik@gitlab.com.</p> - -<p><em>Note: This post is part of a series featuring people who contribute to GitLab. Read the <a href="/2018/10/04/contributor-post-luke/">October Code Contributor post</a>, <a href="/2018/09/06/contributor-post-jacopo/">September Code Contributor post</a>, and <a href="/2018/08/08/contributor-post-vitaliy/">August Code Contributor post</a>.</em></p> -<img src='https://about.gitlab.com/images/blogimages/contributors-cover.png' class='webfeedsFeaturedVisual' style='display: none;' /> - - -Our top 6 tips for making the most of AWS re:Invent - -https://about.gitlab.com/2018/11/19/aws-pre-event-post/ -2018-11-19T00:00:00+00:00 -2018-11-19T00:00:00+00:00 - -William Chia - -<p>This year's <a href="/events/aws-reinvent/">AWS re:Invent</a>, Nov. 26-30, looks to be an amazing show. <a href="/solutions/aws/">GitLab works great together with AWS</a> and as an <a href="/partners/#strategic-partners">AWS partner</a> we're excited to be a part of the show. To help you prepare, the team has put together some top tips for getting the most out of re:Invent, along with a list of all the places you can find GitLab on site.</p> - -<h2 id="top-6-tips-for-aws">Top 6 tips for AWS</h2> - -<h3 id="1-strategize">1. Strategize</h3> - -<p>Know what is a must-do/-see for you and plan accordingly, including all talks and networking events. The week has so much going on and you, unfortunately, cannot do it all, so prioritize what is most important to you, and what you will get the most value out of.</p> - -<h3 id="2-manage-your-time">2. Manage your time</h3> - -<p>All transportation takes longer than you think it will or should during your time in Las Vegas. The conference footprint is huge. Give yourself a buffer to get to talks and plan on arriving early if you want to attend some of the more popular talks.</p> - -<h3 id="3-set-goals">3. Set goals</h3> - -<p>It is easy to get sidetracked, so having a set list of things you want to accomplish or a reminder of why you have chosen to invest your resources and time to be there can be key. When you are are starting to wear down on the morning of day three and need to remind yourself why you came, a list of goals can help you get out of bed 😃</p> - -<div class="newsletter-cta-a panel panel-default panel-newsletter-cta"> -<div class="panel-body newsletter-cta"> -<div class="panel-header"> -<?xml version="1.0" encoding="UTF-8"?> -<svg width="56px" height="52px" viewBox="0 0 56 52" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> - <defs></defs> - <g id="Desktop" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> - <g id="blog-newsletter-cta-graphic-v2" transform="translate(-1070.000000, -383.000000)" fill="#FFFFFF"> - <g id="gitlab-newsletter-cta-b" transform="translate(948.000000, 363.000000)"> - <g id="Page-1" transform="translate(122.000000, 20.000000)"> - <path d="M53.1397841,30.8022957 L34.558125,44.3561117 L51.1622841,22.9844307 L53.4156477,29.9385534 C53.5192159,30.2590074 53.4081705,30.6062589 53.1397841,30.8022957 Z M2.86117045,30.8027742 C2.59198864,30.6062589 2.48094318,30.2590074 2.58419318,29.9395104 L4.83819318,22.9833141 L21.4412386,44.3634491 L2.86117045,30.8027742 Z M11.2584659,3.11293374 L16.410625,19.0155227 L6.12523864,19.0155227 L11.2584659,3.11293374 Z M36.0973295,21.5676699 L28.0054886,46.5780748 L19.9136477,21.5676699 L36.0973295,21.5676699 Z M44.7420114,3.11277423 L49.8844659,19.0155227 L39.5995568,19.0155227 L44.7420114,3.11277423 Z M31.4494886,44.2040994 L33.126625,39.0203693 L38.7700568,21.578038 L49.0266477,21.578038 L32.9091477,42.3254 L31.4494886,44.2040994 Z M17.2337614,21.578038 L24.5527386,44.1996331 L6.98544318,21.578038 L17.2337614,21.578038 Z M55.8366932,29.1508969 L52.8941477,20.069719 C52.8793523,19.9864552 52.8535795,19.904946 52.8220795,19.8248724 L46.9193295,1.57207485 C46.5984432,0.615657669 45.7433295,-4.78527557e-05 44.7385114,-4.78527557e-05 L44.725625,-4.78527557e-05 C43.7206477,0.00521595093 42.8707841,0.62730184 42.5600795,1.58547362 L36.9236477,19.0155227 L19.0866932,19.0155227 L13.4396023,1.58483558 C13.1295341,0.62746135 12.2796705,0.00537546013 11.2746932,-4.78527557e-05 C10.2687614,-0.00563067484 9.40314773,0.611669939 9.07589773,1.58611166 L3.17648864,19.8628356 C3.17092045,19.8781485 3.16344318,19.8923448 3.15851136,19.9076577 L0.163147727,29.151854 C-0.280556818,30.5249092 0.201329545,32.0172773 1.36269318,32.8658663 L27.2447159,51.755584 C27.4696705,51.919719 27.7320114,51.9999521 27.9932386,51.9999521 C28.2622614,51.9999521 28.5292159,51.9133387 28.7525795,51.746492 C28.753375,51.745854 28.7543295,51.745535 28.755125,51.7448969 L54.6377841,32.8655472 C55.7988295,32.0172773 56.2807159,30.5249092 55.8366932,29.1508969 Z" id="Fill-1"></path> - </g> - </g> - </g> - </g> -</svg> -<div id="above-cta-form"> -<div class="newsletter-preamble"> -New blog posts directly to your inbox -</div> -<div class="newsletter-sub-preamble"> -Sign up for our bi-monthly newsletter -</div> -</div> -<div id="confirm-cta-form" style="display: none;"> -<div class="newsletter-preamble"> -Thanks, you’re -<br /> -signed up! -</div> -<div class="newsletter-sub-preamble"> -GitLab is coming to your inbox -</div> -<img class="success-image" src="/images/emojis/newsletter-signup-success.png" /> -</div> -</div> -<div class="newsletter-form"> -<form class="notdefined" id="mktoForm_1546"> -<script src="//app-ab13.marketo.com/js/forms2/js/forms2.min.js"></script> -<script type="text/javascript"> -MktoForms2.loadForm("//app-ab13.marketo.com", "194-VVC-221", 1546, function(form) { - form.onSuccess(function(values, followUpUrl) { - - form.getFormElem().hide(); - document.getElementById('above-cta-form').style.display = 'none'; - document.getElementById('confirm-cta-form').style.display = 'block'; - - dataLayer.push({event: 'mktoLead',mktoFormId: form.getId()}); - return false; - }); - function getgacid() { - try { - var tracker = ga.getAll()[0]; - return tracker.get('clientId'); - } catch (e) { - return 'n/a'; - } - } - form.vals({ - 'gacid': getgacid() - }); -}); - -</script> -</form> -</div> -</div> - -</div> - -<h3 id="4-take-care-of-yourself">4. Take care of yourself</h3> - -<p>This is a simple tip that can make all the difference during networking and negotiations. It is a long week and to make the most of it you do need to practice some self-care. Hydrate regularly, eat meals at regular hours, and stick to your exercise routine. Bring your most comfortable shoes instead of your best looking ones. You will thank yourself when you are walking the strip for the 30th time. Actually, bring two pairs of comfortable shoes. Having the option to switch it up if one pair is rubbing you the wrong way can turn a frustrating experience into a non-issue.</p> - -<h3 id="5-pack-your-go-bag-the-night-before">5. Pack your go-bag the night before</h3> - -<p>Bring a full stock of business cards and external power banks. The days are long and networking strong. Make sure to charge all your devices overnight and don't forget anything you may need for a full day away from your hotel.</p> - -<h3 id="6-be-open-to-learning-and-new-experiences">6. Be open to learning and new experiences</h3> - -<p>This takes us back to the underlying question of why we gather at conferences such as re:Invent. Simply put, to learn from thought leaders and our peers. You are there to connect, share best practices, and expand your point of view. Hopefully, you'll leave with some new approaches, more solutions, and more questions to explore when you get home. Plan on taking notes of your interactions and the connections you make. At GitLab, we create issues for all actionable takeaways from the event. This is a great way for us to make sure the info doesn't get lost and gets disseminated to the rest of the team.</p> - -<h2 id="come-join-gitlab-at-aws-2018">Come join GitLab at AWS 2018</h2> - -<p>GitLab will be on site in Las Vegas with pleny of demos and tutorials you won't want to miss.</p> - -<h3 id="sign-up-to-book-a-time-with-gitlab">Sign up to book a time with GitLab</h3> - -<p>re:Invent can be an extrodinarily busy event with more people to meet and things to see than you'll have time for. To ensure you get time to talk with the GitLab experts on site, <a href="/events/aws-reinvent/">book some time in advance</a> to make sure you get a scheduled slot you can count on.</p> - -<h3 id="stop-by-booth-2608-on-the-expo-floor-in-the-venetian">Stop by booth 2608 on the expo floor in The Venetian</h3> - -<p>The team will be staffing our booth during all expo hours. We'll have some unique swag to hand out along with demos and experts to answer your questions.</p> - -<h3 id="come-see-our-ceo-show-off-gitlab--eks">Come see our CEO show off GitLab + EKS</h3> - -<p>On Tuesday, Nov. 27 at 12:10 p.m. in the Pilvi Theater, <a href="https://www.linkedin.com/in/sijbrandij/">Sid</a> and <a href="https://www.linkedin.com/in/pritianka/">Priyanka</a> will be showing how to <a href="https://www.portal.reinvent.awsevents.com/connect/search.ww#loadSearch-searchPhrase=%22GitLab%22&amp;searchType=session&amp;tc=0&amp;sortBy=abbreviationSort&amp;p=">reinvent your pipelines with GitLab, Kubernetes, and Amazon EKS</a> along with a live demo.</p> - -<h3 id="demo-set-up-your-pipelines-in-five-minutes">Demo: Set up your pipelines in five minutes</h3> - -<p>Join <a href="https://www.linkedin.com/in/jshlmbrt/">Joshua</a> at the GitLab booth (2608) on Wednesday, Nov. 28 at 1 p.m. for a live demo of GitLab <a href="/product/auto-devops/">Auto DevOps</a>.</p> - -<h3 id="gitlab-ci-101">GitLab CI 101</h3> - -<p>Join <a href="https://www.linkedin.com/in/reb33/">Reb</a> at the GitLab booth (2608) on Tuesday, Nov. 27 at 2 p.m. for a tutorial on getting up and going with <a href="/product/continuous-integration/">GitLab continuous integration</a>.</p> - -<p>See you there!</p> -<img src='https://about.gitlab.com/images/events/IMG_4756.jpeg' class='webfeedsFeaturedVisual' style='display: none;' /> - - diff --git a/internal/http/client/testdata/smallfile.xml b/internal/http/client/testdata/smallfile.xml deleted file mode 100644 index 780ef248..00000000 --- a/internal/http/client/testdata/smallfile.xml +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/internal/http/client/testdata/urdu.xml b/internal/http/client/testdata/urdu.xml deleted file mode 100644 index 726230de..00000000 --- a/internal/http/client/testdata/urdu.xml +++ /dev/null @@ -1,226 +0,0 @@ - - - <![CDATA[BBC News اردو - پاکستان کے لیے امریکی امداد کی بہار و خزاں]]> - - http://www.bbcurdu.com - - http://www.bbc.co.uk/urdu/images/gel/rss_logo.gif - BBC News اردو - پاکستان کے لیے امریکی امداد کی بہار و خزاں - http://www.bbcurdu.com - - RSS for Node - Wed, 24 Oct 2018 07:25:10 GMT - - - - 15 - - <![CDATA[امریکی عسکری امداد کی بندش کی وجوہات: انڈیا سے جنگ، جوہری پروگرام اور اب دہشت گردوں کی پشت پناہی]]> - - http://www.bbc.com/urdu/pakistan-42575603 - http://www.bbc.com/urdu/pakistan-42575603 - Fri, 05 Jan 2018 16:51:00 GMT - - - - <![CDATA[امریکہ کے ساتھ خفیہ معلومات کا تبادلہ اور فوجی تعاون معطل کر دیا: وزیر دفاع]]> - - http://www.bbc.com/urdu/pakistan-42645212 - http://www.bbc.com/urdu/pakistan-42645212 - Thu, 11 Jan 2018 13:20:55 GMT - - - - <![CDATA[پاکستان ان دہشت گرد گروہوں کے خلاف کارروائی کرے جن کے خلاف ہم چاہتے ہیں: امریکہ]]> - - http://www.bbc.com/urdu/world-42615276 - http://www.bbc.com/urdu/world-42615276 - Tue, 09 Jan 2018 02:59:43 GMT - - - - <![CDATA[پاکستانی وزیر دفاع کہتے ہیں کہ امریکہ کو ایک کامیابی ملی ہے، وہ بھی پاکستان کی مرہون منت]]> - - http://www.bbc.com/urdu/pakistan-42554318 - http://www.bbc.com/urdu/pakistan-42554318 - Wed, 03 Jan 2018 15:50:55 GMT - - - - <![CDATA[صدر ٹرمپ کے ٹویٹ کو سنجیدگی سے لیتے ہیں: وزیر دفاع]]> - - http://www.bbc.com/urdu/42547605 - http://www.bbc.com/urdu/42547605 - Tue, 02 Jan 2018 17:27:36 GMT - - - - <![CDATA[امریکی وزیرِ خارجہ کی پاکستان آمد]]> - - http://www.bbc.com/urdu/pakistan-41739055 - http://www.bbc.com/urdu/pakistan-41739055 - Tue, 24 Oct 2017 13:08:06 GMT - - - - <![CDATA[امریکہ اور پاکستان ایک دوسرے کا کیا بگاڑ سکتے ہیں؟]]> - - http://www.bbc.com/urdu/pakistan-42542988 - http://www.bbc.com/urdu/pakistan-42542988 - Tue, 02 Jan 2018 16:28:18 GMT - - - - <![CDATA[امریکہ اور پاکستان کے کشیدہ تعلقات میں اربوں ڈالر کی امداد پر بھی تنازع]]> - - http://www.bbc.com/urdu/pakistan-42532582 - http://www.bbc.com/urdu/pakistan-42532582 - Tue, 02 Jan 2018 10:28:02 GMT - - - - <![CDATA[’امریکہ انسداد دہشتگردی سیکھنے کے بجائے دشنام طرازی کر رہا ہے‘]]> - - http://www.bbc.com/urdu/pakistan-42548010 - http://www.bbc.com/urdu/pakistan-42548010 - Wed, 03 Jan 2018 05:04:13 GMT - - - - <![CDATA[پاکستان بھی ’مذہبی آزادیوں کی خلاف ورزیاں‘ کرنے والے ممالک میں شامل]]> - - http://www.bbc.com/urdu/world-42571559 - http://www.bbc.com/urdu/world-42571559 - Thu, 04 Jan 2018 17:12:58 GMT - - - - <![CDATA[پاکستان کی سکیورٹی امداد معطل: ’دہشت گردی کے خلاف عزم پر اثرانداز نہیں ہو سکتی‘]]> - - http://www.bbc.com/urdu/pakistan-42577314 - http://www.bbc.com/urdu/pakistan-42577314 - Fri, 05 Jan 2018 12:32:27 GMT - - - - <![CDATA[ڈونلڈ ٹرمپ: پاکستان نے ہمیں جھوٹ اور دھوکے کے سوا کچھ نہیں دیا]]> - - http://www.bbc.com/urdu/world-42534486 - http://www.bbc.com/urdu/world-42534486 - Mon, 01 Jan 2018 17:59:24 GMT - - - - <![CDATA[پاکستان: اتحادی ایک دوسرے کو تنبیہ جاری نہیں کیا کرتے]]> - - http://www.bbc.com/urdu/world-42451883 - http://www.bbc.com/urdu/world-42451883 - Fri, 22 Dec 2017 08:50:54 GMT - - - - <![CDATA[امریکہ: کون سے ممالک ہیں جن پر امداد بند کر دینے کی دھمکی کارگر ثابت نہیں ہوئی]]> - - http://www.bbc.com/urdu/world-42457273 - http://www.bbc.com/urdu/world-42457273 - Fri, 22 Dec 2017 15:29:44 GMT - - - - <![CDATA[پاکستان امریکہ تعلقات، بیان بدلتے ہیں لیکن عینک نہیں]]> - - http://www.bbc.com/urdu/pakistan-42225606 - http://www.bbc.com/urdu/pakistan-42225606 - Mon, 04 Dec 2017 13:36:14 GMT - - - - <![CDATA[پاکستان امریکہ تعلقات: ’باتیں دھمکی کی زبان سے نہیں صلح کی زبان سے طے ہوں گی‘]]> - - http://www.bbc.com/urdu/pakistan-41742387 - http://www.bbc.com/urdu/pakistan-41742387 - Wed, 25 Oct 2017 01:19:34 GMT - - - - <![CDATA[امریکہ کے ساتھ تعاون ختم کرنے پر غور کیا جائے: قرارداد]]> - - http://www.bbc.com/urdu/pakistan-41097529 - http://www.bbc.com/urdu/pakistan-41097529 - Wed, 30 Aug 2017 16:19:55 GMT - - - - <![CDATA[’پاکستان کو قربانی کا بکرا بناکر افغانستان میں امن نہیں لایا جاسکتا‘]]> - - http://www.bbc.com/urdu/pakistan-41038882 - http://www.bbc.com/urdu/pakistan-41038882 - Thu, 24 Aug 2017 14:35:50 GMT - - - - <![CDATA[امریکہ سے امداد کے نہیں اعتماد کے خواہاں ہیں: جنرل باجوہ]]> - - http://www.bbc.com/urdu/pakistan-41024731 - http://www.bbc.com/urdu/pakistan-41024731 - Wed, 23 Aug 2017 13:11:20 GMT - - - - <![CDATA[’پاکستان نے اپنے رویے کو تبدیل نہ کیا تو امریکی مراعات کھو سکتا ہے‘]]> - - http://www.bbc.com/urdu/pakistan-41019799 - http://www.bbc.com/urdu/pakistan-41019799 - Tue, 22 Aug 2017 23:06:07 GMT - - - - <![CDATA[امریکہ کا پاکستان کو ’نوٹس‘ کیا اور کتنا سنگین ہے؟]]> - - http://www.bbc.com/urdu/pakistan-42550677 - http://www.bbc.com/urdu/pakistan-42550677 - Wed, 03 Jan 2018 07:47:12 GMT - - - - <![CDATA[کمال ہے، اتنی دہشت؟]]> - - http://www.bbc.com/urdu/pakistan-42594820 - http://www.bbc.com/urdu/pakistan-42594820 - Sun, 07 Jan 2018 03:49:01 GMT - - - - <![CDATA[کیا امداد بند کرنے سے امریکہ کا مقصد پورا ہو گا؟]]> - - http://www.bbc.com/urdu/pakistan-42575493 - http://www.bbc.com/urdu/pakistan-42575493 - Fri, 05 Jan 2018 08:27:04 GMT - - - - <![CDATA[وہ تازیانے لگے ہوش سب ٹھکانے لگے]]> - - http://www.bbc.com/urdu/42596931 - http://www.bbc.com/urdu/42596931 - Sun, 07 Jan 2018 12:37:26 GMT - - - - <![CDATA[امریکہ پاکستان سے چاہتا کیا ہے؟]]> - - http://www.bbc.com/urdu/pakistan-41736761 - http://www.bbc.com/urdu/pakistan-41736761 - Tue, 24 Oct 2017 12:53:37 GMT - - - - <![CDATA[پاکستان امریکہ تعلقات میں ’ڈو مور‘ کا نیا ایڈیشن جو آج تک چل رہا]]> - - http://www.bbc.com/urdu/pakistan-42422392 - http://www.bbc.com/urdu/pakistan-42422392 - Wed, 20 Dec 2017 12:23:23 GMT - - - - \ No newline at end of file diff --git a/internal/http/client/testdata/windows_1251.html b/internal/http/client/testdata/windows_1251.html deleted file mode 100644 index 54823312..00000000 --- a/internal/http/client/testdata/windows_1251.html +++ /dev/null @@ -1,242 +0,0 @@ - - - - - - - - - - - - - - - ibash.org.ru - - - - - - -
-

ibash.org.ru

-
-
-
-
#17703 + ( 25103 )
-
xxx:
xxx: ?
yyy: PHP ,
yyy: - - -
-

-
-
#17705 + ( 20507 )
-
: 1 , ' .
: 1 , .
-

-
-
#17707 + ( 16743 )
-
xxx:
xxx: , . ,
xxx: ACPI
yyy: . ?
xxx: BNF. .
xxx: . ACPI " , "
xxx: , 60%
yyy: , . . ,
-

-
-
#17698 + ( 21515 )
-
( DRM, )
, , . , , , , , . , . , : . , , .
-

-
-
#17714 + ( 20101 )
-
: , - AMD nVidia - .
: .
-

-
-
#17715 + ( 19260 )
-
xxx:
xxx: ?
yyy: PHP ,
yyy: - - -
-

-
-
#17722 + ( 19419 )
-
xxx: : " 1 20 " (values within range 1 to 20 may be selected)
-

-
-
#17475 + ( 19325 )
-
<L29Ah> [[ clang++ == *g++ ]] && echo yay
<L29Ah> yay
<Minoru> *g++? ?
-

-
-
#17430 + ( 19644 )
-
xxx: c :)
yyy: , ,
-

-
-
#17419 + ( 22285 )
-
"OpenNET: QEMU/KVM Xen VGA"

xx: proxmox windows , .
yy: . .
-

-
-
#17414 + ( 19815 )
-
xxx: 600 ? >3 . . : , . , .
-

-
-
#17396 + ( 19330 )
-
Apple:
- ?
- , , ?
- ?
- ? !
- Emoji?
- ! !
-

-
-
#17394 + ( 18914 )
-
xxx: , , , , . , , , , - , , , ?

yyy: , , , , . , , .
-

-
-
#17386 + ( 18888 )
-
> Mail.Ru <...> Tarantool

SELECT * FROM cars;

+------+--------------------+
| id | name |
+------+--------------------+
| 1 | "Mazda CX-3" |
| 2 | "Audi Q1" |
| 3 | "BMW X1" |
| 4 | "Mazda CX-5" |
| 5 | "Cadillac XT5" |
| NULL | "@Mail.Ru" |
| NULL | "Guard@Mail.ru" |
| NULL | "@Mail.ru " |
| NULL | "Mail.ru Updater" |
+------+--------------------+
-

-
-
#17381 + ( 19273 )
-
, C++ .

. , ! . , .

. , , . .

, , . , . , , . , , .
-

-
-
#17375 + ( 34347 )
-
: serv29. .
: , .
: ?
: . . : .
-

-
-
#17371 + ( 626 )
-
- , : " ?" gentoo...
-

-
-
#17370 + ( 677 )
-
"":
zzz: " "???", " , IT, . , , -, "."

...,

xxx: Intel Core i5-5287U

yyy: , &#769; (. Filip&#233;ndula) (Rosaceae). 1013 [3], .
:
, , .



zzz:
-

-
-
#17369 + ( 1293 )
-
Grother: , . , Pasta silikonova termoprzewodzaca.
-

-
-
#17367 + ( 21 )
-
xxx: - - ?
xxx: : . , .
xxx: , . .
-

-
-
#17363 + ( -17 )
-
:
1. .
2. "" - .
:
.1 , .. .
.2 ?
-

-
-
#17359 + ( 41 )
-
ReactOS 0.4 :

Oxdeadbeef: x86_64?

Jedi-to-be: , .
-

-
-
#17358 + ( 9 )
-
<dsmirnov> ..... , ....
-

-
-
#17357 + ( 37 )
-
: . 20
: ,
: ,
-

-
-
#17356 + ( 17 )
-
xxx: - . -
-

-
-
#17354 + ( 13 )
-
Nick>
Nick> System information disabled due to load higher than 1.0
Nick> ,
Nick> 400, PCI- SATA
Nick>
-

-
-
#17353 + ( 6 )
-
. , RoHS ,
-

-
-
#17316 + ( 33 )
-
: , - . . 15 . . 180 : , ʔ.
Dmitry: )))))
:
Dmitry: ) , , .
-

-
-
#17314 + ( 3 )
-
Kikimorra: -. , . - :

It's a nice day!

Delete all children!

, >.<
-

-
-
#17312 + ( 15 )
-
xxx:
xxx:,
:
-

-
-
#17306 + ( 25 )
-
aaa: , .
bbb: , ? igloves, , .
ccc: . , .
ddd: ?
.
-

-
-
#17304 + ( -1 )
-
<> ...
<> ?
-

-
-
#17297 + ( -11 )
-
[15:15:56] r@ttler: .
[15:16:05] ZimM:
[15:17:30] r@ttler: : . . ,
[15:17:59] r@ttler: " , "
-

-
-
#17291 + ( 8 )
-
-:

- .

- , ....
[ 2 20 ]..., .

- ?

- : 15 , 15 , . . .
-

-
-
#17285 + ( 0 )
-
ZimM: ... with great power comes great responsibility
r@ttler: great chances to shoot your own leg
ZimM: . ,
r@ttler: work hard to shoot your own leg?
r@ttler:
r@ttler: -,
ZimM: , , , -, - ...
-

-
-
#17280 + ( 11 )
-
xxx: " " ( , ), , . , , , . , .
-

-
-
#17279 + ( 2 )
-
Val: B61-12. , , F-15E "" 20 .
Val: . ""?
: "!" -
-

-
-
#17276 + ( 25 )
-
dimgel: ( .) "Linux.Encoder.1 -. ..."
. : " ".
dimgel: , .
garik:
garik:
dimgel:
dimgel:
dimgel: ! Linux.Encoder.1 FreeBSD?!
-

-
-
#17272 + ( -5 )
-
xxx: , ,
yyy: , , .
xxx: ...
xxx: !!
xxx:
xxx: " "
xxx: " "
yyy: ", "
xxx: " "
yyy: ", "
xxx: , - !
-

-
-
#17259 + ( 17 )
-

[19:27:36] ZimM: . Europe, -
[19:28:01] r@ttler: . ?
[19:28:30] ZimM:
[19:28:49] r@ttler:
[19:29:01] r@ttler: - ?
[19:29:08] ZimM:
[19:29:14] r@ttler: 80 ?
-

-
-
#17236 + ( 13 )
-
xxx: " ",
-

-
-
#17235 + ( 12 )
-
xx: , google :)

yy: )

zz: ( , - ) ,

tt: , ?
-

-
-
#17233 + ( 4 )
-
" Linux- ":

xxx: - , . 3 .
-

-
-
#17230 + ( 24 )
-
:
Last Exile, ? . , . . . .
[...]
, , . , . , :

1)
2)
3)
4) ( )
5)
6) , , , . .
-

-
-
#17226 + ( 15 )
-
, , . , - . . . , -, , , 15 . . , , . , . , . . :

-- , , . . .

UML .
-

-
-
#17227 + ( 7 )
-
xxx: , ! ... , , , , , , , ...
-

-
-
#17223 + ( 12 )
-
xxx: 40 , , ...
yyy: D
yyy:
yyy: -
zzz: :)
zzz: 80
xxx: - )))
yyy:
yyy:
yyy: -
yyy: 2000, , 120
yyy:
yyy:
yyy: ,
yyy: , , 5
yyy: , ,
xxx: ,
yyy:
yyy: ,
-

-
-
#17224 + ( 23 )
-
, , , NDA?
NDA , ?
-

-
-
#17221 + ( 32 )
-
duzorg:
. . , , 15-20 . . 100 ...
100.
duzorg:
, . 4 . %)
Funkryer:

=)
1 4 ,
duzorg:
, )))
duzorg:
... ...
Funkryer:
, , !
-

-
-
#17220 + ( 12 )
-
xxx:
xxx: :(
xxx: ,
-

-
- : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55

-
-
- ibash.org.ru
- : imail@ibash.org.ru -
- -
- - - - diff --git a/internal/http/client/testdata/windows_1251.xml b/internal/http/client/testdata/windows_1251.xml deleted file mode 100644 index 474cc63a..00000000 --- a/internal/http/client/testdata/windows_1251.xml +++ /dev/null @@ -1,359 +0,0 @@ - - - - iBash.Org.Ru - http://ibash.org.ru/ - - ru - - http://ibash.org.ru/quote.php?id=17703 - http://ibash.org.ru/quote.php?id=17703 - #17703 - Wed, 21 Mar 2018 10:27:32 +0300 - xxx: ?
yyy: PHP ,
yyy: - - - ]]>
-
- - http://ibash.org.ru/quote.php?id=17705 - http://ibash.org.ru/quote.php?id=17705 - #17705 - Wed, 21 Mar 2018 10:27:22 +0300 - : 1 , .]]> - - - http://ibash.org.ru/quote.php?id=17707 - http://ibash.org.ru/quote.php?id=17707 - #17707 - Wed, 21 Mar 2018 10:26:48 +0300 - xxx: , . ,
xxx: ACPI
yyy: . ?
xxx: BNF. .
xxx: . ACPI " , "
xxx: , 60%
yyy: , . . , ]]>
-
- - http://ibash.org.ru/quote.php?id=17698 - http://ibash.org.ru/quote.php?id=17698 - #17698 - Thu, 15 Mar 2018 10:15:42 +0300 - , , . , , , , , . , . , : . , , .]]> - - - http://ibash.org.ru/quote.php?id=17714 - http://ibash.org.ru/quote.php?id=17714 - #17714 - Thu, 15 Mar 2018 10:14:00 +0300 - : .]]> - - - http://ibash.org.ru/quote.php?id=17715 - http://ibash.org.ru/quote.php?id=17715 - #17715 - Thu, 15 Mar 2018 10:13:35 +0300 - xxx: ?
yyy: PHP ,
yyy: - - - ]]>
-
- - http://ibash.org.ru/quote.php?id=17722 - http://ibash.org.ru/quote.php?id=17722 - #17722 - Thu, 15 Mar 2018 10:13:03 +0300 - - - - http://ibash.org.ru/quote.php?id=17475 - http://ibash.org.ru/quote.php?id=17475 - #17475 - Thu, 15 Mar 2018 10:05:41 +0300 - <L29Ah> yay
<Minoru> *g++? ?]]>
-
- - http://ibash.org.ru/quote.php?id=17430 - http://ibash.org.ru/quote.php?id=17430 - #17430 - Thu, 15 Mar 2018 09:59:50 +0300 - yyy: , , ]]> - - - http://ibash.org.ru/quote.php?id=17419 - http://ibash.org.ru/quote.php?id=17419 - #17419 - Thu, 15 Mar 2018 09:59:01 +0300 -
xx: proxmox windows , .
yy: . .]]>
-
- - http://ibash.org.ru/quote.php?id=17414 - http://ibash.org.ru/quote.php?id=17414 - #17414 - Thu, 15 Mar 2018 09:58:30 +0300 - - - - http://ibash.org.ru/quote.php?id=17396 - http://ibash.org.ru/quote.php?id=17396 - #17396 - Thu, 15 Mar 2018 09:56:44 +0300 - - ?
- , , ?
- ?
- ? !
- Emoji?
- ! !]]>
-
- - http://ibash.org.ru/quote.php?id=17394 - http://ibash.org.ru/quote.php?id=17394 - #17394 - Thu, 15 Mar 2018 09:56:28 +0300 -
yyy: , , , , . , , .]]>
-
- - http://ibash.org.ru/quote.php?id=17386 - http://ibash.org.ru/quote.php?id=17386 - #17386 - Thu, 15 Mar 2018 09:55:30 +0300 -
SELECT * FROM cars;

+------+--------------------+
| id | name |
+------+--------------------+
| 1 | "Mazda CX-3" |
| 2 | "Audi Q1" |
| 3 | "BMW X1" |
| 4 | "Mazda CX-5" |
| 5 | "Cadillac XT5" |
| NULL | "@Mail.Ru" |
| NULL | "Guard@Mail.ru" |
| NULL | "@Mail.ru " |
| NULL | "Mail.ru Updater" |
+------+--------------------+]]>
-
- - http://ibash.org.ru/quote.php?id=17381 - http://ibash.org.ru/quote.php?id=17381 - #17381 - Thu, 15 Mar 2018 09:54:50 +0300 -
. , ! . , .

. , , . .

, , . , . , , . , , .]]>
-
- - http://ibash.org.ru/quote.php?id=17375 - http://ibash.org.ru/quote.php?id=17375 - #17375 - Thu, 15 Mar 2018 09:53:54 +0300 - : , .
: ?
: . . : .]]>
-
- - http://ibash.org.ru/quote.php?id=17371 - http://ibash.org.ru/quote.php?id=17371 - #17371 - Thu, 15 Mar 2018 09:53:46 +0300 - - - - http://ibash.org.ru/quote.php?id=17370 - http://ibash.org.ru/quote.php?id=17370 - #17370 - Thu, 15 Mar 2018 09:53:28 +0300 - zzz: " "???", " , IT, . , , -, "."

...,

xxx: Intel Core i5-5287U

yyy: , &#769; (. Filip&#233;ndula) (Rosaceae). 1013 [3], .
:
, , .



zzz: ]]>
-
- - http://ibash.org.ru/quote.php?id=17369 - http://ibash.org.ru/quote.php?id=17369 - #17369 - Thu, 15 Mar 2018 09:52:38 +0300 - - - - http://ibash.org.ru/quote.php?id=17367 - http://ibash.org.ru/quote.php?id=17367 - #17367 - Thu, 15 Mar 2018 09:52:20 +0300 - xxx: : . , .
xxx: , . .]]>
-
- - http://ibash.org.ru/quote.php?id=17363 - http://ibash.org.ru/quote.php?id=17363 - #17363 - Thu, 15 Mar 2018 09:51:55 +0300 - 1. .
2. "" - .
:
.1 , .. .
.2 ?]]>
-
- - http://ibash.org.ru/quote.php?id=17359 - http://ibash.org.ru/quote.php?id=17359 - #17359 - Thu, 15 Mar 2018 09:51:10 +0300 -
Oxdeadbeef: x86_64?

Jedi-to-be: , .]]>
-
- - http://ibash.org.ru/quote.php?id=17358 - http://ibash.org.ru/quote.php?id=17358 - #17358 - Thu, 15 Mar 2018 09:51:04 +0300 - - - - http://ibash.org.ru/quote.php?id=17357 - http://ibash.org.ru/quote.php?id=17357 - #17357 - Thu, 15 Mar 2018 09:50:55 +0300 - : ,
: , ]]>
-
- - http://ibash.org.ru/quote.php?id=17356 - http://ibash.org.ru/quote.php?id=17356 - #17356 - Thu, 15 Mar 2018 09:50:51 +0300 - - - - http://ibash.org.ru/quote.php?id=17354 - http://ibash.org.ru/quote.php?id=17354 - #17354 - Thu, 15 Mar 2018 09:50:41 +0300 - Nick> System information disabled due to load higher than 1.0
Nick> ,
Nick> 400, PCI- SATA
Nick> ]]>
-
- - http://ibash.org.ru/quote.php?id=17353 - http://ibash.org.ru/quote.php?id=17353 - #17353 - Thu, 15 Mar 2018 09:49:52 +0300 - - - - http://ibash.org.ru/quote.php?id=17316 - http://ibash.org.ru/quote.php?id=17316 - #17316 - Thu, 15 Mar 2018 09:47:42 +0300 - Dmitry: )))))
:
Dmitry: ) , , .]]>
-
- - http://ibash.org.ru/quote.php?id=17314 - http://ibash.org.ru/quote.php?id=17314 - #17314 - Thu, 15 Mar 2018 09:46:52 +0300 -
It's a nice day!

Delete all children!

, >.<]]>
-
- - http://ibash.org.ru/quote.php?id=17312 - http://ibash.org.ru/quote.php?id=17312 - #17312 - Thu, 15 Mar 2018 09:46:33 +0300 - xxx:,
: ]]>
-
- - http://ibash.org.ru/quote.php?id=17306 - http://ibash.org.ru/quote.php?id=17306 - #17306 - Thu, 15 Mar 2018 09:46:21 +0300 - bbb: , ? igloves, , .
ccc: . , .
ddd: ?
.]]>
-
- - http://ibash.org.ru/quote.php?id=17304 - http://ibash.org.ru/quote.php?id=17304 - #17304 - Thu, 15 Mar 2018 09:45:51 +0300 - <> ?]]> - - - http://ibash.org.ru/quote.php?id=17297 - http://ibash.org.ru/quote.php?id=17297 - #17297 - Thu, 15 Mar 2018 09:44:04 +0300 - [15:16:05] ZimM:
[15:17:30] r@ttler: : . . ,
[15:17:59] r@ttler: " , "]]>
-
- - http://ibash.org.ru/quote.php?id=17291 - http://ibash.org.ru/quote.php?id=17291 - #17291 - Thu, 15 Mar 2018 09:42:11 +0300 -
- .

- , ....
[ 2 20 ]..., .

- ?

- : 15 , 15 , . . .]]>
-
- - http://ibash.org.ru/quote.php?id=17285 - http://ibash.org.ru/quote.php?id=17285 - #17285 - Thu, 15 Mar 2018 09:40:57 +0300 - r@ttler: great chances to shoot your own leg
ZimM: . ,
r@ttler: work hard to shoot your own leg?
r@ttler:
r@ttler: -,
ZimM: , , , -, - ...]]>
-
- - http://ibash.org.ru/quote.php?id=17280 - http://ibash.org.ru/quote.php?id=17280 - #17280 - Thu, 15 Mar 2018 09:37:53 +0300 - - - - http://ibash.org.ru/quote.php?id=17279 - http://ibash.org.ru/quote.php?id=17279 - #17279 - Thu, 15 Mar 2018 09:37:50 +0300 - Val: . ""?
: "!" - ]]>
-
- - http://ibash.org.ru/quote.php?id=17276 - http://ibash.org.ru/quote.php?id=17276 - #17276 - Thu, 15 Mar 2018 09:29:42 +0300 - . : " ".
dimgel: , .
garik:
garik:
dimgel:
dimgel:
dimgel: ! Linux.Encoder.1 FreeBSD?!]]>
-
- - http://ibash.org.ru/quote.php?id=17272 - http://ibash.org.ru/quote.php?id=17272 - #17272 - Thu, 15 Mar 2018 09:28:44 +0300 - yyy: , , .
xxx: ...
xxx: !!
xxx:
xxx: " "
xxx: " "
yyy: ", "
xxx: " "
yyy: ", "
xxx: , - !]]>
-
- - http://ibash.org.ru/quote.php?id=17259 - http://ibash.org.ru/quote.php?id=17259 - #17259 - Thu, 15 Mar 2018 09:25:43 +0300 - [19:27:36] ZimM: . Europe, -
[19:28:01] r@ttler: . ?
[19:28:30] ZimM:
[19:28:49] r@ttler:
[19:29:01] r@ttler: - ?
[19:29:08] ZimM:
[19:29:14] r@ttler: 80 ?]]>
-
- - http://ibash.org.ru/quote.php?id=17236 - http://ibash.org.ru/quote.php?id=17236 - #17236 - Thu, 15 Mar 2018 09:23:51 +0300 - - - - http://ibash.org.ru/quote.php?id=17235 - http://ibash.org.ru/quote.php?id=17235 - #17235 - Thu, 15 Mar 2018 09:23:49 +0300 -
yy: )

zz: ( , - ) ,

tt: , ?]]>
-
- - http://ibash.org.ru/quote.php?id=17233 - http://ibash.org.ru/quote.php?id=17233 - #17233 - Thu, 15 Mar 2018 09:23:33 +0300 -
xxx: - , . 3 .]]>
-
- - http://ibash.org.ru/quote.php?id=17230 - http://ibash.org.ru/quote.php?id=17230 - #17230 - Thu, 15 Mar 2018 09:22:21 +0300 - Last Exile, ? . , . . . .
[...]
, , . , . , :

1)
2)
3)
4) ( )
5)
6) , , , . .]]>
-
- - http://ibash.org.ru/quote.php?id=17226 - http://ibash.org.ru/quote.php?id=17226 - #17226 - Thu, 15 Mar 2018 09:20:48 +0300 -
-- , , . . .

UML .]]>
-
- - http://ibash.org.ru/quote.php?id=17227 - http://ibash.org.ru/quote.php?id=17227 - #17227 - Thu, 15 Mar 2018 09:20:46 +0300 - - - - http://ibash.org.ru/quote.php?id=17223 - http://ibash.org.ru/quote.php?id=17223 - #17223 - Thu, 15 Mar 2018 09:19:38 +0300 - yyy: D
yyy:
yyy: -
zzz: :)
zzz: 80
xxx: - )))
yyy:
yyy:
yyy: -
yyy: 2000, , 120
yyy:
yyy:
yyy: ,
yyy: , , 5
yyy: , ,
xxx: ,
yyy:
yyy: , ]]>
-
- - http://ibash.org.ru/quote.php?id=17224 - http://ibash.org.ru/quote.php?id=17224 - #17224 - Thu, 15 Mar 2018 09:19:36 +0300 - NDA , ?]]> - - - http://ibash.org.ru/quote.php?id=17221 - http://ibash.org.ru/quote.php?id=17221 - #17221 - Thu, 15 Mar 2018 09:17:22 +0300 - . . , , 15-20 . . 100 ...
100.
duzorg:
, . 4 . %)
Funkryer:

=)
1 4 ,
duzorg:
, )))
duzorg:
... ...
Funkryer:
, , !]]>
-
- - http://ibash.org.ru/quote.php?id=17220 - http://ibash.org.ru/quote.php?id=17220 - #17220 - Thu, 15 Mar 2018 09:16:48 +0300 - xxx: :(
xxx: , ]]>
-
-
-
diff --git a/internal/integration/rssbridge/rssbridge.go b/internal/integration/rssbridge/rssbridge.go index 117b9c84..672d36b6 100644 --- a/internal/integration/rssbridge/rssbridge.go +++ b/internal/integration/rssbridge/rssbridge.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + package rssbridge // import "miniflux.app/integration/rssbridge" import ( @@ -29,14 +32,14 @@ func DetectBridges(rssbridgeURL, websiteURL string) (bridgeResponse []Bridge, er response, err := http.Get(u.String()) if err != nil { - return nil, err + return nil, fmt.Errorf("RSS-Bridge: unable to excute request: %w", err) } defer response.Body.Close() if response.StatusCode == http.StatusNotFound { return } if response.StatusCode > 400 { - return nil, fmt.Errorf("RSS-Bridge: server failure (%d)", response.StatusCode) + return nil, fmt.Errorf("RSS-Bridge: unexpected status code %d", response.StatusCode) } if err := json.NewDecoder(response.Body).Decode(&bridgeResponse); err != nil { return nil, fmt.Errorf("RSS-Bridge: unable to decode bridge response: %w", err) diff --git a/internal/locale/error.go b/internal/locale/error.go new file mode 100644 index 00000000..eba43227 --- /dev/null +++ b/internal/locale/error.go @@ -0,0 +1,52 @@ +// SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +package locale // import "miniflux.app/v2/internal/locale" + +import "errors" + +type LocalizedErrorWrapper struct { + originalErr error + translationKey string + translationArgs []any +} + +func NewLocalizedErrorWrapper(originalErr error, translationKey string, translationArgs ...any) *LocalizedErrorWrapper { + return &LocalizedErrorWrapper{ + originalErr: originalErr, + translationKey: translationKey, + translationArgs: translationArgs, + } +} + +func (l *LocalizedErrorWrapper) Error() error { + return l.originalErr +} + +func (l *LocalizedErrorWrapper) Translate(language string) string { + if l.translationKey == "" { + return l.originalErr.Error() + } + return NewPrinter(language).Printf(l.translationKey, l.translationArgs...) +} + +type LocalizedError struct { + translationKey string + translationArgs []any +} + +func NewLocalizedError(translationKey string, translationArgs ...any) *LocalizedError { + return &LocalizedError{translationKey: translationKey, translationArgs: translationArgs} +} + +func (v *LocalizedError) String() string { + return NewPrinter("en_US").Printf(v.translationKey, v.translationArgs...) +} + +func (v *LocalizedError) Error() error { + return errors.New(v.String()) +} + +func (v *LocalizedError) Translate(language string) string { + return NewPrinter(language).Printf(v.translationKey, v.translationArgs...) +} diff --git a/internal/locale/translations/de_DE.json b/internal/locale/translations/de_DE.json index abcddc1b..c8a22594 100644 --- a/internal/locale/translations/de_DE.json +++ b/internal/locale/translations/de_DE.json @@ -436,25 +436,29 @@ "vor %d Jahr", "vor %d Jahren" ], - "This feed already exists (%s)": "Diese Abonnement existiert bereits (%s)", - "Unable to fetch feed (Status Code = %d)": "Abonnement konnte nicht abgerufen werden (code=%d)", - "Unable to open this link: %v": "Dieser Link konnte nicht geöffnet werden: %v", - "Unable to analyze this page: %v": "Diese Seite konnte nicht analysiert werden: %v", - "Unable to execute request: %v": "Diese Anfrage konnte nicht ausgeführt werden: %v", - "Unable to parse OPML file: %q": "OPML Datei konnte nicht gelesen werden: %q", - "Unable to parse RSS feed: %q": "RSS Abonnement konnte nicht gelesen werden: %q", - "Unable to parse Atom feed: %q": "Atom Abonnement konnte nicht gelesen werden: %q", - "Unable to parse JSON feed: %q": "JSON Abonnement konnte nicht gelesen werden: %q", - "Unable to parse RDF feed: %q": "RDF Abonnement konnte nicht gelesen werden: %q", - "Unable to normalize encoding: %q": "Zeichenkodierung konnte nicht normalisiert werden: %q", - "This feed is empty": "Dieses Abonnement ist leer", - "This web page is empty": "Diese Webseite ist leer", - "Invalid SSL certificate (original error: %q)": "Ungültiges SSL-Zertifikat (ursprünglicher Fehler: %q)", - "This website is unreachable (original error: %q)": "Diese Webseite ist nicht erreichbar (ursprünglicher Fehler: %q)", - "Website unreachable, the request timed out after %d seconds": "Webseite nicht erreichbar, die Anfrage endete nach %d Sekunden", - "You are not authorized to access this resource (invalid username/password)": "Sie sind nicht berechtigt, auf diese Ressource zuzugreifen (Benutzername/Passwort ungültig)", - "Unable to fetch this resource (Status Code = %d)": "Ressource konnte nicht abgerufen werden (code=%d)", - "Resource not found (404), this feed doesn't exist anymore, check the feed URL": "Ressource nicht gefunden (404), dieses Abonnement existiert nicht mehr, überprüfen Sie die Abonnement-URL", "alert.too_many_feeds_refresh": "You have triggered too many feed refreshes. Please wait 30 minutes before trying again.", - "alert.background_feed_refresh": "All feeds are being refreshed in the background. You can continue to use Miniflux while this process is running." + "alert.background_feed_refresh": "All feeds are being refreshed in the background. You can continue to use Miniflux while this process is running.", + "error.http_response_too_large": "The HTTP response is too large. You could increase the HTTP response size limit in the global settings (requires a server restart).", + "error.http_body_read": "Unable to read the HTTP body.", + "error.http_empty_response_body": "The HTTP response body is empty.", + "error.http_empty_response": "The HTTP response is empty. Perhaps, this website is using a bot protection mechanism?", + "error.tls_error": "TLS error: %v. You could disable TLS verification in the feed settings if you would like.", + "error.network_operation": "Miniflux is not able to reach this website due to a network error: %v.", + "error.network_timeout": "This website is too slow and the request timed out: %v", + "error.http_client_error": "HTTP client error: %v.", + "error.http_not_authorized": "Access to this website is not authorized. It could be a bad username or password.", + "error.http_too_many_requests": "Miniflux generated too many requests to this website. Please, try again later or change the application configuration.", + "error.http_forbidden": "Access to this website is forbidden. Perhaps, this website has a bot protection mechanism?", + "error.http_resource_not_found": "The requested resource is not found. Please, verify the URL.", + "error.http_internal_server_error": "The website is not available at the moment due to a server error. The problem is not on Miniflux side. Please, try again later.", + "error.http_bad_gateway": "The website is not available at the moment due to a bad gateway error. The problem is not on Miniflux side. Please, try again later.", + "error.http_service_unavailable": "The website is not available at the moment due to an internal server error. The problem is not on Miniflux side. Please, try again later.", + "error.http_gateway_timeout": "The website is not available at the moment due to a gateway timeout error. The problem is not on Miniflux side. Please, try again later.", + "error.http_unexpected_status_code": "The website is not available at the moment due to an unexpected HTTP status code: %d. The problem is not on Miniflux side. Please, try again later.", + "error.database_error": "Database error: %v.", + "error.category_not_found": "This category does not exist or does not belong to this user.", + "error.duplicated_feed": "This feed already exists.", + "error.unable_to_parse_feed": "Unable to parse this feed: %v.", + "error.feed_not_found": "This feed does not exist or does not belong to this user.", + "error.unable_to_detect_rssbridge": "Unable to detect feed using RSS-Bridge: %v." } diff --git a/internal/locale/translations/el_EL.json b/internal/locale/translations/el_EL.json index 6a4d87e4..1da5910c 100644 --- a/internal/locale/translations/el_EL.json +++ b/internal/locale/translations/el_EL.json @@ -437,5 +437,28 @@ "πριν %d έτη" ], "alert.too_many_feeds_refresh": "You have triggered too many feed refreshes. Please wait 30 minutes before trying again.", - "alert.background_feed_refresh": "All feeds are being refreshed in the background. You can continue to use Miniflux while this process is running." + "alert.background_feed_refresh": "All feeds are being refreshed in the background. You can continue to use Miniflux while this process is running.", + "error.http_response_too_large": "The HTTP response is too large. You could increase the HTTP response size limit in the global settings (requires a server restart).", + "error.http_body_read": "Unable to read the HTTP body.", + "error.http_empty_response_body": "The HTTP response body is empty.", + "error.http_empty_response": "The HTTP response is empty. Perhaps, this website is using a bot protection mechanism?", + "error.tls_error": "TLS error: %v. You could disable TLS verification in the feed settings if you would like.", + "error.network_operation": "Miniflux is not able to reach this website due to a network error: %v.", + "error.network_timeout": "This website is too slow and the request timed out: %v", + "error.http_client_error": "HTTP client error: %v.", + "error.http_not_authorized": "Access to this website is not authorized. It could be a bad username or password.", + "error.http_too_many_requests": "Miniflux generated too many requests to this website. Please, try again later or change the application configuration.", + "error.http_forbidden": "Access to this website is forbidden. Perhaps, this website has a bot protection mechanism?", + "error.http_resource_not_found": "The requested resource is not found. Please, verify the URL.", + "error.http_internal_server_error": "The website is not available at the moment due to a server error. The problem is not on Miniflux side. Please, try again later.", + "error.http_bad_gateway": "The website is not available at the moment due to a bad gateway error. The problem is not on Miniflux side. Please, try again later.", + "error.http_service_unavailable": "The website is not available at the moment due to an internal server error. The problem is not on Miniflux side. Please, try again later.", + "error.http_gateway_timeout": "The website is not available at the moment due to a gateway timeout error. The problem is not on Miniflux side. Please, try again later.", + "error.http_unexpected_status_code": "The website is not available at the moment due to an unexpected HTTP status code: %d. The problem is not on Miniflux side. Please, try again later.", + "error.database_error": "Database error: %v.", + "error.category_not_found": "This category does not exist or does not belong to this user.", + "error.duplicated_feed": "This feed already exists.", + "error.unable_to_parse_feed": "Unable to parse this feed: %v.", + "error.feed_not_found": "This feed does not exist or does not belong to this user.", + "error.unable_to_detect_rssbridge": "Unable to detect feed using RSS-Bridge: %v." } diff --git a/internal/locale/translations/en_US.json b/internal/locale/translations/en_US.json index e553b5b1..fbabb427 100644 --- a/internal/locale/translations/en_US.json +++ b/internal/locale/translations/en_US.json @@ -437,5 +437,28 @@ "%d years ago" ], "alert.too_many_feeds_refresh": "You have triggered too many feed refreshes. Please wait 30 minutes before trying again.", - "alert.background_feed_refresh": "All feeds are being refreshed in the background. You can continue to use Miniflux while this process is running." + "alert.background_feed_refresh": "All feeds are being refreshed in the background. You can continue to use Miniflux while this process is running.", + "error.http_response_too_large": "The HTTP response is too large. You could increase the HTTP response size limit in the global settings (requires a server restart).", + "error.http_body_read": "Unable to read the HTTP body.", + "error.http_empty_response_body": "The HTTP response body is empty.", + "error.http_empty_response": "The HTTP response is empty. Perhaps, this website is using a bot protection mechanism?", + "error.tls_error": "TLS error: %v. You could disable TLS verification in the feed settings if you would like.", + "error.network_operation": "Miniflux is not able to reach this website due to a network error: %v.", + "error.network_timeout": "This website is too slow and the request timed out: %v", + "error.http_client_error": "HTTP client error: %v.", + "error.http_not_authorized": "Access to this website is not authorized. It could be a bad username or password.", + "error.http_too_many_requests": "Miniflux generated too many requests to this website. Please, try again later or change the application configuration.", + "error.http_forbidden": "Access to this website is forbidden. Perhaps, this website has a bot protection mechanism?", + "error.http_resource_not_found": "The requested resource is not found. Please, verify the URL.", + "error.http_internal_server_error": "The website is not available at the moment due to a server error. The problem is not on Miniflux side. Please, try again later.", + "error.http_bad_gateway": "The website is not available at the moment due to a bad gateway error. The problem is not on Miniflux side. Please, try again later.", + "error.http_service_unavailable": "The website is not available at the moment due to an internal server error. The problem is not on Miniflux side. Please, try again later.", + "error.http_gateway_timeout": "The website is not available at the moment due to a gateway timeout error. The problem is not on Miniflux side. Please, try again later.", + "error.http_unexpected_status_code": "The website is not available at the moment due to an unexpected HTTP status code: %d. The problem is not on Miniflux side. Please, try again later.", + "error.database_error": "Database error: %v.", + "error.category_not_found": "This category does not exist or does not belong to this user.", + "error.duplicated_feed": "This feed already exists.", + "error.unable_to_parse_feed": "Unable to parse this feed: %v.", + "error.feed_not_found": "This feed does not exist or does not belong to this user.", + "error.unable_to_detect_rssbridge": "Unable to detect feed using RSS-Bridge: %v." } diff --git a/internal/locale/translations/es_ES.json b/internal/locale/translations/es_ES.json index 5db848b4..89df8d69 100644 --- a/internal/locale/translations/es_ES.json +++ b/internal/locale/translations/es_ES.json @@ -437,5 +437,28 @@ "hace %d años" ], "alert.too_many_feeds_refresh": "You have triggered too many feed refreshes. Please wait 30 minutes before trying again.", - "alert.background_feed_refresh": "All feeds are being refreshed in the background. You can continue to use Miniflux while this process is running." + "alert.background_feed_refresh": "All feeds are being refreshed in the background. You can continue to use Miniflux while this process is running.", + "error.http_response_too_large": "The HTTP response is too large. You could increase the HTTP response size limit in the global settings (requires a server restart).", + "error.http_body_read": "Unable to read the HTTP body.", + "error.http_empty_response_body": "The HTTP response body is empty.", + "error.http_empty_response": "The HTTP response is empty. Perhaps, this website is using a bot protection mechanism?", + "error.tls_error": "TLS error: %v. You could disable TLS verification in the feed settings if you would like.", + "error.network_operation": "Miniflux is not able to reach this website due to a network error: %v.", + "error.network_timeout": "This website is too slow and the request timed out: %v", + "error.http_client_error": "HTTP client error: %v.", + "error.http_not_authorized": "Access to this website is not authorized. It could be a bad username or password.", + "error.http_too_many_requests": "Miniflux generated too many requests to this website. Please, try again later or change the application configuration.", + "error.http_forbidden": "Access to this website is forbidden. Perhaps, this website has a bot protection mechanism?", + "error.http_resource_not_found": "The requested resource is not found. Please, verify the URL.", + "error.http_internal_server_error": "The website is not available at the moment due to a server error. The problem is not on Miniflux side. Please, try again later.", + "error.http_bad_gateway": "The website is not available at the moment due to a bad gateway error. The problem is not on Miniflux side. Please, try again later.", + "error.http_service_unavailable": "The website is not available at the moment due to an internal server error. The problem is not on Miniflux side. Please, try again later.", + "error.http_gateway_timeout": "The website is not available at the moment due to a gateway timeout error. The problem is not on Miniflux side. Please, try again later.", + "error.http_unexpected_status_code": "The website is not available at the moment due to an unexpected HTTP status code: %d. The problem is not on Miniflux side. Please, try again later.", + "error.database_error": "Database error: %v.", + "error.category_not_found": "This category does not exist or does not belong to this user.", + "error.duplicated_feed": "This feed already exists.", + "error.unable_to_parse_feed": "Unable to parse this feed: %v.", + "error.feed_not_found": "This feed does not exist or does not belong to this user.", + "error.unable_to_detect_rssbridge": "Unable to detect feed using RSS-Bridge: %v." } diff --git a/internal/locale/translations/fi_FI.json b/internal/locale/translations/fi_FI.json index a83a43c9..17ef7657 100644 --- a/internal/locale/translations/fi_FI.json +++ b/internal/locale/translations/fi_FI.json @@ -437,5 +437,28 @@ "%d vuotta sitten" ], "alert.too_many_feeds_refresh": "You have triggered too many feed refreshes. Please wait 30 minutes before trying again.", - "alert.background_feed_refresh": "All feeds are being refreshed in the background. You can continue to use Miniflux while this process is running." + "alert.background_feed_refresh": "All feeds are being refreshed in the background. You can continue to use Miniflux while this process is running.", + "error.http_response_too_large": "The HTTP response is too large. You could increase the HTTP response size limit in the global settings (requires a server restart).", + "error.http_body_read": "Unable to read the HTTP body.", + "error.http_empty_response_body": "The HTTP response body is empty.", + "error.http_empty_response": "The HTTP response is empty. Perhaps, this website is using a bot protection mechanism?", + "error.tls_error": "TLS error: %v. You could disable TLS verification in the feed settings if you would like.", + "error.network_operation": "Miniflux is not able to reach this website due to a network error: %v.", + "error.network_timeout": "This website is too slow and the request timed out: %v", + "error.http_client_error": "HTTP client error: %v.", + "error.http_not_authorized": "Access to this website is not authorized. It could be a bad username or password.", + "error.http_too_many_requests": "Miniflux generated too many requests to this website. Please, try again later or change the application configuration.", + "error.http_forbidden": "Access to this website is forbidden. Perhaps, this website has a bot protection mechanism?", + "error.http_resource_not_found": "The requested resource is not found. Please, verify the URL.", + "error.http_internal_server_error": "The website is not available at the moment due to a server error. The problem is not on Miniflux side. Please, try again later.", + "error.http_bad_gateway": "The website is not available at the moment due to a bad gateway error. The problem is not on Miniflux side. Please, try again later.", + "error.http_service_unavailable": "The website is not available at the moment due to an internal server error. The problem is not on Miniflux side. Please, try again later.", + "error.http_gateway_timeout": "The website is not available at the moment due to a gateway timeout error. The problem is not on Miniflux side. Please, try again later.", + "error.http_unexpected_status_code": "The website is not available at the moment due to an unexpected HTTP status code: %d. The problem is not on Miniflux side. Please, try again later.", + "error.database_error": "Database error: %v.", + "error.category_not_found": "This category does not exist or does not belong to this user.", + "error.duplicated_feed": "This feed already exists.", + "error.unable_to_parse_feed": "Unable to parse this feed: %v.", + "error.feed_not_found": "This feed does not exist or does not belong to this user.", + "error.unable_to_detect_rssbridge": "Unable to detect feed using RSS-Bridge: %v." } diff --git a/internal/locale/translations/fr_FR.json b/internal/locale/translations/fr_FR.json index a27de069..aeaf3c6a 100644 --- a/internal/locale/translations/fr_FR.json +++ b/internal/locale/translations/fr_FR.json @@ -436,25 +436,29 @@ "il y a %d an", "il y a %d ans" ], - "This feed already exists (%s)": "Cet abonnement existe déjà (%s)", - "Unable to fetch feed (Status Code = %d)": "Impossible de récupérer cet abonnement (code=%d)", - "Unable to open this link: %v": "Impossible d'ouvrir ce lien : %v", - "Unable to analyze this page: %v": "Impossible d'analyzer cette page : %v", - "Unable to execute request: %v": "Impossible d'exécuter cette requête: %v", - "Unable to parse OPML file: %q": "Impossible de lire ce fichier OPML : %q", - "Unable to parse RSS feed: %q": "Impossible de lire ce flux RSS : %q", - "Unable to parse Atom feed: %q": "Impossible de lire ce flux Atom : %q", - "Unable to parse JSON feed: %q": "Impossible de lire ce flux JSON : %q", - "Unable to parse RDF feed: %q": "Impossible de lire ce flux RDF : %q", - "Unable to normalize encoding: %q": "Impossible de normaliser l'encodage : %q", - "This feed is empty": "Cet abonnement est vide", - "This web page is empty": "Cette page web est vide", - "Invalid SSL certificate (original error: %q)": "Certificat SSL invalide (erreur originale : %q)", - "This website is unreachable (original error: %q)": "Ce site web n'est pas joignable (erreur originale : %q)", - "Website unreachable, the request timed out after %d seconds": "Site web injoignable, la requête à échouée après %d secondes", - "You are not authorized to access this resource (invalid username/password)": "Vous n'êtes pas autorisé à accéder à cette ressource (nom d'utilisateur / mot de passe incorrect)", - "Unable to fetch this resource (Status Code = %d)": "Impossible de récupérer cette ressource (code=%d)", - "Resource not found (404), this feed doesn't exist anymore, check the feed URL": "Page introuvable (404), cet abonnement n'existe plus, vérifiez l'adresse du flux", "alert.too_many_feeds_refresh": "Vous avez déclenché trop d'actualisations de flux. Veuillez attendre 30 minutes avant de réessayer.", - "alert.background_feed_refresh": "Les abonnements sont en cours d'actualisation en arrière-plan. Vous pouvez continuer à naviguer dans l'application." + "alert.background_feed_refresh": "Les abonnements sont en cours d'actualisation en arrière-plan. Vous pouvez continuer à naviguer dans l'application.", + "error.http_response_too_large": "La réponse HTTP est trop volumineuse. Vous pouvez augmenter la limite de taille de réponse HTTP dans les paramètres de l'application (redémarrage de l'application nécessaire).", + "error.http_body_read": "Impossible de lire le corps de la réponse HTTP.", + "error.http_empty_response_body": "Le corps de la réponse HTTP est vide.", + "error.http_empty_response": "La réponse HTTP est vide. Peut-être que ce site web bloque Miniflux avec une protection anti-bot ?", + "error.tls_error": "Erreur TLS : %v. Vous pouvez désactiver la vérification TLS dans les paramètres de l'abonnement.", + "error.network_operation": "Miniflux n'est pas en mesure de se connecter à ce site web à cause d'un problème réseau : %v.", + "error.network_timeout": "Ce site web est trop lent à répondre : %v.", + "error.http_client_error": "Erreur du client HTTP : %v.", + "error.http_not_authorized": "Accès non autorisé à ce site web. Veuillez vérifier les identifiants de cet abonnement.", + "error.http_too_many_requests": "Miniflux a généré trop de requêtes vers ce site web. Veuillez réessayer plus tard ou changez la configuration de l'application.", + "error.http_forbidden": "Accès interdit à ce site web. Il se peut que ce site web bloque Miniflux avec une protection anti-bot.", + "error.http_resource_not_found": "La resource demandée n'existe pas sur ce site web. Veuillez vérifier l'URL.", + "error.http_internal_server_error": "Le site web n'est pas disponible pour le moment à cause d'une erreur interne au serveur. Le problème ne vient pas de Miniflux. Veuillez réessayer plus tard.", + "error.http_bad_gateway": "Le site web n'est pas disponible pour le moment à cause d'une erreur de passerelle réseau. Le problème ne vient pas de Miniflux. Veuillez réessayer plus tard.", + "error.http_service_unavailable": "Le site web n'est pas disponible pour le moment. Le problème ne vient pas de Miniflux. Veuillez réessayer plus tard.", + "error.http_gateway_timeout": "Le site web n'est pas disponible pour le moment à cause d'un délai d'attente dépassé. Le problème ne vient pas de Miniflux. Veuillez réessayer plus tard.", + "error.http_unexpected_status_code": "Le site web a répondu avec un code HTTP inattendu : %d. Le problème ne vient pas de Miniflux. Veuillez réessayer plus tard.", + "error.database_error": "Erreur de la base de données : %v.", + "error.category_not_found": "Cette catégorie n'existe pas ou n'appartient pas à cet utilisateur.", + "error.duplicated_feed": "Ce flux existe déjà.", + "error.unable_to_parse_feed": "Impossible d'analyser ce flux : %v.", + "error.feed_not_found": "Impossible de trouver ce flux.", + "error.unable_to_detect_rssbridge": "Impossible de détecter un flux RSS en utilisant RSS-Bridge: %v." } diff --git a/internal/locale/translations/hi_IN.json b/internal/locale/translations/hi_IN.json index 278d78c6..a0efc399 100644 --- a/internal/locale/translations/hi_IN.json +++ b/internal/locale/translations/hi_IN.json @@ -437,5 +437,28 @@ "%d वर्षों पहले" ], "alert.too_many_feeds_refresh": "You have triggered too many feed refreshes. Please wait 30 minutes before trying again.", - "alert.background_feed_refresh": "All feeds are being refreshed in the background. You can continue to use Miniflux while this process is running." + "alert.background_feed_refresh": "All feeds are being refreshed in the background. You can continue to use Miniflux while this process is running.", + "error.http_response_too_large": "The HTTP response is too large. You could increase the HTTP response size limit in the global settings (requires a server restart).", + "error.http_body_read": "Unable to read the HTTP body.", + "error.http_empty_response_body": "The HTTP response body is empty.", + "error.http_empty_response": "The HTTP response is empty. Perhaps, this website is using a bot protection mechanism?", + "error.tls_error": "TLS error: %v. You could disable TLS verification in the feed settings if you would like.", + "error.network_operation": "Miniflux is not able to reach this website due to a network error: %v.", + "error.network_timeout": "This website is too slow and the request timed out: %v", + "error.http_client_error": "HTTP client error: %v.", + "error.http_not_authorized": "Access to this website is not authorized. It could be a bad username or password.", + "error.http_too_many_requests": "Miniflux generated too many requests to this website. Please, try again later or change the application configuration.", + "error.http_forbidden": "Access to this website is forbidden. Perhaps, this website has a bot protection mechanism?", + "error.http_resource_not_found": "The requested resource is not found. Please, verify the URL.", + "error.http_internal_server_error": "The website is not available at the moment due to a server error. The problem is not on Miniflux side. Please, try again later.", + "error.http_bad_gateway": "The website is not available at the moment due to a bad gateway error. The problem is not on Miniflux side. Please, try again later.", + "error.http_service_unavailable": "The website is not available at the moment due to an internal server error. The problem is not on Miniflux side. Please, try again later.", + "error.http_gateway_timeout": "The website is not available at the moment due to a gateway timeout error. The problem is not on Miniflux side. Please, try again later.", + "error.http_unexpected_status_code": "The website is not available at the moment due to an unexpected HTTP status code: %d. The problem is not on Miniflux side. Please, try again later.", + "error.database_error": "Database error: %v.", + "error.category_not_found": "This category does not exist or does not belong to this user.", + "error.duplicated_feed": "This feed already exists.", + "error.unable_to_parse_feed": "Unable to parse this feed: %v.", + "error.feed_not_found": "This feed does not exist or does not belong to this user.", + "error.unable_to_detect_rssbridge": "Unable to detect feed using RSS-Bridge: %v." } diff --git a/internal/locale/translations/id_ID.json b/internal/locale/translations/id_ID.json index 62ea5c76..b4f7e0f7 100644 --- a/internal/locale/translations/id_ID.json +++ b/internal/locale/translations/id_ID.json @@ -427,25 +427,29 @@ "time_elapsed.years": [ "%d tahun yang lalu" ], - "This feed already exists (%s)": "Umpan ini sudah ada (%s)", - "Unable to fetch feed (Status Code = %d)": "Tidak bisa mengambil umpan (Kode Status = %d)", - "Unable to open this link: %v": "Tidak bisa membuka tautan ini: %v", - "Unable to analyze this page: %v": "Tidak bisa menganalisis halaman ini: %v", - "Unable to execute request: %v": "Tidak bisa mengeksekusi permintaan: %v", - "Unable to parse OPML file: %q": "Tidak bisa mengurai berkas OPML: %q", - "Unable to parse RSS feed: %q": "Tidak bisa mengurai umpan RSS: %q", - "Unable to parse Atom feed: %q": "Tidak bisa mengurai umpan Atom: %q", - "Unable to parse JSON feed: %q": "Tidak bisa mengurai umpan JSON: %q", - "Unable to parse RDF feed: %q": "Tidak bisa mengurai umpan RDF: %q", - "Unable to normalize encoding: %q": "Tidak dapat menormalisasi enkode: %q", - "This feed is empty": "Umpan ini kosong", - "This web page is empty": "Halaman web ini kosong", - "Invalid SSL certificate (original error: %q)": "Sertifikat SSL tidak valid (galat: %q)", - "This website is unreachable (original error: %q)": "Situs ini tidak dapat tersambung (galat: %q)", - "Website unreachable, the request timed out after %d seconds": "Situs tidak dapat tersambung, permintaan galat setelah %d detik", - "You are not authorized to access this resource (invalid username/password)": "Anda tidak memiliki izin yang cukup untuk mengakses umpan ini (nama pengguna/kata sandi tidak valid)", - "Unable to fetch this resource (Status Code = %d)": "Tidak bisa mengambil umpan ini (Kode Status = %d)", - "Resource not found (404), this feed doesn't exist anymore, check the feed URL": "Umpan tidak ditemukan (404), umpan ini tidak ada lagi, periksa URL umpan", "alert.too_many_feeds_refresh": "You have triggered too many feed refreshes. Please wait 30 minutes before trying again.", - "alert.background_feed_refresh": "All feeds are being refreshed in the background. You can continue to use Miniflux while this process is running." + "alert.background_feed_refresh": "All feeds are being refreshed in the background. You can continue to use Miniflux while this process is running.", + "error.http_response_too_large": "The HTTP response is too large. You could increase the HTTP response size limit in the global settings (requires a server restart).", + "error.http_body_read": "Unable to read the HTTP body.", + "error.http_empty_response_body": "The HTTP response body is empty.", + "error.http_empty_response": "The HTTP response is empty. Perhaps, this website is using a bot protection mechanism?", + "error.tls_error": "TLS error: %v. You could disable TLS verification in the feed settings if you would like.", + "error.network_operation": "Miniflux is not able to reach this website due to a network error: %v.", + "error.network_timeout": "This website is too slow and the request timed out: %v", + "error.http_client_error": "HTTP client error: %v.", + "error.http_not_authorized": "Access to this website is not authorized. It could be a bad username or password.", + "error.http_too_many_requests": "Miniflux generated too many requests to this website. Please, try again later or change the application configuration.", + "error.http_forbidden": "Access to this website is forbidden. Perhaps, this website has a bot protection mechanism?", + "error.http_resource_not_found": "The requested resource is not found. Please, verify the URL.", + "error.http_internal_server_error": "The website is not available at the moment due to a server error. The problem is not on Miniflux side. Please, try again later.", + "error.http_bad_gateway": "The website is not available at the moment due to a bad gateway error. The problem is not on Miniflux side. Please, try again later.", + "error.http_service_unavailable": "The website is not available at the moment due to an internal server error. The problem is not on Miniflux side. Please, try again later.", + "error.http_gateway_timeout": "The website is not available at the moment due to a gateway timeout error. The problem is not on Miniflux side. Please, try again later.", + "error.http_unexpected_status_code": "The website is not available at the moment due to an unexpected HTTP status code: %d. The problem is not on Miniflux side. Please, try again later.", + "error.database_error": "Database error: %v.", + "error.category_not_found": "This category does not exist or does not belong to this user.", + "error.duplicated_feed": "This feed already exists.", + "error.unable_to_parse_feed": "Unable to parse this feed: %v.", + "error.feed_not_found": "This feed does not exist or does not belong to this user.", + "error.unable_to_detect_rssbridge": "Unable to detect feed using RSS-Bridge: %v." } diff --git a/internal/locale/translations/it_IT.json b/internal/locale/translations/it_IT.json index dd4a33e8..f93af980 100644 --- a/internal/locale/translations/it_IT.json +++ b/internal/locale/translations/it_IT.json @@ -437,5 +437,28 @@ "%d anni fa" ], "alert.too_many_feeds_refresh": "You have triggered too many feed refreshes. Please wait 30 minutes before trying again.", - "alert.background_feed_refresh": "All feeds are being refreshed in the background. You can continue to use Miniflux while this process is running." + "alert.background_feed_refresh": "All feeds are being refreshed in the background. You can continue to use Miniflux while this process is running.", + "error.http_response_too_large": "The HTTP response is too large. You could increase the HTTP response size limit in the global settings (requires a server restart).", + "error.http_body_read": "Unable to read the HTTP body.", + "error.http_empty_response_body": "The HTTP response body is empty.", + "error.http_empty_response": "The HTTP response is empty. Perhaps, this website is using a bot protection mechanism?", + "error.tls_error": "TLS error: %v. You could disable TLS verification in the feed settings if you would like.", + "error.network_operation": "Miniflux is not able to reach this website due to a network error: %v.", + "error.network_timeout": "This website is too slow and the request timed out: %v", + "error.http_client_error": "HTTP client error: %v.", + "error.http_not_authorized": "Access to this website is not authorized. It could be a bad username or password.", + "error.http_too_many_requests": "Miniflux generated too many requests to this website. Please, try again later or change the application configuration.", + "error.http_forbidden": "Access to this website is forbidden. Perhaps, this website has a bot protection mechanism?", + "error.http_resource_not_found": "The requested resource is not found. Please, verify the URL.", + "error.http_internal_server_error": "The website is not available at the moment due to a server error. The problem is not on Miniflux side. Please, try again later.", + "error.http_bad_gateway": "The website is not available at the moment due to a bad gateway error. The problem is not on Miniflux side. Please, try again later.", + "error.http_service_unavailable": "The website is not available at the moment due to an internal server error. The problem is not on Miniflux side. Please, try again later.", + "error.http_gateway_timeout": "The website is not available at the moment due to a gateway timeout error. The problem is not on Miniflux side. Please, try again later.", + "error.http_unexpected_status_code": "The website is not available at the moment due to an unexpected HTTP status code: %d. The problem is not on Miniflux side. Please, try again later.", + "error.database_error": "Database error: %v.", + "error.category_not_found": "This category does not exist or does not belong to this user.", + "error.duplicated_feed": "This feed already exists.", + "error.unable_to_parse_feed": "Unable to parse this feed: %v.", + "error.feed_not_found": "This feed does not exist or does not belong to this user.", + "error.unable_to_detect_rssbridge": "Unable to detect feed using RSS-Bridge: %v." } diff --git a/internal/locale/translations/ja_JP.json b/internal/locale/translations/ja_JP.json index 3eadf836..757f9f51 100644 --- a/internal/locale/translations/ja_JP.json +++ b/internal/locale/translations/ja_JP.json @@ -437,5 +437,28 @@ "%d 年前" ], "alert.too_many_feeds_refresh": "You have triggered too many feed refreshes. Please wait 30 minutes before trying again.", - "alert.background_feed_refresh": "All feeds are being refreshed in the background. You can continue to use Miniflux while this process is running." + "alert.background_feed_refresh": "All feeds are being refreshed in the background. You can continue to use Miniflux while this process is running.", + "error.http_response_too_large": "The HTTP response is too large. You could increase the HTTP response size limit in the global settings (requires a server restart).", + "error.http_body_read": "Unable to read the HTTP body.", + "error.http_empty_response_body": "The HTTP response body is empty.", + "error.http_empty_response": "The HTTP response is empty. Perhaps, this website is using a bot protection mechanism?", + "error.tls_error": "TLS error: %v. You could disable TLS verification in the feed settings if you would like.", + "error.network_operation": "Miniflux is not able to reach this website due to a network error: %v.", + "error.network_timeout": "This website is too slow and the request timed out: %v", + "error.http_client_error": "HTTP client error: %v.", + "error.http_not_authorized": "Access to this website is not authorized. It could be a bad username or password.", + "error.http_too_many_requests": "Miniflux generated too many requests to this website. Please, try again later or change the application configuration.", + "error.http_forbidden": "Access to this website is forbidden. Perhaps, this website has a bot protection mechanism?", + "error.http_resource_not_found": "The requested resource is not found. Please, verify the URL.", + "error.http_internal_server_error": "The website is not available at the moment due to a server error. The problem is not on Miniflux side. Please, try again later.", + "error.http_bad_gateway": "The website is not available at the moment due to a bad gateway error. The problem is not on Miniflux side. Please, try again later.", + "error.http_service_unavailable": "The website is not available at the moment due to an internal server error. The problem is not on Miniflux side. Please, try again later.", + "error.http_gateway_timeout": "The website is not available at the moment due to a gateway timeout error. The problem is not on Miniflux side. Please, try again later.", + "error.http_unexpected_status_code": "The website is not available at the moment due to an unexpected HTTP status code: %d. The problem is not on Miniflux side. Please, try again later.", + "error.database_error": "Database error: %v.", + "error.category_not_found": "This category does not exist or does not belong to this user.", + "error.duplicated_feed": "This feed already exists.", + "error.unable_to_parse_feed": "Unable to parse this feed: %v.", + "error.feed_not_found": "This feed does not exist or does not belong to this user.", + "error.unable_to_detect_rssbridge": "Unable to detect feed using RSS-Bridge: %v." } diff --git a/internal/locale/translations/nl_NL.json b/internal/locale/translations/nl_NL.json index 2b887f95..3efadfe6 100644 --- a/internal/locale/translations/nl_NL.json +++ b/internal/locale/translations/nl_NL.json @@ -436,23 +436,29 @@ "%d jaar geleden", "%d jaar geleden" ], - "This feed already exists (%s)": "Deze feed bestaat al (%s)", - "Unable to fetch feed (Status Code = %d)": "Kon feed niet updaten (statuscode = %d)", - "Unable to open this link: %v": "Kon link niet volgen: %v", - "Unable to analyze this page: %v": "Kon pagina niet analyseren: %v", - "Unable to execute request: %v": "Kon request niet uitvoeren: %v", - "Unable to parse OPML file: %q": "Kon OPML niet parsen: %q", - "Unable to parse RSS feed: %q": "Kon RSS-feed niet parsen: %q", - "Unable to parse Atom feed: %q": "Kon Atom-feed niet parsen: %q", - "Unable to parse JSON feed: %q": "Kon JSON-feed niet parsen: %q", - "Unable to parse RDF feed: %q": "Kon RDF-feed niet parsen: %q", - "Unable to normalize encoding: %q": "Kon encoding niet normaliseren: %q", - "Unable to create this category.": "Kon categorie niet aanmaken.", - "Category not found for this user": "Categorie niet gevonden voor deze gebruiker", - "This web page is empty": "Deze webpagina is leeg", - "Invalid SSL certificate (original error: %q)": "Ongeldig SSL-certificaat (originele error: %q)", - "This website is unreachable (original error: %q)": "Deze website is onbereikbaar (originele error: %q)", - "Website unreachable, the request timed out after %d seconds": "Website onbereikbaar, de request gaf een timeout na %d seconden", "alert.too_many_feeds_refresh": "You have triggered too many feed refreshes. Please wait 30 minutes before trying again.", - "alert.background_feed_refresh": "All feeds are being refreshed in the background. You can continue to use Miniflux while this process is running." + "alert.background_feed_refresh": "All feeds are being refreshed in the background. You can continue to use Miniflux while this process is running.", + "error.http_response_too_large": "The HTTP response is too large. You could increase the HTTP response size limit in the global settings (requires a server restart).", + "error.http_body_read": "Unable to read the HTTP body.", + "error.http_empty_response_body": "The HTTP response body is empty.", + "error.http_empty_response": "The HTTP response is empty. Perhaps, this website is using a bot protection mechanism?", + "error.tls_error": "TLS error: %v. You could disable TLS verification in the feed settings if you would like.", + "error.network_operation": "Miniflux is not able to reach this website due to a network error: %v.", + "error.network_timeout": "This website is too slow and the request timed out: %v", + "error.http_client_error": "HTTP client error: %v.", + "error.http_not_authorized": "Access to this website is not authorized. It could be a bad username or password.", + "error.http_too_many_requests": "Miniflux generated too many requests to this website. Please, try again later or change the application configuration.", + "error.http_forbidden": "Access to this website is forbidden. Perhaps, this website has a bot protection mechanism?", + "error.http_resource_not_found": "The requested resource is not found. Please, verify the URL.", + "error.http_internal_server_error": "The website is not available at the moment due to a server error. The problem is not on Miniflux side. Please, try again later.", + "error.http_bad_gateway": "The website is not available at the moment due to a bad gateway error. The problem is not on Miniflux side. Please, try again later.", + "error.http_service_unavailable": "The website is not available at the moment due to an internal server error. The problem is not on Miniflux side. Please, try again later.", + "error.http_gateway_timeout": "The website is not available at the moment due to a gateway timeout error. The problem is not on Miniflux side. Please, try again later.", + "error.http_unexpected_status_code": "The website is not available at the moment due to an unexpected HTTP status code: %d. The problem is not on Miniflux side. Please, try again later.", + "error.database_error": "Database error: %v.", + "error.category_not_found": "This category does not exist or does not belong to this user.", + "error.duplicated_feed": "This feed already exists.", + "error.unable_to_parse_feed": "Unable to parse this feed: %v.", + "error.feed_not_found": "This feed does not exist or does not belong to this user.", + "error.unable_to_detect_rssbridge": "Unable to detect feed using RSS-Bridge: %v." } diff --git a/internal/locale/translations/pl_PL.json b/internal/locale/translations/pl_PL.json index 08ff54c0..62744703 100644 --- a/internal/locale/translations/pl_PL.json +++ b/internal/locale/translations/pl_PL.json @@ -444,23 +444,29 @@ "%d lat temu", "%d lat temu" ], - "This feed already exists (%s)": "Ten kanał już istnieje (%s)", - "Unable to fetch feed (Status Code = %d)": "Kanał nie mógł zostać pobrany (kod=%d)", - "Unable to open this link: %v": "Nie można było otworzyć tego linku: %v", - "Unable to analyze this page: %v": "Nie można przeanalizować tej strony: %v", - "Unable to execute request: %v": "To polecenie nie mogło zostać wykonane: %v", - "Unable to parse OPML file: %q": "Plik OPML nie mógł zostać odczytany: %q", - "Unable to parse RSS feed: %q": "Nie można było odczytać kanału RSS: %q", - "Unable to parse Atom feed: %q": "Nie można było odczytać kanału Atom: %q", - "Unable to parse JSON feed: %q": "Nie można było odczytać kanału JSON: %q", - "Unable to parse RDF feed: %q": "Nie można było odczytać kanału RDF: %q", - "Unable to normalize encoding: %q": "Kodowanie znaków nie mogło zostać znormalizowane: %q", - "Category not found for this user": "Kategoria nie znaleziona dla tego użytkownika", - "This feed is empty": "Ten kanał jest pusty", - "This web page is empty": "Ta strona jest pusta", - "Invalid SSL certificate (original error: %q)": "Certyfikat SSL jest nieprawidłowy (błąd: %q)", - "This website is unreachable (original error: %q)": "Ta strona jest niedostępna (błąd: %q)", - "Website unreachable, the request timed out after %d seconds": "Strona internetowa nieosiągalna, żądanie wygasło po %d sekundach", "alert.too_many_feeds_refresh": "You have triggered too many feed refreshes. Please wait 30 minutes before trying again.", - "alert.background_feed_refresh": "All feeds are being refreshed in the background. You can continue to use Miniflux while this process is running." + "alert.background_feed_refresh": "All feeds are being refreshed in the background. You can continue to use Miniflux while this process is running.", + "error.http_response_too_large": "The HTTP response is too large. You could increase the HTTP response size limit in the global settings (requires a server restart).", + "error.http_body_read": "Unable to read the HTTP body.", + "error.http_empty_response_body": "The HTTP response body is empty.", + "error.http_empty_response": "The HTTP response is empty. Perhaps, this website is using a bot protection mechanism?", + "error.tls_error": "TLS error: %v. You could disable TLS verification in the feed settings if you would like.", + "error.network_operation": "Miniflux is not able to reach this website due to a network error: %v.", + "error.network_timeout": "This website is too slow and the request timed out: %v", + "error.http_client_error": "HTTP client error: %v.", + "error.http_not_authorized": "Access to this website is not authorized. It could be a bad username or password.", + "error.http_too_many_requests": "Miniflux generated too many requests to this website. Please, try again later or change the application configuration.", + "error.http_forbidden": "Access to this website is forbidden. Perhaps, this website has a bot protection mechanism?", + "error.http_resource_not_found": "The requested resource is not found. Please, verify the URL.", + "error.http_internal_server_error": "The website is not available at the moment due to a server error. The problem is not on Miniflux side. Please, try again later.", + "error.http_bad_gateway": "The website is not available at the moment due to a bad gateway error. The problem is not on Miniflux side. Please, try again later.", + "error.http_service_unavailable": "The website is not available at the moment due to an internal server error. The problem is not on Miniflux side. Please, try again later.", + "error.http_gateway_timeout": "The website is not available at the moment due to a gateway timeout error. The problem is not on Miniflux side. Please, try again later.", + "error.http_unexpected_status_code": "The website is not available at the moment due to an unexpected HTTP status code: %d. The problem is not on Miniflux side. Please, try again later.", + "error.database_error": "Database error: %v.", + "error.category_not_found": "This category does not exist or does not belong to this user.", + "error.duplicated_feed": "This feed already exists.", + "error.unable_to_parse_feed": "Unable to parse this feed: %v.", + "error.feed_not_found": "This feed does not exist or does not belong to this user.", + "error.unable_to_detect_rssbridge": "Unable to detect feed using RSS-Bridge: %v." } diff --git a/internal/locale/translations/pt_BR.json b/internal/locale/translations/pt_BR.json index bb9d40a0..0651fe71 100644 --- a/internal/locale/translations/pt_BR.json +++ b/internal/locale/translations/pt_BR.json @@ -437,5 +437,28 @@ "há %d anos" ], "alert.too_many_feeds_refresh": "You have triggered too many feed refreshes. Please wait 30 minutes before trying again.", - "alert.background_feed_refresh": "All feeds are being refreshed in the background. You can continue to use Miniflux while this process is running." + "alert.background_feed_refresh": "All feeds are being refreshed in the background. You can continue to use Miniflux while this process is running.", + "error.http_response_too_large": "The HTTP response is too large. You could increase the HTTP response size limit in the global settings (requires a server restart).", + "error.http_body_read": "Unable to read the HTTP body.", + "error.http_empty_response_body": "The HTTP response body is empty.", + "error.http_empty_response": "The HTTP response is empty. Perhaps, this website is using a bot protection mechanism?", + "error.tls_error": "TLS error: %v. You could disable TLS verification in the feed settings if you would like.", + "error.network_operation": "Miniflux is not able to reach this website due to a network error: %v.", + "error.network_timeout": "This website is too slow and the request timed out: %v", + "error.http_client_error": "HTTP client error: %v.", + "error.http_not_authorized": "Access to this website is not authorized. It could be a bad username or password.", + "error.http_too_many_requests": "Miniflux generated too many requests to this website. Please, try again later or change the application configuration.", + "error.http_forbidden": "Access to this website is forbidden. Perhaps, this website has a bot protection mechanism?", + "error.http_resource_not_found": "The requested resource is not found. Please, verify the URL.", + "error.http_internal_server_error": "The website is not available at the moment due to a server error. The problem is not on Miniflux side. Please, try again later.", + "error.http_bad_gateway": "The website is not available at the moment due to a bad gateway error. The problem is not on Miniflux side. Please, try again later.", + "error.http_service_unavailable": "The website is not available at the moment due to an internal server error. The problem is not on Miniflux side. Please, try again later.", + "error.http_gateway_timeout": "The website is not available at the moment due to a gateway timeout error. The problem is not on Miniflux side. Please, try again later.", + "error.http_unexpected_status_code": "The website is not available at the moment due to an unexpected HTTP status code: %d. The problem is not on Miniflux side. Please, try again later.", + "error.database_error": "Database error: %v.", + "error.category_not_found": "This category does not exist or does not belong to this user.", + "error.duplicated_feed": "This feed already exists.", + "error.unable_to_parse_feed": "Unable to parse this feed: %v.", + "error.feed_not_found": "This feed does not exist or does not belong to this user.", + "error.unable_to_detect_rssbridge": "Unable to detect feed using RSS-Bridge: %v." } diff --git a/internal/locale/translations/ru_RU.json b/internal/locale/translations/ru_RU.json index 2ad084c3..8f2a9d71 100644 --- a/internal/locale/translations/ru_RU.json +++ b/internal/locale/translations/ru_RU.json @@ -445,5 +445,28 @@ "%d лет назад" ], "alert.too_many_feeds_refresh": "You have triggered too many feed refreshes. Please wait 30 minutes before trying again.", - "alert.background_feed_refresh": "All feeds are being refreshed in the background. You can continue to use Miniflux while this process is running." + "alert.background_feed_refresh": "All feeds are being refreshed in the background. You can continue to use Miniflux while this process is running.", + "error.http_response_too_large": "The HTTP response is too large. You could increase the HTTP response size limit in the global settings (requires a server restart).", + "error.http_body_read": "Unable to read the HTTP body.", + "error.http_empty_response_body": "The HTTP response body is empty.", + "error.http_empty_response": "The HTTP response is empty. Perhaps, this website is using a bot protection mechanism?", + "error.tls_error": "TLS error: %v. You could disable TLS verification in the feed settings if you would like.", + "error.network_operation": "Miniflux is not able to reach this website due to a network error: %v.", + "error.network_timeout": "This website is too slow and the request timed out: %v", + "error.http_client_error": "HTTP client error: %v.", + "error.http_not_authorized": "Access to this website is not authorized. It could be a bad username or password.", + "error.http_too_many_requests": "Miniflux generated too many requests to this website. Please, try again later or change the application configuration.", + "error.http_forbidden": "Access to this website is forbidden. Perhaps, this website has a bot protection mechanism?", + "error.http_resource_not_found": "The requested resource is not found. Please, verify the URL.", + "error.http_internal_server_error": "The website is not available at the moment due to a server error. The problem is not on Miniflux side. Please, try again later.", + "error.http_bad_gateway": "The website is not available at the moment due to a bad gateway error. The problem is not on Miniflux side. Please, try again later.", + "error.http_service_unavailable": "The website is not available at the moment due to an internal server error. The problem is not on Miniflux side. Please, try again later.", + "error.http_gateway_timeout": "The website is not available at the moment due to a gateway timeout error. The problem is not on Miniflux side. Please, try again later.", + "error.http_unexpected_status_code": "The website is not available at the moment due to an unexpected HTTP status code: %d. The problem is not on Miniflux side. Please, try again later.", + "error.database_error": "Database error: %v.", + "error.category_not_found": "This category does not exist or does not belong to this user.", + "error.duplicated_feed": "This feed already exists.", + "error.unable_to_parse_feed": "Unable to parse this feed: %v.", + "error.feed_not_found": "This feed does not exist or does not belong to this user.", + "error.unable_to_detect_rssbridge": "Unable to detect feed using RSS-Bridge: %v." } diff --git a/internal/locale/translations/tr_TR.json b/internal/locale/translations/tr_TR.json index d896b8f7..b732fa5b 100644 --- a/internal/locale/translations/tr_TR.json +++ b/internal/locale/translations/tr_TR.json @@ -437,5 +437,28 @@ "%d yıl önce" ], "alert.too_many_feeds_refresh": "You have triggered too many feed refreshes. Please wait 30 minutes before trying again.", - "alert.background_feed_refresh": "All feeds are being refreshed in the background. You can continue to use Miniflux while this process is running." + "alert.background_feed_refresh": "All feeds are being refreshed in the background. You can continue to use Miniflux while this process is running.", + "error.http_response_too_large": "The HTTP response is too large. You could increase the HTTP response size limit in the global settings (requires a server restart).", + "error.http_body_read": "Unable to read the HTTP body.", + "error.http_empty_response_body": "The HTTP response body is empty.", + "error.http_empty_response": "The HTTP response is empty. Perhaps, this website is using a bot protection mechanism?", + "error.tls_error": "TLS error: %v. You could disable TLS verification in the feed settings if you would like.", + "error.network_operation": "Miniflux is not able to reach this website due to a network error: %v.", + "error.network_timeout": "This website is too slow and the request timed out: %v", + "error.http_client_error": "HTTP client error: %v.", + "error.http_not_authorized": "Access to this website is not authorized. It could be a bad username or password.", + "error.http_too_many_requests": "Miniflux generated too many requests to this website. Please, try again later or change the application configuration.", + "error.http_forbidden": "Access to this website is forbidden. Perhaps, this website has a bot protection mechanism?", + "error.http_resource_not_found": "The requested resource is not found. Please, verify the URL.", + "error.http_internal_server_error": "The website is not available at the moment due to a server error. The problem is not on Miniflux side. Please, try again later.", + "error.http_bad_gateway": "The website is not available at the moment due to a bad gateway error. The problem is not on Miniflux side. Please, try again later.", + "error.http_service_unavailable": "The website is not available at the moment due to an internal server error. The problem is not on Miniflux side. Please, try again later.", + "error.http_gateway_timeout": "The website is not available at the moment due to a gateway timeout error. The problem is not on Miniflux side. Please, try again later.", + "error.http_unexpected_status_code": "The website is not available at the moment due to an unexpected HTTP status code: %d. The problem is not on Miniflux side. Please, try again later.", + "error.database_error": "Database error: %v.", + "error.category_not_found": "This category does not exist or does not belong to this user.", + "error.duplicated_feed": "This feed already exists.", + "error.unable_to_parse_feed": "Unable to parse this feed: %v.", + "error.feed_not_found": "This feed does not exist or does not belong to this user.", + "error.unable_to_detect_rssbridge": "Unable to detect feed using RSS-Bridge: %v." } diff --git a/internal/locale/translations/uk_UA.json b/internal/locale/translations/uk_UA.json index 22d69d77..39226cd7 100644 --- a/internal/locale/translations/uk_UA.json +++ b/internal/locale/translations/uk_UA.json @@ -446,5 +446,28 @@ "%d років тому" ], "alert.too_many_feeds_refresh": "You have triggered too many feed refreshes. Please wait 30 minutes before trying again.", - "alert.background_feed_refresh": "All feeds are being refreshed in the background. You can continue to use Miniflux while this process is running." + "alert.background_feed_refresh": "All feeds are being refreshed in the background. You can continue to use Miniflux while this process is running.", + "error.http_response_too_large": "The HTTP response is too large. You could increase the HTTP response size limit in the global settings (requires a server restart).", + "error.http_body_read": "Unable to read the HTTP body.", + "error.http_empty_response_body": "The HTTP response body is empty.", + "error.http_empty_response": "The HTTP response is empty. Perhaps, this website is using a bot protection mechanism?", + "error.tls_error": "TLS error: %v. You could disable TLS verification in the feed settings if you would like.", + "error.network_operation": "Miniflux is not able to reach this website due to a network error: %v.", + "error.network_timeout": "This website is too slow and the request timed out: %v", + "error.http_client_error": "HTTP client error: %v.", + "error.http_not_authorized": "Access to this website is not authorized. It could be a bad username or password.", + "error.http_too_many_requests": "Miniflux generated too many requests to this website. Please, try again later or change the application configuration.", + "error.http_forbidden": "Access to this website is forbidden. Perhaps, this website has a bot protection mechanism?", + "error.http_resource_not_found": "The requested resource is not found. Please, verify the URL.", + "error.http_internal_server_error": "The website is not available at the moment due to a server error. The problem is not on Miniflux side. Please, try again later.", + "error.http_bad_gateway": "The website is not available at the moment due to a bad gateway error. The problem is not on Miniflux side. Please, try again later.", + "error.http_service_unavailable": "The website is not available at the moment due to an internal server error. The problem is not on Miniflux side. Please, try again later.", + "error.http_gateway_timeout": "The website is not available at the moment due to a gateway timeout error. The problem is not on Miniflux side. Please, try again later.", + "error.http_unexpected_status_code": "The website is not available at the moment due to an unexpected HTTP status code: %d. The problem is not on Miniflux side. Please, try again later.", + "error.database_error": "Database error: %v.", + "error.category_not_found": "This category does not exist or does not belong to this user.", + "error.duplicated_feed": "This feed already exists.", + "error.unable_to_parse_feed": "Unable to parse this feed: %v.", + "error.feed_not_found": "This feed does not exist or does not belong to this user.", + "error.unable_to_detect_rssbridge": "Unable to detect feed using RSS-Bridge: %v." } diff --git a/internal/locale/translations/zh_CN.json b/internal/locale/translations/zh_CN.json index da90de6b..4b265615 100644 --- a/internal/locale/translations/zh_CN.json +++ b/internal/locale/translations/zh_CN.json @@ -428,24 +428,29 @@ "time_elapsed.years": [ "%d 年前" ], - "This feed already exists (%s)": "源已存在 (%s)", - "Unable to fetch feed (Status Code = %d)": "无法获取源 (错误代码=%d)", - "Unable to open this link: %v": "无法打开这一链接: %v", - "Unable to analyze this page: %v": "无法分析这一页面: %v", - "Unable to execute request: %v": "无法执行这一请求: %v", - "Unable to parse OPML file: %q": "无法解析 OPML 文件: %q", - "Unable to parse RSS feed: %q": "无法解析 RSS 源: %q", - "Unable to parse Atom feed: %q": "无法解析 Atom 源: %q", - "Unable to parse JSON feed: %q": "无法解析 JSON 源: %q", - "Unable to parse RDF feed: %q": "无法解析 RDF 源: %q", - "Unable to read data: %q": "无法读取数据: %q", - "Unable to normalize encoding: %q": "无法正则化编码: %q", - "Category not found for this user": "未找到该用户的这一分类", - "This feed is empty": "该源是空的", - "This web page is empty": "该网页是空的", - "Invalid SSL certificate (original error: %q)": "无效的 SSL 证书 (原始错误: %q)", - "This website is unreachable (original error: %q)": "该网站永久不可达 (原始错误: %q)", - "Website unreachable, the request timed out after %d seconds": "网站不可达, 请求已在 %d 秒后超时", "alert.too_many_feeds_refresh": "You have triggered too many feed refreshes. Please wait 30 minutes before trying again.", - "alert.background_feed_refresh": "All feeds are being refreshed in the background. You can continue to use Miniflux while this process is running." + "alert.background_feed_refresh": "All feeds are being refreshed in the background. You can continue to use Miniflux while this process is running.", + "error.http_response_too_large": "The HTTP response is too large. You could increase the HTTP response size limit in the global settings (requires a server restart).", + "error.http_body_read": "Unable to read the HTTP body.", + "error.http_empty_response_body": "The HTTP response body is empty.", + "error.http_empty_response": "The HTTP response is empty. Perhaps, this website is using a bot protection mechanism?", + "error.tls_error": "TLS error: %v. You could disable TLS verification in the feed settings if you would like.", + "error.network_operation": "Miniflux is not able to reach this website due to a network error: %v.", + "error.network_timeout": "This website is too slow and the request timed out: %v", + "error.http_client_error": "HTTP client error: %v.", + "error.http_not_authorized": "Access to this website is not authorized. It could be a bad username or password.", + "error.http_too_many_requests": "Miniflux generated too many requests to this website. Please, try again later or change the application configuration.", + "error.http_forbidden": "Access to this website is forbidden. Perhaps, this website has a bot protection mechanism?", + "error.http_resource_not_found": "The requested resource is not found. Please, verify the URL.", + "error.http_internal_server_error": "The website is not available at the moment due to a server error. The problem is not on Miniflux side. Please, try again later.", + "error.http_bad_gateway": "The website is not available at the moment due to a bad gateway error. The problem is not on Miniflux side. Please, try again later.", + "error.http_service_unavailable": "The website is not available at the moment due to an internal server error. The problem is not on Miniflux side. Please, try again later.", + "error.http_gateway_timeout": "The website is not available at the moment due to a gateway timeout error. The problem is not on Miniflux side. Please, try again later.", + "error.http_unexpected_status_code": "The website is not available at the moment due to an unexpected HTTP status code: %d. The problem is not on Miniflux side. Please, try again later.", + "error.database_error": "Database error: %v.", + "error.category_not_found": "This category does not exist or does not belong to this user.", + "error.duplicated_feed": "This feed already exists.", + "error.unable_to_parse_feed": "Unable to parse this feed: %v.", + "error.feed_not_found": "This feed does not exist or does not belong to this user.", + "error.unable_to_detect_rssbridge": "Unable to detect feed using RSS-Bridge: %v." } diff --git a/internal/locale/translations/zh_TW.json b/internal/locale/translations/zh_TW.json index 52b75745..3b556773 100644 --- a/internal/locale/translations/zh_TW.json +++ b/internal/locale/translations/zh_TW.json @@ -436,24 +436,29 @@ "%d 年前", "%d 年前" ], - "This feed already exists (%s)": "Feed已存在 (%s)", - "Unable to fetch feed (Status Code = %d)": "無法獲取Feed (錯誤程式碼=%d)", - "Unable to open this link: %v": "無法開啟這一連結: %v", - "Unable to analyze this page: %v": "無法分析這一頁面: %v", - "Unable to execute request: %v": "無法執行這一請求: %v", - "Unable to parse OPML file: %q": "無法解析 OPML 檔案: %q", - "Unable to parse RSS feed: %q": "無法解析 RSS Feed: %q", - "Unable to parse Atom feed: %q": "無法解析 Atom Feed: %q", - "Unable to parse JSON feed: %q": "無法解析 JSON Feed: %q", - "Unable to parse RDF feed: %q": "無法解析 RDF Feed: %q", - "Unable to read data: %q": "無法讀取資料: %q", - "Unable to normalize encoding: %q": "無法正則化編碼: %q", - "Category not found for this user": "未找到該使用者的這一分類", - "This feed is empty": "該Feed是空的", - "This web page is empty": "該網頁是空的", - "Invalid SSL certificate (original error: %q)": "無效的 SSL 憑證 (錯誤: %q)", - "This website is unreachable (original error: %q)": "該網站永久無法訪問(原始錯誤: %q)", - "Website unreachable, the request timed out after %d seconds": "網站無法訪問, 請求已在 %d 秒後超時", "alert.too_many_feeds_refresh": "You have triggered too many feed refreshes. Please wait 30 minutes before trying again.", - "alert.background_feed_refresh": "All feeds are being refreshed in the background. You can continue to use Miniflux while this process is running." + "alert.background_feed_refresh": "All feeds are being refreshed in the background. You can continue to use Miniflux while this process is running.", + "error.http_response_too_large": "The HTTP response is too large. You could increase the HTTP response size limit in the global settings (requires a server restart).", + "error.http_body_read": "Unable to read the HTTP body.", + "error.http_empty_response_body": "The HTTP response body is empty.", + "error.http_empty_response": "The HTTP response is empty. Perhaps, this website is using a bot protection mechanism?", + "error.tls_error": "TLS error: %v. You could disable TLS verification in the feed settings if you would like.", + "error.network_operation": "Miniflux is not able to reach this website due to a network error: %v.", + "error.network_timeout": "This website is too slow and the request timed out: %v", + "error.http_client_error": "HTTP client error: %v.", + "error.http_not_authorized": "Access to this website is not authorized. It could be a bad username or password.", + "error.http_too_many_requests": "Miniflux generated too many requests to this website. Please, try again later or change the application configuration.", + "error.http_forbidden": "Access to this website is forbidden. Perhaps, this website has a bot protection mechanism?", + "error.http_resource_not_found": "The requested resource is not found. Please, verify the URL.", + "error.http_internal_server_error": "The website is not available at the moment due to a server error. The problem is not on Miniflux side. Please, try again later.", + "error.http_bad_gateway": "The website is not available at the moment due to a bad gateway error. The problem is not on Miniflux side. Please, try again later.", + "error.http_service_unavailable": "The website is not available at the moment due to an internal server error. The problem is not on Miniflux side. Please, try again later.", + "error.http_gateway_timeout": "The website is not available at the moment due to a gateway timeout error. The problem is not on Miniflux side. Please, try again later.", + "error.http_unexpected_status_code": "The website is not available at the moment due to an unexpected HTTP status code: %d. The problem is not on Miniflux side. Please, try again later.", + "error.database_error": "Database error: %v.", + "error.category_not_found": "This category does not exist or does not belong to this user.", + "error.duplicated_feed": "This feed already exists.", + "error.unable_to_parse_feed": "Unable to parse this feed: %v.", + "error.feed_not_found": "This feed does not exist or does not belong to this user.", + "error.unable_to_detect_rssbridge": "Unable to detect feed using RSS-Bridge: %v." } diff --git a/internal/model/feed.go b/internal/model/feed.go index 9e2b89e8..88560a27 100644 --- a/internal/model/feed.go +++ b/internal/model/feed.go @@ -9,7 +9,6 @@ import ( "time" "miniflux.app/v2/internal/config" - "miniflux.app/v2/internal/http/client" ) // List of supported schedulers. @@ -79,20 +78,13 @@ func (f *Feed) String() string { ) } -// WithClientResponse updates feed attributes from an HTTP request. -func (f *Feed) WithClientResponse(response *client.Response) { - f.EtagHeader = response.ETag - f.LastModifiedHeader = response.LastModified - f.FeedURL = response.EffectiveURL -} - // WithCategoryID initializes the category attribute of the feed. func (f *Feed) WithCategoryID(categoryID int64) { f.Category = &Category{ID: categoryID} } -// WithError adds a new error message and increment the error counter. -func (f *Feed) WithError(message string) { +// WithTranslatedErrorMessage adds a new error message and increment the error counter. +func (f *Feed) WithTranslatedErrorMessage(message string) { f.ParsingErrorCount++ f.ParsingErrorMsg = message } diff --git a/internal/model/feed_test.go b/internal/model/feed_test.go index 0a4c44a8..394279dd 100644 --- a/internal/model/feed_test.go +++ b/internal/model/feed_test.go @@ -10,28 +10,8 @@ import ( "time" "miniflux.app/v2/internal/config" - "miniflux.app/v2/internal/http/client" ) -func TestFeedWithResponse(t *testing.T) { - response := &client.Response{ETag: "Some etag", LastModified: "Some date", EffectiveURL: "Some URL"} - - feed := &Feed{} - feed.WithClientResponse(response) - - if feed.EtagHeader != "Some etag" { - t.Fatal(`The ETag header should be set`) - } - - if feed.LastModifiedHeader != "Some date" { - t.Fatal(`The LastModified header should be set`) - } - - if feed.FeedURL != "Some URL" { - t.Fatal(`The Feed URL should be set`) - } -} - func TestFeedCategorySetter(t *testing.T) { feed := &Feed{} feed.WithCategoryID(int64(123)) @@ -47,7 +27,7 @@ func TestFeedCategorySetter(t *testing.T) { func TestFeedErrorCounter(t *testing.T) { feed := &Feed{} - feed.WithError("Some Error") + feed.WithTranslatedErrorMessage("Some Error") if feed.ParsingErrorMsg != "Some Error" { t.Error(`The error message must be set`) diff --git a/internal/reader/atom/parser.go b/internal/reader/atom/parser.go index b685a7a8..aab3e6a4 100644 --- a/internal/reader/atom/parser.go +++ b/internal/reader/atom/parser.go @@ -6,9 +6,9 @@ package atom // import "miniflux.app/v2/internal/reader/atom" import ( "bytes" "encoding/xml" + "fmt" "io" - "miniflux.app/v2/internal/errors" "miniflux.app/v2/internal/model" xml_decoder "miniflux.app/v2/internal/reader/xml" ) @@ -18,7 +18,7 @@ type atomFeed interface { } // Parse returns a normalized feed struct from a Atom feed. -func Parse(baseURL string, r io.Reader) (*model.Feed, *errors.LocalizedError) { +func Parse(baseURL string, r io.Reader) (*model.Feed, error) { var buf bytes.Buffer tee := io.TeeReader(r, &buf) @@ -29,10 +29,8 @@ func Parse(baseURL string, r io.Reader) (*model.Feed, *errors.LocalizedError) { rawFeed = new(atom10Feed) } - decoder := xml_decoder.NewDecoder(&buf) - err := decoder.Decode(rawFeed) - if err != nil { - return nil, errors.NewLocalizedError("Unable to parse Atom feed: %q", err) + if err := xml_decoder.NewDecoder(&buf).Decode(rawFeed); err != nil { + return nil, fmt.Errorf("atom: unable to parse feed: %w", err) } return rawFeed.Transform(baseURL), nil diff --git a/internal/reader/browser/browser.go b/internal/reader/browser/browser.go deleted file mode 100644 index fe5374d1..00000000 --- a/internal/reader/browser/browser.go +++ /dev/null @@ -1,54 +0,0 @@ -// SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved. -// SPDX-License-Identifier: Apache-2.0 - -package browser // import "miniflux.app/v2/internal/reader/browser" - -import ( - "miniflux.app/v2/internal/errors" - "miniflux.app/v2/internal/http/client" -) - -var ( - errRequestFailed = "Unable to open this link: %v" - errServerFailure = "Unable to fetch this resource (Status Code = %d)" - errEncoding = "Unable to normalize encoding: %q" - errEmptyFeed = "This feed is empty" - errResourceNotFound = "Resource not found (404), this feed doesn't exist anymore, check the feed URL" - errNotAuthorized = "You are not authorized to access this resource (invalid username/password)" -) - -// Exec executes a HTTP request and handles errors. -func Exec(request *client.Client) (*client.Response, *errors.LocalizedError) { - response, err := request.Get() - if err != nil { - if e, ok := err.(*errors.LocalizedError); ok { - return nil, e - } - return nil, errors.NewLocalizedError(errRequestFailed, err) - } - - if response.IsNotFound() { - return nil, errors.NewLocalizedError(errResourceNotFound) - } - - if response.IsNotAuthorized() { - return nil, errors.NewLocalizedError(errNotAuthorized) - } - - if response.HasServerFailure() { - return nil, errors.NewLocalizedError(errServerFailure, response.StatusCode) - } - - if response.StatusCode != 304 { - // Content-Length = -1 when no Content-Length header is sent. - if response.ContentLength == 0 { - return nil, errors.NewLocalizedError(errEmptyFeed) - } - - if err := response.EnsureUnicodeBody(); err != nil { - return nil, errors.NewLocalizedError(errEncoding, err) - } - } - - return response, nil -} diff --git a/internal/reader/fetcher/request_builder.go b/internal/reader/fetcher/request_builder.go new file mode 100644 index 00000000..6c11488b --- /dev/null +++ b/internal/reader/fetcher/request_builder.go @@ -0,0 +1,168 @@ +// SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +package fetcher // import "miniflux.app/v2/internal/reader/fetcher" + +import ( + "crypto/tls" + "encoding/base64" + "log/slog" + "net" + "net/http" + "net/url" + "time" +) + +const ( + defaultHTTPClientTimeout = 20 + defaultHTTPClientMaxBodySize = 15 * 1024 * 1024 +) + +type RequestBuilder struct { + headers http.Header + clientProxyURL string + useClientProxy bool + clientTimeout int + withoutRedirects bool + ignoreTLSErrors bool +} + +func NewRequestBuilder() *RequestBuilder { + return &RequestBuilder{ + headers: make(http.Header), + clientTimeout: defaultHTTPClientTimeout, + } +} + +func (r *RequestBuilder) WithHeader(key, value string) *RequestBuilder { + r.headers.Set(key, value) + return r +} + +func (r *RequestBuilder) WithETag(etag string) *RequestBuilder { + if etag != "" { + r.headers.Set("If-None-Match", etag) + } + return r +} + +func (r *RequestBuilder) WithLastModified(lastModified string) *RequestBuilder { + if lastModified != "" { + r.headers.Set("If-Modified-Since", lastModified) + } + return r +} + +func (r *RequestBuilder) WithUserAgent(userAgent string) *RequestBuilder { + if userAgent != "" { + r.headers.Set("User-Agent", userAgent) + } else { + r.headers.Del("User-Agent") + } + return r +} + +func (r *RequestBuilder) WithCookie(cookie string) *RequestBuilder { + if cookie != "" { + r.headers.Set("Cookie", cookie) + } + return r +} + +func (r *RequestBuilder) WithUsernameAndPassword(username, password string) *RequestBuilder { + if username != "" && password != "" { + r.headers.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(username+":"+password))) + } + return r +} + +func (r *RequestBuilder) WithProxy(proxyURL string) *RequestBuilder { + r.clientProxyURL = proxyURL + return r +} + +func (r *RequestBuilder) UseProxy(value bool) *RequestBuilder { + r.useClientProxy = value + return r +} + +func (r *RequestBuilder) WithTimeout(timeout int) *RequestBuilder { + r.clientTimeout = timeout + return r +} + +func (r *RequestBuilder) WithoutRedirects() *RequestBuilder { + r.withoutRedirects = true + return r +} + +func (r *RequestBuilder) IgnoreTLSErrors(value bool) *RequestBuilder { + r.ignoreTLSErrors = value + return r +} + +func (r *RequestBuilder) ExecuteRequest(requestURL string) (*http.Response, error) { + transport := &http.Transport{ + Proxy: http.ProxyFromEnvironment, + DialContext: (&net.Dialer{ + // Default is 30s. + Timeout: 10 * time.Second, + + // Default is 30s. + KeepAlive: 15 * time.Second, + }).DialContext, + + // Default is 100. + MaxIdleConns: 50, + + // Default is 90s. + IdleConnTimeout: 10 * time.Second, + + TLSClientConfig: &tls.Config{ + InsecureSkipVerify: r.ignoreTLSErrors, + }, + } + + if r.useClientProxy && r.clientProxyURL != "" { + if proxyURL, err := url.Parse(r.clientProxyURL); err != nil { + slog.Warn("Unable to parse proxy URL", + slog.String("proxy_url", r.clientProxyURL), + slog.Any("error", err), + ) + } else { + transport.Proxy = http.ProxyURL(proxyURL) + } + } + + client := &http.Client{ + Timeout: time.Duration(r.clientTimeout) * time.Second, + } + + if r.withoutRedirects { + client.CheckRedirect = func(req *http.Request, via []*http.Request) error { + return http.ErrUseLastResponse + } + } + + client.Transport = transport + + req, err := http.NewRequest("GET", requestURL, nil) + if err != nil { + return nil, err + } + + req.Header = r.headers + req.Header.Set("Accept", "*/*") + req.Header.Set("Connection", "close") + + slog.Debug("Making outgoing request", slog.Group("request", + slog.String("method", req.Method), + slog.String("url", req.URL.String()), + slog.Any("headers", req.Header), + slog.Bool("without_redirects", r.withoutRedirects), + slog.Bool("with_proxy", r.useClientProxy), + slog.String("proxy_url", r.clientProxyURL), + )) + + return client.Do(req) +} diff --git a/internal/reader/fetcher/response_handler.go b/internal/reader/fetcher/response_handler.go new file mode 100644 index 00000000..1283b405 --- /dev/null +++ b/internal/reader/fetcher/response_handler.go @@ -0,0 +1,147 @@ +// SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +package fetcher // import "miniflux.app/v2/internal/reader/fetcher" + +import ( + "crypto/x509" + "errors" + "fmt" + "io" + "net" + "net/http" + + "miniflux.app/v2/internal/locale" +) + +type ResponseHandler struct { + httpResponse *http.Response + clientErr error +} + +func NewResponseHandler(httpResponse *http.Response, clientErr error) *ResponseHandler { + return &ResponseHandler{httpResponse: httpResponse, clientErr: clientErr} +} + +func (r *ResponseHandler) EffectiveURL() string { + return r.httpResponse.Request.URL.String() +} + +func (r *ResponseHandler) ContentType() string { + return r.httpResponse.Header.Get("Content-Type") +} + +func (r *ResponseHandler) LastModified() string { + // Ignore caching headers for feeds that do not want any cache. + if r.httpResponse.Header.Get("Expires") == "0" { + return "" + } + return r.httpResponse.Header.Get("Last-Modified") +} + +func (r *ResponseHandler) ETag() string { + // Ignore caching headers for feeds that do not want any cache. + if r.httpResponse.Header.Get("Expires") == "0" { + return "" + } + return r.httpResponse.Header.Get("ETag") +} + +func (r *ResponseHandler) IsModified(lastEtagValue, lastModifiedValue string) bool { + if r.httpResponse.StatusCode == http.StatusNotModified { + return false + } + + if r.ETag() != "" && r.ETag() == lastEtagValue { + return false + } + + if r.LastModified() != "" && r.LastModified() == lastModifiedValue { + return false + } + + return true +} + +func (r *ResponseHandler) Close() { + if r.httpResponse != nil && r.httpResponse.Body != nil && r.clientErr == nil { + r.httpResponse.Body.Close() + } +} + +func (r *ResponseHandler) Body(maxBodySize int64) io.ReadCloser { + return http.MaxBytesReader(nil, r.httpResponse.Body, maxBodySize) +} + +func (r *ResponseHandler) ReadBody(maxBodySize int64) ([]byte, *locale.LocalizedErrorWrapper) { + limitedReader := http.MaxBytesReader(nil, r.httpResponse.Body, maxBodySize) + + buffer, err := io.ReadAll(limitedReader) + if err != nil && err != io.EOF { + if err == io.ErrUnexpectedEOF { + return nil, locale.NewLocalizedErrorWrapper(fmt.Errorf("fetcher: response body too large: %w", err), "error.http_response_too_large") + } + + return nil, locale.NewLocalizedErrorWrapper(fmt.Errorf("fetcher: unable to read response body: %w", err), "error.http_body_read", err) + } + + if len(buffer) == 0 { + return nil, locale.NewLocalizedErrorWrapper(fmt.Errorf("fetcher: empty response body"), "error.http_empty_response_body") + } + + return buffer, nil +} + +func (r *ResponseHandler) LocalizedError() *locale.LocalizedErrorWrapper { + if r.clientErr != nil { + switch r.clientErr.(type) { + case x509.CertificateInvalidError, x509.UnknownAuthorityError, x509.HostnameError: + return locale.NewLocalizedErrorWrapper(fmt.Errorf("fetcher: %w", r.clientErr), "error.tls_error", r.clientErr.Error()) + case *net.OpError: + return locale.NewLocalizedErrorWrapper(fmt.Errorf("fetcher: %w", r.clientErr), "error.network_operation", r.clientErr.Error()) + case net.Error: + networkErr := r.clientErr.(net.Error) + if networkErr.Timeout() { + return locale.NewLocalizedErrorWrapper(fmt.Errorf("fetcher: %w", r.clientErr), "error.network_timeout", r.clientErr.Error()) + } + } + + if errors.Is(r.clientErr, io.EOF) { + return locale.NewLocalizedErrorWrapper(fmt.Errorf("fetcher: %w", r.clientErr), "error.http_empty_response") + } + + return locale.NewLocalizedErrorWrapper(fmt.Errorf("fetcher: %w", r.clientErr), "error.http_client_error", r.clientErr.Error()) + } + + switch r.httpResponse.StatusCode { + case http.StatusUnauthorized: + return locale.NewLocalizedErrorWrapper(fmt.Errorf("fetcher: access unauthorized (401 status code)"), "error.http_not_authorized") + case http.StatusForbidden: + return locale.NewLocalizedErrorWrapper(fmt.Errorf("fetcher: access forbidden (403 status code)"), "error.http_forbidden") + case http.StatusTooManyRequests: + return locale.NewLocalizedErrorWrapper(fmt.Errorf("fetcher: too many requests (429 status code)"), "error.http_too_many_requests") + case http.StatusNotFound, http.StatusGone: + return locale.NewLocalizedErrorWrapper(fmt.Errorf("fetcher: resource not found (%d status code)", r.httpResponse.StatusCode), "error.http_resource_not_found") + case http.StatusInternalServerError: + return locale.NewLocalizedErrorWrapper(fmt.Errorf("fetcher: remote server error (%d status code)", r.httpResponse.StatusCode), "error.http_internal_server_error") + case http.StatusBadGateway: + return locale.NewLocalizedErrorWrapper(fmt.Errorf("fetcher: bad gateway (%d status code)", r.httpResponse.StatusCode), "error.http_bad_gateway") + case http.StatusServiceUnavailable: + return locale.NewLocalizedErrorWrapper(fmt.Errorf("fetcher: service unavailable (%d status code)", r.httpResponse.StatusCode), "error.http_service_unavailable") + case http.StatusGatewayTimeout: + return locale.NewLocalizedErrorWrapper(fmt.Errorf("fetcher: gateway timeout (%d status code)", r.httpResponse.StatusCode), "error.http_gateway_timeout") + } + + if r.httpResponse.StatusCode >= 400 { + return locale.NewLocalizedErrorWrapper(fmt.Errorf("fetcher: unexpected status code (%d status code)", r.httpResponse.StatusCode), "error.http_unexpected_status_code", r.httpResponse.StatusCode) + } + + if r.httpResponse.StatusCode != 304 { + // Content-Length = -1 when no Content-Length header is sent. + if r.httpResponse.ContentLength == 0 { + return locale.NewLocalizedErrorWrapper(fmt.Errorf("fetcher: empty response body"), "error.http_empty_response_body") + } + } + + return nil +} diff --git a/internal/reader/handler/handler.go b/internal/reader/handler/handler.go index cfd03ce1..fa38e4cf 100644 --- a/internal/reader/handler/handler.go +++ b/internal/reader/handler/handler.go @@ -4,16 +4,15 @@ package handler // import "miniflux.app/v2/internal/reader/handler" import ( + "errors" "log/slog" "time" "miniflux.app/v2/internal/config" - "miniflux.app/v2/internal/errors" - "miniflux.app/v2/internal/http/client" "miniflux.app/v2/internal/integration" "miniflux.app/v2/internal/locale" "miniflux.app/v2/internal/model" - "miniflux.app/v2/internal/reader/browser" + "miniflux.app/v2/internal/reader/fetcher" "miniflux.app/v2/internal/reader/icon" "miniflux.app/v2/internal/reader/parser" "miniflux.app/v2/internal/reader/processor" @@ -21,13 +20,13 @@ import ( ) var ( - errDuplicate = "This feed already exists (%s)" - errNotFound = "Feed %d not found" - errCategoryNotFound = "Category not found for this user" + ErrCategoryNotFound = errors.New("fetcher: category not found") + ErrFeedNotFound = errors.New("fetcher: feed not found") + ErrDuplicatedFeed = errors.New("fetcher: duplicated feed") ) // CreateFeed fetch, parse and store a new feed. -func CreateFeed(store *storage.Storage, userID int64, feedCreationRequest *model.FeedCreationRequest) (*model.Feed, error) { +func CreateFeed(store *storage.Storage, userID int64, feedCreationRequest *model.FeedCreationRequest) (*model.Feed, *locale.LocalizedErrorWrapper) { slog.Debug("Begin feed creation process", slog.Int64("user_id", userID), slog.String("feed_url", feedCreationRequest.FeedURL), @@ -35,35 +34,43 @@ func CreateFeed(store *storage.Storage, userID int64, feedCreationRequest *model user, storeErr := store.UserByID(userID) if storeErr != nil { - return nil, storeErr + return nil, locale.NewLocalizedErrorWrapper(storeErr, "error.database_error", storeErr) } if !store.CategoryIDExists(userID, feedCreationRequest.CategoryID) { - return nil, errors.NewLocalizedError(errCategoryNotFound) + return nil, locale.NewLocalizedErrorWrapper(ErrCategoryNotFound, "error.category_not_found") } - request := client.NewClientWithConfig(feedCreationRequest.FeedURL, config.Opts) - request.WithCredentials(feedCreationRequest.Username, feedCreationRequest.Password) - request.WithUserAgent(feedCreationRequest.UserAgent) - request.WithCookie(feedCreationRequest.Cookie) - request.AllowSelfSignedCertificates = feedCreationRequest.AllowSelfSignedCertificates + requestBuilder := fetcher.NewRequestBuilder() + requestBuilder.WithUsernameAndPassword(feedCreationRequest.Username, feedCreationRequest.Password) + requestBuilder.WithUserAgent(feedCreationRequest.UserAgent) + requestBuilder.WithCookie(feedCreationRequest.Cookie) + requestBuilder.WithTimeout(config.Opts.HTTPClientTimeout()) + requestBuilder.WithProxy(config.Opts.HTTPClientProxy()) + requestBuilder.UseProxy(feedCreationRequest.FetchViaProxy) + requestBuilder.IgnoreTLSErrors(feedCreationRequest.AllowSelfSignedCertificates) - if feedCreationRequest.FetchViaProxy { - request.WithProxy() + responseHandler := fetcher.NewResponseHandler(requestBuilder.ExecuteRequest(feedCreationRequest.FeedURL)) + defer responseHandler.Close() + + if localizedError := responseHandler.LocalizedError(); localizedError != nil { + slog.Warn("Unable to fetch feed", slog.String("feed_url", feedCreationRequest.FeedURL), slog.Any("error", localizedError.Error())) + return nil, localizedError } - response, requestErr := browser.Exec(request) - if requestErr != nil { - return nil, requestErr + responseBody, localizedError := responseHandler.ReadBody(config.Opts.HTTPClientMaxBodySize()) + if localizedError != nil { + slog.Warn("Unable to fetch feed", slog.String("feed_url", feedCreationRequest.FeedURL), slog.Any("error", localizedError.Error())) + return nil, localizedError } - if store.FeedURLExists(userID, response.EffectiveURL) { - return nil, errors.NewLocalizedError(errDuplicate, response.EffectiveURL) + if store.FeedURLExists(userID, responseHandler.EffectiveURL()) { + return nil, locale.NewLocalizedErrorWrapper(ErrDuplicatedFeed, "error.duplicated_feed") } - subscription, parseErr := parser.ParseFeed(response.EffectiveURL, response.BodyAsString()) + subscription, parseErr := parser.ParseFeed(responseHandler.EffectiveURL(), string(responseBody)) if parseErr != nil { - return nil, parseErr + return nil, locale.NewLocalizedErrorWrapper(parseErr, "error.unable_to_parse_feed", parseErr) } subscription.UserID = userID @@ -81,14 +88,16 @@ func CreateFeed(store *storage.Storage, userID int64, feedCreationRequest *model subscription.BlocklistRules = feedCreationRequest.BlocklistRules subscription.KeeplistRules = feedCreationRequest.KeeplistRules subscription.UrlRewriteRules = feedCreationRequest.UrlRewriteRules + subscription.EtagHeader = responseHandler.ETag() + subscription.LastModifiedHeader = responseHandler.LastModified() + subscription.FeedURL = responseHandler.EffectiveURL() subscription.WithCategoryID(feedCreationRequest.CategoryID) - subscription.WithClientResponse(response) subscription.CheckedNow() processor.ProcessFeedEntries(store, subscription, user, true) if storeErr := store.CreateFeed(subscription); storeErr != nil { - return nil, storeErr + return nil, locale.NewLocalizedErrorWrapper(storeErr, "error.database_error", storeErr) } slog.Debug("Created feed", @@ -99,18 +108,16 @@ func CreateFeed(store *storage.Storage, userID int64, feedCreationRequest *model checkFeedIcon( store, + requestBuilder, subscription.ID, subscription.SiteURL, subscription.IconURL, - feedCreationRequest.UserAgent, - feedCreationRequest.FetchViaProxy, - feedCreationRequest.AllowSelfSignedCertificates, ) return subscription, nil } // RefreshFeed refreshes a feed. -func RefreshFeed(store *storage.Storage, userID, feedID int64, forceRefresh bool) error { +func RefreshFeed(store *storage.Storage, userID, feedID int64, forceRefresh bool) *locale.LocalizedErrorWrapper { slog.Debug("Begin feed refresh process", slog.Int64("user_id", userID), slog.Int64("feed_id", feedID), @@ -119,18 +126,16 @@ func RefreshFeed(store *storage.Storage, userID, feedID int64, forceRefresh bool user, storeErr := store.UserByID(userID) if storeErr != nil { - return storeErr + return locale.NewLocalizedErrorWrapper(storeErr, "error.database_error", storeErr) } - printer := locale.NewPrinter(user.Language) - originalFeed, storeErr := store.FeedByID(userID, feedID) if storeErr != nil { - return storeErr + return locale.NewLocalizedErrorWrapper(storeErr, "error.database_error", storeErr) } if originalFeed == nil { - return errors.NewLocalizedError(errNotFound, feedID) + return locale.NewLocalizedErrorWrapper(ErrFeedNotFound, "error.feed_not_found") } weeklyEntryCount := 0 @@ -138,52 +143,62 @@ func RefreshFeed(store *storage.Storage, userID, feedID int64, forceRefresh bool var weeklyCountErr error weeklyEntryCount, weeklyCountErr = store.WeeklyFeedEntryCount(userID, feedID) if weeklyCountErr != nil { - return weeklyCountErr + return locale.NewLocalizedErrorWrapper(weeklyCountErr, "error.database_error", weeklyCountErr) } } originalFeed.CheckedNow() originalFeed.ScheduleNextCheck(weeklyEntryCount) - request := client.NewClientWithConfig(originalFeed.FeedURL, config.Opts) - request.WithCredentials(originalFeed.Username, originalFeed.Password) - request.WithUserAgent(originalFeed.UserAgent) - request.WithCookie(originalFeed.Cookie) - request.AllowSelfSignedCertificates = originalFeed.AllowSelfSignedCertificates + requestBuilder := fetcher.NewRequestBuilder() + requestBuilder.WithUsernameAndPassword(originalFeed.Username, originalFeed.Password) + requestBuilder.WithUserAgent(originalFeed.UserAgent) + requestBuilder.WithCookie(originalFeed.Cookie) + requestBuilder.WithTimeout(config.Opts.HTTPClientTimeout()) + requestBuilder.WithProxy(config.Opts.HTTPClientProxy()) + requestBuilder.UseProxy(originalFeed.FetchViaProxy) + requestBuilder.IgnoreTLSErrors(originalFeed.AllowSelfSignedCertificates) - if !originalFeed.IgnoreHTTPCache { - request.WithCacheHeaders(originalFeed.EtagHeader, originalFeed.LastModifiedHeader) - } + responseHandler := fetcher.NewResponseHandler(requestBuilder.ExecuteRequest(originalFeed.FeedURL)) + defer responseHandler.Close() - if originalFeed.FetchViaProxy { - request.WithProxy() - } - - response, requestErr := browser.Exec(request) - if requestErr != nil { - originalFeed.WithError(requestErr.Localize(printer)) + if localizedError := responseHandler.LocalizedError(); localizedError != nil { + slog.Warn("Unable to fetch feed", slog.String("feed_url", originalFeed.FeedURL), slog.Any("error", localizedError.Error())) + originalFeed.WithTranslatedErrorMessage(localizedError.Translate(user.Language)) store.UpdateFeedError(originalFeed) - return requestErr + return localizedError } - if store.AnotherFeedURLExists(userID, originalFeed.ID, response.EffectiveURL) { - storeErr := errors.NewLocalizedError(errDuplicate, response.EffectiveURL) - originalFeed.WithError(storeErr.Error()) + if store.AnotherFeedURLExists(userID, originalFeed.ID, responseHandler.EffectiveURL()) { + localizedError := locale.NewLocalizedErrorWrapper(ErrDuplicatedFeed, "error.duplicated_feed") + originalFeed.WithTranslatedErrorMessage(localizedError.Translate(user.Language)) store.UpdateFeedError(originalFeed) - return storeErr + return localizedError } - if originalFeed.IgnoreHTTPCache || response.IsModified(originalFeed.EtagHeader, originalFeed.LastModifiedHeader) { + if originalFeed.IgnoreHTTPCache || responseHandler.IsModified(originalFeed.EtagHeader, originalFeed.LastModifiedHeader) { slog.Debug("Feed modified", slog.Int64("user_id", userID), slog.Int64("feed_id", feedID), ) - updatedFeed, parseErr := parser.ParseFeed(response.EffectiveURL, response.BodyAsString()) + responseBody, localizedError := responseHandler.ReadBody(config.Opts.HTTPClientMaxBodySize()) + if localizedError != nil { + slog.Warn("Unable to fetch feed", slog.String("feed_url", originalFeed.FeedURL), slog.Any("error", localizedError.Error())) + return localizedError + } + + updatedFeed, parseErr := parser.ParseFeed(responseHandler.EffectiveURL(), string(responseBody)) if parseErr != nil { - originalFeed.WithError(parseErr.Localize(printer)) + localizedError := locale.NewLocalizedErrorWrapper(parseErr, "error.unable_to_parse_feed") + + if errors.Is(parseErr, parser.ErrFeedFormatNotDetected) { + localizedError = locale.NewLocalizedErrorWrapper(parseErr, "error.feed_format_not_detected", parseErr) + } + + originalFeed.WithTranslatedErrorMessage(localizedError.Translate(user.Language)) store.UpdateFeedError(originalFeed) - return parseErr + return localizedError } // If the feed has a TTL defined, we use it to make sure we don't check it too often. @@ -215,9 +230,10 @@ func RefreshFeed(store *storage.Storage, userID, feedID int64, forceRefresh bool updateExistingEntries := forceRefresh || !originalFeed.Crawler newEntries, storeErr := store.RefreshFeedEntries(originalFeed.UserID, originalFeed.ID, originalFeed.Entries, updateExistingEntries) if storeErr != nil { - originalFeed.WithError(storeErr.Error()) + localizedError := locale.NewLocalizedErrorWrapper(storeErr, "error.database_error", storeErr) + originalFeed.WithTranslatedErrorMessage(localizedError.Translate(user.Language)) store.UpdateFeedError(originalFeed) - return storeErr + return localizedError } userIntegrations, intErr := store.Integration(userID) @@ -233,16 +249,15 @@ func RefreshFeed(store *storage.Storage, userID, feedID int64, forceRefresh bool // We update caching headers only if the feed has been modified, // because some websites don't return the same headers when replying with a 304. - originalFeed.WithClientResponse(response) + originalFeed.EtagHeader = responseHandler.ETag() + originalFeed.LastModifiedHeader = responseHandler.LastModified() checkFeedIcon( store, + requestBuilder, originalFeed.ID, originalFeed.SiteURL, updatedFeed.IconURL, - originalFeed.UserAgent, - originalFeed.FetchViaProxy, - originalFeed.AllowSelfSignedCertificates, ) } else { slog.Debug("Feed not modified", @@ -254,17 +269,18 @@ func RefreshFeed(store *storage.Storage, userID, feedID int64, forceRefresh bool originalFeed.ResetErrorCounter() if storeErr := store.UpdateFeed(originalFeed); storeErr != nil { - originalFeed.WithError(storeErr.Error()) + localizedError := locale.NewLocalizedErrorWrapper(storeErr, "error.database_error", storeErr) + originalFeed.WithTranslatedErrorMessage(localizedError.Translate(user.Language)) store.UpdateFeedError(originalFeed) - return storeErr + return localizedError } return nil } -func checkFeedIcon(store *storage.Storage, feedID int64, websiteURL, feedIconURL, userAgent string, fetchViaProxy, allowSelfSignedCertificates bool) { +func checkFeedIcon(store *storage.Storage, requestBuilder *fetcher.RequestBuilder, feedID int64, websiteURL, feedIconURL string) { if !store.HasIcon(feedID) { - iconFinder := icon.NewIconFinder(websiteURL, feedIconURL, userAgent, fetchViaProxy, allowSelfSignedCertificates) + iconFinder := icon.NewIconFinder(requestBuilder, websiteURL, feedIconURL) if icon, err := iconFinder.FindIcon(); err != nil { slog.Debug("Unable to find feed icon", slog.Int64("feed_id", feedID), diff --git a/internal/reader/icon/finder.go b/internal/reader/icon/finder.go index 37a5e18d..91a74d14 100644 --- a/internal/reader/icon/finder.go +++ b/internal/reader/icon/finder.go @@ -13,28 +13,24 @@ import ( "miniflux.app/v2/internal/config" "miniflux.app/v2/internal/crypto" - "miniflux.app/v2/internal/http/client" "miniflux.app/v2/internal/model" + "miniflux.app/v2/internal/reader/fetcher" "miniflux.app/v2/internal/urllib" "github.com/PuerkitoBio/goquery" ) type IconFinder struct { - websiteURL string - feedIconURL string - userAgent string - fetchViaProxy bool - allowSelfSignedCertificates bool + requestBuilder *fetcher.RequestBuilder + websiteURL string + feedIconURL string } -func NewIconFinder(websiteURL, feedIconURL, userAgent string, fetchViaProxy, allowSelfSignedCertificates bool) *IconFinder { +func NewIconFinder(requestBuilder *fetcher.RequestBuilder, websiteURL, feedIconURL string) *IconFinder { return &IconFinder{ - websiteURL: websiteURL, - feedIconURL: feedIconURL, - userAgent: userAgent, - fetchViaProxy: fetchViaProxy, - allowSelfSignedCertificates: allowSelfSignedCertificates, + requestBuilder: requestBuilder, + websiteURL: websiteURL, + feedIconURL: feedIconURL, } } @@ -105,12 +101,16 @@ func (f *IconFinder) FetchIconsFromHTMLDocument() (*model.Icon, error) { slog.String("website_url", f.websiteURL), ) - documentBody, err := f.FetchRootDocument() - if err != nil { - return nil, err + rootURL := urllib.RootURL(f.websiteURL) + + responseHandler := fetcher.NewResponseHandler(f.requestBuilder.ExecuteRequest(rootURL)) + defer responseHandler.Close() + + if localizedError := responseHandler.LocalizedError(); localizedError != nil { + return nil, fmt.Errorf("icon: unable to download website index page: %w", localizedError.Error()) } - iconURLs, err := findIconURLsFromHTMLDocument(documentBody) + iconURLs, err := findIconURLsFromHTMLDocument(responseHandler.Body(config.Opts.HTTPClientMaxBodySize())) if err != nil { return nil, err } @@ -151,64 +151,28 @@ func (f *IconFinder) FetchIconsFromHTMLDocument() (*model.Icon, error) { return nil, nil } -func (f *IconFinder) FetchRootDocument() (io.Reader, error) { - rootURL := urllib.RootURL(f.websiteURL) - - clt := client.NewClientWithConfig(rootURL, config.Opts) - clt.WithUserAgent(f.userAgent) - clt.AllowSelfSignedCertificates = f.allowSelfSignedCertificates - - if f.fetchViaProxy { - clt.WithProxy() - } - - response, err := clt.Get() - if err != nil { - return nil, fmt.Errorf("icon: unable to download website index page: %v", err) - } - - if response.HasServerFailure() { - return nil, fmt.Errorf("icon: unable to download website index page: status=%d", response.StatusCode) - } - - return response.Body, nil -} - func (f *IconFinder) DownloadIcon(iconURL string) (*model.Icon, error) { slog.Debug("Downloading icon", slog.String("website_url", f.websiteURL), slog.String("icon_url", iconURL), ) - clt := client.NewClientWithConfig(iconURL, config.Opts) - clt.WithUserAgent(f.userAgent) - clt.AllowSelfSignedCertificates = f.allowSelfSignedCertificates - if f.fetchViaProxy { - clt.WithProxy() + responseHandler := fetcher.NewResponseHandler(f.requestBuilder.ExecuteRequest(iconURL)) + defer responseHandler.Close() + + if localizedError := responseHandler.LocalizedError(); localizedError != nil { + return nil, fmt.Errorf("icon: unable to download website icon: %w", localizedError.Error()) } - response, err := clt.Get() - if err != nil { - return nil, fmt.Errorf("icon: unable to download icon %s: %v", iconURL, err) - } - - if response.HasServerFailure() { - return nil, fmt.Errorf("icon: unable to download icon %s: status=%d", iconURL, response.StatusCode) - } - - body, err := io.ReadAll(response.Body) - if err != nil { - return nil, fmt.Errorf("icon: unable to read downloaded icon from %s: %v", iconURL, err) - } - - if len(body) == 0 { - return nil, fmt.Errorf("icon: downloaded icon is empty, iconURL=%s", iconURL) + responseBody, localizedError := responseHandler.ReadBody(config.Opts.HTTPClientMaxBodySize()) + if localizedError != nil { + return nil, fmt.Errorf("icon: unable to read response body: %w", localizedError.Error()) } icon := &model.Icon{ - Hash: crypto.HashFromBytes(body), - MimeType: response.ContentType, - Content: body, + Hash: crypto.HashFromBytes(responseBody), + MimeType: responseHandler.ContentType(), + Content: responseBody, } return icon, nil diff --git a/internal/reader/json/parser.go b/internal/reader/json/parser.go index 09963e83..ee0f634d 100644 --- a/internal/reader/json/parser.go +++ b/internal/reader/json/parser.go @@ -5,18 +5,17 @@ package json // import "miniflux.app/v2/internal/reader/json" import ( "encoding/json" + "fmt" "io" - "miniflux.app/v2/internal/errors" "miniflux.app/v2/internal/model" ) // Parse returns a normalized feed struct from a JSON feed. -func Parse(baseURL string, data io.Reader) (*model.Feed, *errors.LocalizedError) { +func Parse(baseURL string, data io.Reader) (*model.Feed, error) { feed := new(jsonFeed) - decoder := json.NewDecoder(data) - if err := decoder.Decode(&feed); err != nil { - return nil, errors.NewLocalizedError("Unable to parse JSON Feed: %q", err) + if err := json.NewDecoder(data).Decode(&feed); err != nil { + return nil, fmt.Errorf("json: unable to parse feed: %w", err) } return feed.Transform(baseURL), nil diff --git a/internal/reader/opml/parser.go b/internal/reader/opml/parser.go index 7dac0de5..5e3fd0d2 100644 --- a/internal/reader/opml/parser.go +++ b/internal/reader/opml/parser.go @@ -5,14 +5,14 @@ package opml // import "miniflux.app/v2/internal/reader/opml" import ( "encoding/xml" + "fmt" "io" - "miniflux.app/v2/internal/errors" "miniflux.app/v2/internal/reader/encoding" ) // Parse reads an OPML file and returns a SubcriptionList. -func Parse(data io.Reader) (SubcriptionList, *errors.LocalizedError) { +func Parse(data io.Reader) (SubcriptionList, error) { opmlDocument := NewOPMLDocument() decoder := xml.NewDecoder(data) decoder.Entity = xml.HTMLEntity @@ -21,7 +21,7 @@ func Parse(data io.Reader) (SubcriptionList, *errors.LocalizedError) { err := decoder.Decode(opmlDocument) if err != nil { - return nil, errors.NewLocalizedError("Unable to parse OPML file: %q", err) + return nil, fmt.Errorf("opml: unable to parse document: %w", err) } return getSubscriptionsFromOutlines(opmlDocument.Outlines, ""), nil diff --git a/internal/reader/parser/parser.go b/internal/reader/parser/parser.go index c87ac844..60b194d4 100644 --- a/internal/reader/parser/parser.go +++ b/internal/reader/parser/parser.go @@ -4,9 +4,9 @@ package parser // import "miniflux.app/v2/internal/reader/parser" import ( + "errors" "strings" - "miniflux.app/v2/internal/errors" "miniflux.app/v2/internal/model" "miniflux.app/v2/internal/reader/atom" "miniflux.app/v2/internal/reader/json" @@ -14,8 +14,10 @@ import ( "miniflux.app/v2/internal/reader/rss" ) +var ErrFeedFormatNotDetected = errors.New("parser: unable to detect feed format") + // ParseFeed analyzes the input data and returns a normalized feed object. -func ParseFeed(baseURL, data string) (*model.Feed, *errors.LocalizedError) { +func ParseFeed(baseURL, data string) (*model.Feed, error) { switch DetectFeedFormat(data) { case FormatAtom: return atom.Parse(baseURL, strings.NewReader(data)) @@ -26,6 +28,6 @@ func ParseFeed(baseURL, data string) (*model.Feed, *errors.LocalizedError) { case FormatRDF: return rdf.Parse(baseURL, strings.NewReader(data)) default: - return nil, errors.NewLocalizedError("Unsupported feed format") + return nil, ErrFeedFormatNotDetected } } diff --git a/internal/reader/parser/parser_test.go b/internal/reader/parser/parser_test.go index 81ddc665..cd0a3213 100644 --- a/internal/reader/parser/parser_test.go +++ b/internal/reader/parser/parser_test.go @@ -4,11 +4,7 @@ package parser // import "miniflux.app/v2/internal/reader/parser" import ( - "bytes" - "os" "testing" - - "miniflux.app/v2/internal/http/client" ) func TestParseAtom(t *testing.T) { @@ -301,50 +297,3 @@ func TestParseEmptyFeed(t *testing.T) { t.Error("ParseFeed must returns an error") } } - -func TestDifferentEncodingWithResponse(t *testing.T) { - var unicodeTestCases = []struct { - filename, contentType string - index int - title string - }{ - // Arabic language encoded in UTF-8. - {"urdu_UTF8.xml", "text/xml; charset=utf-8", 0, "امریکی عسکری امداد کی بندش کی وجوہات: انڈیا سے جنگ، جوہری پروگرام اور اب دہشت گردوں کی پشت پناہی"}, - - // Windows-1251 encoding and not charset in HTTP header. - {"encoding_WINDOWS-1251.xml", "text/xml", 0, "Цитата #17703"}, - - // No encoding in XML, but defined in HTTP Content-Type header. - {"no_encoding_ISO-8859-1.xml", "application/xml; charset=ISO-8859-1", 2, "La criminalité liée surtout à... l'ennui ?"}, - - // ISO-8859-1 encoding defined in XML and HTTP header. - {"encoding_ISO-8859-1.xml", "application/rss+xml; charset=ISO-8859-1", 5, "Projekt Jedi: Microsoft will weiter mit US-Militär zusammenarbeiten"}, - - // UTF-8 encoding defined in RDF document and HTTP header. - {"rdf_UTF8.xml", "application/rss+xml; charset=utf-8", 1, "Mega-Deal: IBM übernimmt Red Hat"}, - - // UTF-8 encoding defined only in RDF document. - {"rdf_UTF8.xml", "application/rss+xml", 1, "Mega-Deal: IBM übernimmt Red Hat"}, - } - - for _, tc := range unicodeTestCases { - content, err := os.ReadFile("testdata/" + tc.filename) - if err != nil { - t.Fatalf(`Unable to read file %q: %v`, tc.filename, err) - } - - r := &client.Response{Body: bytes.NewReader(content), ContentType: tc.contentType} - if encodingErr := r.EnsureUnicodeBody(); encodingErr != nil { - t.Fatalf(`Encoding error for %q: %v`, tc.filename, encodingErr) - } - - feed, parseErr := ParseFeed("https://example.org/", r.BodyAsString()) - if parseErr != nil { - t.Fatalf(`Parsing error for %q - %q: %v`, tc.filename, tc.contentType, parseErr) - } - - if feed.Entries[tc.index].Title != tc.title { - t.Errorf(`Unexpected title, got %q instead of %q`, feed.Entries[tc.index].Title, tc.title) - } - } -} diff --git a/internal/reader/processor/processor.go b/internal/reader/processor/processor.go index 2fa85a7c..6b9af305 100644 --- a/internal/reader/processor/processor.go +++ b/internal/reader/processor/processor.go @@ -12,10 +12,9 @@ import ( "time" "miniflux.app/v2/internal/config" - "miniflux.app/v2/internal/http/client" "miniflux.app/v2/internal/metric" "miniflux.app/v2/internal/model" - "miniflux.app/v2/internal/reader/browser" + "miniflux.app/v2/internal/reader/fetcher" "miniflux.app/v2/internal/reader/readingtime" "miniflux.app/v2/internal/reader/rewrite" "miniflux.app/v2/internal/reader/sanitizer" @@ -52,7 +51,7 @@ func ProcessFeedEntries(store *storage.Storage, feed *model.Feed, user *model.Us continue } - url := getUrlFromEntry(feed, entry) + websiteURL := getUrlFromEntry(feed, entry) entryIsNew := !store.EntryURLExists(feed.ID, entry.URL) if feed.Crawler && (entryIsNew || forceRefresh) { slog.Debug("Scraping entry", @@ -64,13 +63,19 @@ func ProcessFeedEntries(store *storage.Storage, feed *model.Feed, user *model.Us ) startTime := time.Now() - content, scraperErr := scraper.Fetch( - url, + + requestBuilder := fetcher.NewRequestBuilder() + requestBuilder.WithUserAgent(feed.UserAgent) + requestBuilder.WithCookie(feed.Cookie) + requestBuilder.WithTimeout(config.Opts.HTTPClientTimeout()) + requestBuilder.WithProxy(config.Opts.HTTPClientProxy()) + requestBuilder.UseProxy(feed.FetchViaProxy) + requestBuilder.IgnoreTLSErrors(feed.AllowSelfSignedCertificates) + + content, scraperErr := scraper.ScrapeWebsite( + requestBuilder, + websiteURL, feed.ScraperRules, - feed.UserAgent, - feed.Cookie, - feed.AllowSelfSignedCertificates, - feed.FetchViaProxy, ) if config.Opts.HasMetricsCollector() { @@ -96,10 +101,10 @@ func ProcessFeedEntries(store *storage.Storage, feed *model.Feed, user *model.Us } } - rewrite.Rewriter(url, entry, feed.RewriteRules) + rewrite.Rewriter(websiteURL, entry, feed.RewriteRules) // The sanitizer should always run at the end of the process to make sure unsafe HTML is filtered. - entry.Content = sanitizer.Sanitize(url, entry.Content) + entry.Content = sanitizer.Sanitize(websiteURL, entry.Content) updateEntryReadingTime(store, feed, entry, entryIsNew, user) filteredEntries = append(filteredEntries, entry) @@ -146,15 +151,20 @@ func isAllowedEntry(feed *model.Feed, entry *model.Entry) bool { // ProcessEntryWebPage downloads the entry web page and apply rewrite rules. func ProcessEntryWebPage(feed *model.Feed, entry *model.Entry, user *model.User) error { startTime := time.Now() - url := getUrlFromEntry(feed, entry) + websiteURL := getUrlFromEntry(feed, entry) - content, scraperErr := scraper.Fetch( - url, - entry.Feed.ScraperRules, - entry.Feed.UserAgent, - entry.Feed.Cookie, - feed.AllowSelfSignedCertificates, - feed.FetchViaProxy, + requestBuilder := fetcher.NewRequestBuilder() + requestBuilder.WithUserAgent(feed.UserAgent) + requestBuilder.WithCookie(feed.Cookie) + requestBuilder.WithTimeout(config.Opts.HTTPClientTimeout()) + requestBuilder.WithProxy(config.Opts.HTTPClientProxy()) + requestBuilder.UseProxy(feed.FetchViaProxy) + requestBuilder.IgnoreTLSErrors(feed.AllowSelfSignedCertificates) + + content, scraperErr := scraper.ScrapeWebsite( + requestBuilder, + websiteURL, + feed.ScraperRules, ) if config.Opts.HasMetricsCollector() { @@ -174,8 +184,8 @@ func ProcessEntryWebPage(feed *model.Feed, entry *model.Entry, user *model.User) entry.ReadingTime = readingtime.EstimateReadingTime(entry.Content, user.DefaultReadingSpeed, user.CJKReadingSpeed) } - rewrite.Rewriter(url, entry, entry.Feed.RewriteRules) - entry.Content = sanitizer.Sanitize(url, entry.Content) + rewrite.Rewriter(websiteURL, entry, entry.Feed.RewriteRules) + entry.Content = sanitizer.Sanitize(websiteURL, entry.Content) return nil } @@ -270,14 +280,20 @@ func shouldFetchOdyseeWatchTime(entry *model.Entry) bool { return matches != nil } -func fetchYouTubeWatchTime(url string) (int, error) { - clt := client.NewClientWithConfig(url, config.Opts) - response, browserErr := browser.Exec(clt) - if browserErr != nil { - return 0, browserErr +func fetchYouTubeWatchTime(websiteURL string) (int, error) { + requestBuilder := fetcher.NewRequestBuilder() + requestBuilder.WithTimeout(config.Opts.HTTPClientTimeout()) + requestBuilder.WithProxy(config.Opts.HTTPClientProxy()) + + responseHandler := fetcher.NewResponseHandler(requestBuilder.ExecuteRequest(websiteURL)) + defer responseHandler.Close() + + if localizedError := responseHandler.LocalizedError(); localizedError != nil { + slog.Warn("Unable to fetch YouTube page", slog.String("website_url", websiteURL), slog.Any("error", localizedError.Error())) + return 0, localizedError.Error() } - doc, docErr := goquery.NewDocumentFromReader(response.Body) + doc, docErr := goquery.NewDocumentFromReader(responseHandler.Body(config.Opts.HTTPClientMaxBodySize())) if docErr != nil { return 0, docErr } @@ -295,14 +311,20 @@ func fetchYouTubeWatchTime(url string) (int, error) { return int(dur.Minutes()), nil } -func fetchOdyseeWatchTime(url string) (int, error) { - clt := client.NewClientWithConfig(url, config.Opts) - response, browserErr := browser.Exec(clt) - if browserErr != nil { - return 0, browserErr +func fetchOdyseeWatchTime(websiteURL string) (int, error) { + requestBuilder := fetcher.NewRequestBuilder() + requestBuilder.WithTimeout(config.Opts.HTTPClientTimeout()) + requestBuilder.WithProxy(config.Opts.HTTPClientProxy()) + + responseHandler := fetcher.NewResponseHandler(requestBuilder.ExecuteRequest(websiteURL)) + defer responseHandler.Close() + + if localizedError := responseHandler.LocalizedError(); localizedError != nil { + slog.Warn("Unable to fetch Odysee watch time", slog.String("website_url", websiteURL), slog.Any("error", localizedError.Error())) + return 0, localizedError.Error() } - doc, docErr := goquery.NewDocumentFromReader(response.Body) + doc, docErr := goquery.NewDocumentFromReader(responseHandler.Body(config.Opts.HTTPClientMaxBodySize())) if docErr != nil { return 0, docErr } diff --git a/internal/reader/rdf/parser.go b/internal/reader/rdf/parser.go index 4c7fb556..1ce8b16b 100644 --- a/internal/reader/rdf/parser.go +++ b/internal/reader/rdf/parser.go @@ -4,20 +4,18 @@ package rdf // import "miniflux.app/v2/internal/reader/rdf" import ( + "fmt" "io" - "miniflux.app/v2/internal/errors" "miniflux.app/v2/internal/model" "miniflux.app/v2/internal/reader/xml" ) // Parse returns a normalized feed struct from a RDF feed. -func Parse(baseURL string, data io.Reader) (*model.Feed, *errors.LocalizedError) { +func Parse(baseURL string, data io.Reader) (*model.Feed, error) { feed := new(rdfFeed) - decoder := xml.NewDecoder(data) - err := decoder.Decode(feed) - if err != nil { - return nil, errors.NewLocalizedError("Unable to parse RDF feed: %q", err) + if err := xml.NewDecoder(data).Decode(feed); err != nil { + return nil, fmt.Errorf("rdf: unable to parse feed: %w", err) } return feed.Transform(baseURL), nil diff --git a/internal/reader/rss/parser.go b/internal/reader/rss/parser.go index 1e295534..90a48750 100644 --- a/internal/reader/rss/parser.go +++ b/internal/reader/rss/parser.go @@ -4,21 +4,18 @@ package rss // import "miniflux.app/v2/internal/reader/rss" import ( + "fmt" "io" - "miniflux.app/v2/internal/errors" "miniflux.app/v2/internal/model" "miniflux.app/v2/internal/reader/xml" ) // Parse returns a normalized feed struct from a RSS feed. -func Parse(baseURL string, data io.Reader) (*model.Feed, *errors.LocalizedError) { +func Parse(baseURL string, data io.Reader) (*model.Feed, error) { feed := new(rssFeed) - decoder := xml.NewDecoder(data) - err := decoder.Decode(feed) - if err != nil { - return nil, errors.NewLocalizedError("Unable to parse RSS feed: %q", err) + if err := xml.NewDecoder(data).Decode(feed); err != nil { + return nil, fmt.Errorf("rss: unable to parse feed: %w", err) } - return feed.Transform(baseURL), nil } diff --git a/internal/reader/scraper/scraper.go b/internal/reader/scraper/scraper.go index c74946c3..8508761f 100644 --- a/internal/reader/scraper/scraper.go +++ b/internal/reader/scraper/scraper.go @@ -4,67 +4,54 @@ package scraper // import "miniflux.app/v2/internal/reader/scraper" import ( - "errors" "fmt" "io" "log/slog" "strings" "miniflux.app/v2/internal/config" - "miniflux.app/v2/internal/http/client" + "miniflux.app/v2/internal/reader/fetcher" "miniflux.app/v2/internal/reader/readability" "miniflux.app/v2/internal/urllib" "github.com/PuerkitoBio/goquery" ) -// Fetch downloads a web page and returns relevant contents. -func Fetch(websiteURL, rules, userAgent string, cookie string, allowSelfSignedCertificates, useProxy bool) (string, error) { - clt := client.NewClientWithConfig(websiteURL, config.Opts) - clt.WithUserAgent(userAgent) - clt.WithCookie(cookie) - if useProxy { - clt.WithProxy() - } - clt.AllowSelfSignedCertificates = allowSelfSignedCertificates +func ScrapeWebsite(requestBuilder *fetcher.RequestBuilder, websiteURL, rules string) (string, error) { + responseHandler := fetcher.NewResponseHandler(requestBuilder.ExecuteRequest(websiteURL)) + defer responseHandler.Close() - response, err := clt.Get() - if err != nil { - return "", err + if localizedError := responseHandler.LocalizedError(); localizedError != nil { + slog.Warn("Unable to scrape website", slog.String("website_url", websiteURL), slog.Any("error", localizedError.Error())) + return "", localizedError.Error() } - if response.HasServerFailure() { - return "", errors.New("scraper: unable to download web page") - } - - if !isAllowedContentType(response.ContentType) { - return "", fmt.Errorf("scraper: this resource is not a HTML document (%s)", response.ContentType) - } - - if err = response.EnsureUnicodeBody(); err != nil { - return "", err + if !isAllowedContentType(responseHandler.ContentType()) { + return "", fmt.Errorf("scraper: this resource is not a HTML document (%s)", responseHandler.ContentType()) } // The entry URL could redirect somewhere else. - sameSite := urllib.Domain(websiteURL) == urllib.Domain(response.EffectiveURL) - websiteURL = response.EffectiveURL + sameSite := urllib.Domain(websiteURL) == urllib.Domain(responseHandler.EffectiveURL()) + websiteURL = responseHandler.EffectiveURL() if rules == "" { rules = getPredefinedScraperRules(websiteURL) } var content string + var err error + if sameSite && rules != "" { slog.Debug("Extracting content with custom rules", "url", websiteURL, "rules", rules, ) - content, err = scrapContent(response.Body, rules) + content, err = findContentUsingCustomRules(responseHandler.Body(config.Opts.HTTPClientMaxBodySize()), rules) } else { slog.Debug("Extracting content with readability", "url", websiteURL, ) - content, err = readability.ExtractContent(response.Body) + content, err = readability.ExtractContent(responseHandler.Body(config.Opts.HTTPClientMaxBodySize())) } if err != nil { @@ -74,7 +61,7 @@ func Fetch(websiteURL, rules, userAgent string, cookie string, allowSelfSignedCe return content, nil } -func scrapContent(page io.Reader, rules string) (string, error) { +func findContentUsingCustomRules(page io.Reader, rules string) (string, error) { document, err := goquery.NewDocumentFromReader(page) if err != nil { return "", err diff --git a/internal/reader/scraper/scraper_test.go b/internal/reader/scraper/scraper_test.go index ced32d5e..9ad1e080 100644 --- a/internal/reader/scraper/scraper_test.go +++ b/internal/reader/scraper/scraper_test.go @@ -58,7 +58,7 @@ func TestSelectorRules(t *testing.T) { t.Fatalf(`Unable to read file %q: %v`, filename, err) } - actualResult, err := scrapContent(bytes.NewReader(html), rule) + actualResult, err := findContentUsingCustomRules(bytes.NewReader(html), rule) if err != nil { t.Fatalf(`Scraping error for %q - %q: %v`, filename, rule, err) } diff --git a/internal/reader/subscription/finder.go b/internal/reader/subscription/finder.go index f20d272a..6455c214 100644 --- a/internal/reader/subscription/finder.go +++ b/internal/reader/subscription/finder.go @@ -4,16 +4,16 @@ package subscription // import "miniflux.app/v2/internal/reader/subscription" import ( + "bytes" "fmt" "io" + "log/slog" "regexp" - "strings" "miniflux.app/v2/internal/config" - "miniflux.app/v2/internal/errors" - "miniflux.app/v2/internal/http/client" "miniflux.app/v2/internal/integration/rssbridge" - "miniflux.app/v2/internal/reader/browser" + "miniflux.app/v2/internal/locale" + "miniflux.app/v2/internal/reader/fetcher" "miniflux.app/v2/internal/reader/parser" "miniflux.app/v2/internal/urllib" @@ -21,18 +21,70 @@ import ( ) var ( - errUnreadableDoc = "Unable to analyze this page: %v" youtubeChannelRegex = regexp.MustCompile(`youtube\.com/channel/(.*)`) youtubeVideoRegex = regexp.MustCompile(`youtube\.com/watch\?v=(.*)`) ) -// FindSubscriptions downloads and try to find one or more subscriptions from an URL. -func FindSubscriptions(websiteURL, userAgent, cookie, username, password string, fetchViaProxy, allowSelfSignedCertificates bool, rssbridgeURL string) (Subscriptions, *errors.LocalizedError) { +func FindSubscriptions(websiteURL, userAgent, cookie, username, password string, fetchViaProxy, allowSelfSignedCertificates bool, rssbridgeURL string) (Subscriptions, *locale.LocalizedErrorWrapper) { + websiteURL = findYoutubeChannelFeed(websiteURL) + websiteURL = parseYoutubeVideoPage(websiteURL) + + requestBuilder := fetcher.NewRequestBuilder() + requestBuilder.WithUsernameAndPassword(username, password) + requestBuilder.WithUserAgent(userAgent) + requestBuilder.WithCookie(cookie) + requestBuilder.WithTimeout(config.Opts.HTTPClientTimeout()) + requestBuilder.WithProxy(config.Opts.HTTPClientProxy()) + requestBuilder.UseProxy(fetchViaProxy) + requestBuilder.IgnoreTLSErrors(allowSelfSignedCertificates) + + responseHandler := fetcher.NewResponseHandler(requestBuilder.ExecuteRequest(websiteURL)) + defer responseHandler.Close() + + if localizedError := responseHandler.LocalizedError(); localizedError != nil { + slog.Warn("Unable to find subscriptions", slog.String("website_url", websiteURL), slog.Any("error", localizedError.Error())) + return nil, localizedError + } + + responseBody, localizedError := responseHandler.ReadBody(config.Opts.HTTPClientMaxBodySize()) + if localizedError != nil { + slog.Warn("Unable to find subscriptions", slog.String("website_url", websiteURL), slog.Any("error", localizedError.Error())) + return nil, localizedError + } + + if format := parser.DetectFeedFormat(string(responseBody)); format != parser.FormatUnknown { + var subscriptions Subscriptions + subscriptions = append(subscriptions, &Subscription{ + Title: responseHandler.EffectiveURL(), + URL: responseHandler.EffectiveURL(), + Type: format, + }) + + return subscriptions, nil + } + + subscriptions, localizedError := parseWebPage(responseHandler.EffectiveURL(), bytes.NewReader(responseBody)) + if localizedError != nil || subscriptions != nil { + return subscriptions, localizedError + } + if rssbridgeURL != "" { + slog.Debug("Trying to detect feeds using RSS-Bridge", + slog.String("website_url", websiteURL), + slog.String("rssbridge_url", rssbridgeURL), + ) + bridges, err := rssbridge.DetectBridges(rssbridgeURL, websiteURL) if err != nil { - return nil, errors.NewLocalizedError("RSS-Bridge: %v", err) + return nil, locale.NewLocalizedErrorWrapper(err, "error.unable_to_detect_rssbridge", err) } + + slog.Debug("RSS-Bridge results", + slog.String("website_url", websiteURL), + slog.String("rssbridge_url", rssbridgeURL), + slog.Int("nb_bridges", len(bridges)), + ) + if len(bridges) > 0 { var subscriptions Subscriptions for _, bridge := range bridges { @@ -46,45 +98,10 @@ func FindSubscriptions(websiteURL, userAgent, cookie, username, password string, } } - websiteURL = findYoutubeChannelFeed(websiteURL) - websiteURL = parseYoutubeVideoPage(websiteURL) - - clt := client.NewClientWithConfig(websiteURL, config.Opts) - clt.WithCredentials(username, password) - clt.WithUserAgent(userAgent) - clt.WithCookie(cookie) - clt.AllowSelfSignedCertificates = allowSelfSignedCertificates - - if fetchViaProxy { - clt.WithProxy() - } - - response, err := browser.Exec(clt) - if err != nil { - return nil, err - } - - body := response.BodyAsString() - if format := parser.DetectFeedFormat(body); format != parser.FormatUnknown { - var subscriptions Subscriptions - subscriptions = append(subscriptions, &Subscription{ - Title: response.EffectiveURL, - URL: response.EffectiveURL, - Type: format, - }) - - return subscriptions, nil - } - - subscriptions, err := parseWebPage(response.EffectiveURL, strings.NewReader(body)) - if err != nil || subscriptions != nil { - return subscriptions, err - } - - return tryWellKnownUrls(websiteURL, userAgent, cookie, username, password) + return tryWellKnownUrls(websiteURL, userAgent, cookie, username, password, fetchViaProxy, allowSelfSignedCertificates) } -func parseWebPage(websiteURL string, data io.Reader) (Subscriptions, *errors.LocalizedError) { +func parseWebPage(websiteURL string, data io.Reader) (Subscriptions, *locale.LocalizedErrorWrapper) { var subscriptions Subscriptions queries := map[string]string{ "link[type='application/rss+xml']": "rss", @@ -95,7 +112,7 @@ func parseWebPage(websiteURL string, data io.Reader) (Subscriptions, *errors.Loc doc, err := goquery.NewDocumentFromReader(data) if err != nil { - return nil, errors.NewLocalizedError(errUnreadableDoc, err) + return nil, locale.NewLocalizedErrorWrapper(err, "error.unable_to_parse_html_document", err) } for query, kind := range queries { @@ -140,13 +157,19 @@ func parseYoutubeVideoPage(websiteURL string) string { return websiteURL } - clt := client.NewClientWithConfig(websiteURL, config.Opts) - response, browserErr := browser.Exec(clt) - if browserErr != nil { + requestBuilder := fetcher.NewRequestBuilder() + requestBuilder.WithTimeout(config.Opts.HTTPClientTimeout()) + requestBuilder.WithProxy(config.Opts.HTTPClientProxy()) + + responseHandler := fetcher.NewResponseHandler(requestBuilder.ExecuteRequest(websiteURL)) + defer responseHandler.Close() + + if localizedError := responseHandler.LocalizedError(); localizedError != nil { + slog.Warn("Unable to find subscriptions", slog.String("website_url", websiteURL), slog.Any("error", localizedError.Error())) return websiteURL } - doc, docErr := goquery.NewDocumentFromReader(response.Body) + doc, docErr := goquery.NewDocumentFromReader(responseHandler.Body(config.Opts.HTTPClientMaxBodySize())) if docErr != nil { return websiteURL } @@ -158,7 +181,7 @@ func parseYoutubeVideoPage(websiteURL string) string { return websiteURL } -func tryWellKnownUrls(websiteURL, userAgent, cookie, username, password string) (Subscriptions, *errors.LocalizedError) { +func tryWellKnownUrls(websiteURL, userAgent, cookie, username, password string, fetchViaProxy, allowSelfSignedCertificates bool) (Subscriptions, *locale.LocalizedErrorWrapper) { var subscriptions Subscriptions knownURLs := map[string]string{ "atom.xml": "atom", @@ -173,6 +196,7 @@ func tryWellKnownUrls(websiteURL, userAgent, cookie, username, password string) // Look for knownURLs in the root. websiteURLRoot, } + // Look for knownURLs in current subdirectory, such as 'example.com/blog/'. websiteURL, _ = urllib.AbsoluteURL(websiteURL, "./") if websiteURL != websiteURLRoot { @@ -185,30 +209,33 @@ func tryWellKnownUrls(websiteURL, userAgent, cookie, username, password string) if err != nil { continue } - clt := client.NewClientWithConfig(fullURL, config.Opts) - clt.WithCredentials(username, password) - clt.WithUserAgent(userAgent) - clt.WithCookie(cookie) + + requestBuilder := fetcher.NewRequestBuilder() + requestBuilder.WithUsernameAndPassword(username, password) + requestBuilder.WithUserAgent(userAgent) + requestBuilder.WithCookie(cookie) + requestBuilder.WithTimeout(config.Opts.HTTPClientTimeout()) + requestBuilder.WithProxy(config.Opts.HTTPClientProxy()) + requestBuilder.UseProxy(fetchViaProxy) + requestBuilder.IgnoreTLSErrors(allowSelfSignedCertificates) // Some websites redirects unknown URLs to the home page. // As result, the list of known URLs is returned to the subscription list. // We don't want the user to choose between invalid feed URLs. - clt.WithoutRedirects() + requestBuilder.WithoutRedirects() - response, err := clt.Get() - if err != nil { + responseHandler := fetcher.NewResponseHandler(requestBuilder.ExecuteRequest(fullURL)) + defer responseHandler.Close() + + if localizedError := responseHandler.LocalizedError(); localizedError != nil { continue } - if response != nil && response.StatusCode == 200 { - subscription := new(Subscription) - subscription.Type = kind - subscription.Title = fullURL - subscription.URL = fullURL - if subscription.URL != "" { - subscriptions = append(subscriptions, subscription) - } - } + subscription := new(Subscription) + subscription.Type = kind + subscription.Title = fullURL + subscription.URL = fullURL + subscriptions = append(subscriptions, subscription) } } diff --git a/internal/template/engine.go b/internal/template/engine.go index 4104e019..1c834f35 100644 --- a/internal/template/engine.go +++ b/internal/template/engine.go @@ -11,7 +11,6 @@ import ( "strings" "time" - "miniflux.app/v2/internal/errors" "miniflux.app/v2/internal/locale" "github.com/gorilla/mux" @@ -119,10 +118,6 @@ func (e *Engine) Render(name string, data map[string]interface{}) []byte { switch k := key.(type) { case string: return printer.Printf(k, args...) - case errors.LocalizedError: - return k.Localize(printer) - case *errors.LocalizedError: - return k.Localize(printer) case error: return k.Error() default: diff --git a/internal/template/templates/views/add_subscription.html b/internal/template/templates/views/add_subscription.html index be208f60..5a2cd3d6 100644 --- a/internal/template/templates/views/add_subscription.html +++ b/internal/template/templates/views/add_subscription.html @@ -13,7 +13,7 @@ {{ if .errorMessage }} -
{{ t .errorMessage }}
+
{{ .errorMessage }}
{{ end }} diff --git a/internal/template/templates/views/create_api_key.html b/internal/template/templates/views/create_api_key.html index 8c1e2f28..cf6ace4c 100644 --- a/internal/template/templates/views/create_api_key.html +++ b/internal/template/templates/views/create_api_key.html @@ -10,7 +10,7 @@ {{ if .errorMessage }} -
{{ t .errorMessage }}
+
{{ .errorMessage }}
{{ end }} diff --git a/internal/template/templates/views/create_category.html b/internal/template/templates/views/create_category.html index c6be3e6f..c9635966 100644 --- a/internal/template/templates/views/create_category.html +++ b/internal/template/templates/views/create_category.html @@ -14,7 +14,7 @@ {{ if .errorMessage }} -
{{ t .errorMessage }}
+
{{ .errorMessage }}
{{ end }} diff --git a/internal/template/templates/views/create_user.html b/internal/template/templates/views/create_user.html index 155cb9bf..cce2a7bb 100644 --- a/internal/template/templates/views/create_user.html +++ b/internal/template/templates/views/create_user.html @@ -10,7 +10,7 @@ {{ if .errorMessage }} -
{{ t .errorMessage }}
+
{{ .errorMessage }}
{{ end }} diff --git a/internal/template/templates/views/edit_category.html b/internal/template/templates/views/edit_category.html index 4412ff97..16588a60 100644 --- a/internal/template/templates/views/edit_category.html +++ b/internal/template/templates/views/edit_category.html @@ -20,7 +20,7 @@ {{ if .errorMessage }} -
{{ t .errorMessage }}
+
{{ .errorMessage }}
{{ end }} diff --git a/internal/template/templates/views/edit_feed.html b/internal/template/templates/views/edit_feed.html index 37f719b5..fc621826 100644 --- a/internal/template/templates/views/edit_feed.html +++ b/internal/template/templates/views/edit_feed.html @@ -37,7 +37,7 @@ {{ if .errorMessage }} -
{{ t .errorMessage }}
+
{{ .errorMessage }}
{{ end }}
diff --git a/internal/template/templates/views/edit_user.html b/internal/template/templates/views/edit_user.html index 87765110..e8b735f4 100644 --- a/internal/template/templates/views/edit_user.html +++ b/internal/template/templates/views/edit_user.html @@ -10,7 +10,7 @@ {{ if .errorMessage }} -
{{ t .errorMessage }}
+
{{ .errorMessage }}
{{ end }} diff --git a/internal/template/templates/views/import.html b/internal/template/templates/views/import.html index 042b1962..55d9fe4d 100644 --- a/internal/template/templates/views/import.html +++ b/internal/template/templates/views/import.html @@ -7,7 +7,7 @@ {{ if .errorMessage }} -
{{ t .errorMessage }}
+
{{ .errorMessage }}
{{ end }}
diff --git a/internal/template/templates/views/integrations.html b/internal/template/templates/views/integrations.html index faffb3b7..4edb98d1 100644 --- a/internal/template/templates/views/integrations.html +++ b/internal/template/templates/views/integrations.html @@ -10,7 +10,7 @@ {{ if .errorMessage }} -
{{ t .errorMessage }}
+
{{ .errorMessage }}
{{ end }}
diff --git a/internal/template/templates/views/login.html b/internal/template/templates/views/login.html index 4831eefe..74ed39c9 100644 --- a/internal/template/templates/views/login.html +++ b/internal/template/templates/views/login.html @@ -6,7 +6,7 @@ {{ if .errorMessage }} -
{{ t .errorMessage }}
+
{{ .errorMessage }}
{{ end }} diff --git a/internal/template/templates/views/settings.html b/internal/template/templates/views/settings.html index 3cc4adf4..43ded00d 100644 --- a/internal/template/templates/views/settings.html +++ b/internal/template/templates/views/settings.html @@ -10,7 +10,7 @@ {{ if .errorMessage }} -
{{ t .errorMessage }}
+
{{ .errorMessage }}
{{ end }}
diff --git a/internal/ui/api_key_save.go b/internal/ui/api_key_save.go index ebadd300..34773c30 100644 --- a/internal/ui/api_key_save.go +++ b/internal/ui/api_key_save.go @@ -9,6 +9,7 @@ import ( "miniflux.app/v2/internal/http/request" "miniflux.app/v2/internal/http/response/html" "miniflux.app/v2/internal/http/route" + "miniflux.app/v2/internal/locale" "miniflux.app/v2/internal/model" "miniflux.app/v2/internal/ui/form" "miniflux.app/v2/internal/ui/session" @@ -32,14 +33,14 @@ func (h *handler) saveAPIKey(w http.ResponseWriter, r *http.Request) { view.Set("countUnread", h.store.CountUnreadEntries(user.ID)) view.Set("countErrorFeeds", h.store.CountUserFeedsWithErrors(user.ID)) - if err := apiKeyForm.Validate(); err != nil { - view.Set("errorMessage", err.Error()) + if validationErr := apiKeyForm.Validate(); validationErr != nil { + view.Set("errorMessage", validationErr.Translate(user.Language)) html.OK(w, r, view.Render("create_api_key")) return } if h.store.APIKeyExists(user.ID, apiKeyForm.Description) { - view.Set("errorMessage", "error.api_key_already_exists") + view.Set("errorMessage", locale.NewLocalizedError("error.api_key_already_exists").Translate(user.Language)) html.OK(w, r, view.Render("create_api_key")) return } diff --git a/internal/ui/category_save.go b/internal/ui/category_save.go index e4708b5a..22787e16 100644 --- a/internal/ui/category_save.go +++ b/internal/ui/category_save.go @@ -36,7 +36,7 @@ func (h *handler) saveCategory(w http.ResponseWriter, r *http.Request) { categoryRequest := &model.CategoryRequest{Title: categoryForm.Title} if validationErr := validator.ValidateCategoryCreation(h.store, loggedUser.ID, categoryRequest); validationErr != nil { - view.Set("errorMessage", validationErr.TranslationKey) + view.Set("errorMessage", validationErr.Translate(loggedUser.Language)) html.OK(w, r, view.Render("create_category")) return } diff --git a/internal/ui/category_update.go b/internal/ui/category_update.go index 8dad9375..e701a0bd 100644 --- a/internal/ui/category_update.go +++ b/internal/ui/category_update.go @@ -52,7 +52,7 @@ func (h *handler) updateCategory(w http.ResponseWriter, r *http.Request) { } if validationErr := validator.ValidateCategoryModification(h.store, loggedUser.ID, category.ID, categoryRequest); validationErr != nil { - view.Set("errorMessage", validationErr.TranslationKey) + view.Set("errorMessage", validationErr.Translate(loggedUser.Language)) html.OK(w, r, view.Render("create_category")) return } diff --git a/internal/ui/feed_update.go b/internal/ui/feed_update.go index 773c61b2..db5600ae 100644 --- a/internal/ui/feed_update.go +++ b/internal/ui/feed_update.go @@ -66,7 +66,7 @@ func (h *handler) updateFeed(w http.ResponseWriter, r *http.Request) { } if validationErr := validator.ValidateFeedModification(h.store, loggedUser.ID, feedModificationRequest); validationErr != nil { - view.Set("errorMessage", validationErr.TranslationKey) + view.Set("errorMessage", validationErr.Translate(loggedUser.Language)) html.OK(w, r, view.Render("edit_feed")) return } diff --git a/internal/ui/form/api_key.go b/internal/ui/form/api_key.go index 1eb754bc..b87322a5 100644 --- a/internal/ui/form/api_key.go +++ b/internal/ui/form/api_key.go @@ -6,7 +6,7 @@ package form // import "miniflux.app/v2/internal/ui/form" import ( "net/http" - "miniflux.app/v2/internal/errors" + "miniflux.app/v2/internal/locale" ) // APIKeyForm represents the API Key form. @@ -15,9 +15,9 @@ type APIKeyForm struct { } // Validate makes sure the form values are valid. -func (a APIKeyForm) Validate() error { +func (a APIKeyForm) Validate() *locale.LocalizedError { if a.Description == "" { - return errors.NewLocalizedError("error.fields_mandatory") + return locale.NewLocalizedError("error.fields_mandatory") } return nil diff --git a/internal/ui/form/auth.go b/internal/ui/form/auth.go index 37c3eab0..d1a9055b 100644 --- a/internal/ui/form/auth.go +++ b/internal/ui/form/auth.go @@ -7,7 +7,7 @@ import ( "net/http" "strings" - "miniflux.app/v2/internal/errors" + "miniflux.app/v2/internal/locale" ) // AuthForm represents the authentication form. @@ -17,9 +17,9 @@ type AuthForm struct { } // Validate makes sure the form values are valid. -func (a AuthForm) Validate() error { +func (a AuthForm) Validate() *locale.LocalizedError { if a.Username == "" || a.Password == "" { - return errors.NewLocalizedError("error.fields_mandatory") + return locale.NewLocalizedError("error.fields_mandatory") } return nil diff --git a/internal/ui/form/settings.go b/internal/ui/form/settings.go index b640eff7..d5442218 100644 --- a/internal/ui/form/settings.go +++ b/internal/ui/form/settings.go @@ -7,7 +7,7 @@ import ( "net/http" "strconv" - "miniflux.app/v2/internal/errors" + "miniflux.app/v2/internal/locale" "miniflux.app/v2/internal/model" ) @@ -64,13 +64,13 @@ func (s *SettingsForm) Merge(user *model.User) *model.User { } // Validate makes sure the form values are valid. -func (s *SettingsForm) Validate() error { +func (s *SettingsForm) Validate() *locale.LocalizedError { if s.Username == "" || s.Theme == "" || s.Language == "" || s.Timezone == "" || s.EntryDirection == "" || s.DisplayMode == "" || s.DefaultHomePage == "" { - return errors.NewLocalizedError("error.settings_mandatory_fields") + return locale.NewLocalizedError("error.settings_mandatory_fields") } if s.CJKReadingSpeed <= 0 || s.DefaultReadingSpeed <= 0 { - return errors.NewLocalizedError("error.settings_reading_speed_is_positive") + return locale.NewLocalizedError("error.settings_reading_speed_is_positive") } if s.Confirmation == "" { @@ -80,7 +80,7 @@ func (s *SettingsForm) Validate() error { s.Password = "" } else if s.Password != "" { if s.Password != s.Confirmation { - return errors.NewLocalizedError("error.different_passwords") + return locale.NewLocalizedError("error.different_passwords") } } diff --git a/internal/ui/form/subscription.go b/internal/ui/form/subscription.go index 16dd215b..39e76fd6 100644 --- a/internal/ui/form/subscription.go +++ b/internal/ui/form/subscription.go @@ -7,7 +7,7 @@ import ( "net/http" "strconv" - "miniflux.app/v2/internal/errors" + "miniflux.app/v2/internal/locale" "miniflux.app/v2/internal/validator" ) @@ -29,26 +29,26 @@ type SubscriptionForm struct { UrlRewriteRules string } -// Validate makes sure the form values are valid. -func (s *SubscriptionForm) Validate() error { +// Validate makes sure the form values locale.are valid. +func (s *SubscriptionForm) Validate() *locale.LocalizedError { if s.URL == "" || s.CategoryID == 0 { - return errors.NewLocalizedError("error.feed_mandatory_fields") + return locale.NewLocalizedError("error.feed_mandatory_fields") } if !validator.IsValidURL(s.URL) { - return errors.NewLocalizedError("error.invalid_feed_url") + return locale.NewLocalizedError("error.invalid_feed_url") } if !validator.IsValidRegex(s.BlocklistRules) { - return errors.NewLocalizedError("error.feed_invalid_blocklist_rule") + return locale.NewLocalizedError("error.feed_invalid_blocklist_rule") } if !validator.IsValidRegex(s.KeeplistRules) { - return errors.NewLocalizedError("error.feed_invalid_keeplist_rule") + return locale.NewLocalizedError("error.feed_invalid_keeplist_rule") } if !validator.IsValidRegex(s.UrlRewriteRules) { - return errors.NewLocalizedError("error.feed_invalid_urlrewrite_rule") + return locale.NewLocalizedError("error.feed_invalid_urlrewrite_rule") } return nil diff --git a/internal/ui/form/user.go b/internal/ui/form/user.go index 4c6c4e13..ea4cfcd6 100644 --- a/internal/ui/form/user.go +++ b/internal/ui/form/user.go @@ -6,7 +6,7 @@ package form // import "miniflux.app/v2/internal/ui/form" import ( "net/http" - "miniflux.app/v2/internal/errors" + "miniflux.app/v2/internal/locale" "miniflux.app/v2/internal/model" ) @@ -19,31 +19,31 @@ type UserForm struct { } // ValidateCreation validates user creation. -func (u UserForm) ValidateCreation() error { +func (u UserForm) ValidateCreation() *locale.LocalizedError { if u.Username == "" || u.Password == "" || u.Confirmation == "" { - return errors.NewLocalizedError("error.fields_mandatory") + return locale.NewLocalizedError("error.fields_mandatory") } if u.Password != u.Confirmation { - return errors.NewLocalizedError("error.different_passwords") + return locale.NewLocalizedError("error.different_passwords") } return nil } // ValidateModification validates user modification. -func (u UserForm) ValidateModification() error { +func (u UserForm) ValidateModification() *locale.LocalizedError { if u.Username == "" { - return errors.NewLocalizedError("error.user_mandatory_fields") + return locale.NewLocalizedError("error.user_mandatory_fields") } if u.Password != "" { if u.Password != u.Confirmation { - return errors.NewLocalizedError("error.different_passwords") + return locale.NewLocalizedError("error.different_passwords") } if len(u.Password) < 6 { - return errors.NewLocalizedError("error.password_min_length") + return locale.NewLocalizedError("error.password_min_length") } } diff --git a/internal/ui/login_check.go b/internal/ui/login_check.go index 9ae56c47..b870cf57 100644 --- a/internal/ui/login_check.go +++ b/internal/ui/login_check.go @@ -12,6 +12,7 @@ import ( "miniflux.app/v2/internal/http/request" "miniflux.app/v2/internal/http/response/html" "miniflux.app/v2/internal/http/route" + "miniflux.app/v2/internal/locale" "miniflux.app/v2/internal/ui/form" "miniflux.app/v2/internal/ui/session" "miniflux.app/v2/internal/ui/view" @@ -23,16 +24,17 @@ func (h *handler) checkLogin(w http.ResponseWriter, r *http.Request) { authForm := form.NewAuthForm(r) view := view.New(h.tpl, r, sess) - view.Set("errorMessage", "error.bad_credentials") + view.Set("errorMessage", locale.NewLocalizedError("error.bad_credentials").Translate(request.UserLanguage(r))) view.Set("form", authForm) - if err := authForm.Validate(); err != nil { + if validationErr := authForm.Validate(); validationErr != nil { + translatedErrorMessage := validationErr.Translate(request.UserLanguage(r)) slog.Warn("Validation error during login check", slog.Bool("authentication_failed", true), slog.String("client_ip", clientIP), slog.String("user_agent", r.UserAgent()), slog.String("username", authForm.Username), - slog.Any("error", err), + slog.Any("error", translatedErrorMessage), ) html.OK(w, r, view.Render("login")) return diff --git a/internal/ui/opml_upload.go b/internal/ui/opml_upload.go index 0121952a..ed05cc2f 100644 --- a/internal/ui/opml_upload.go +++ b/internal/ui/opml_upload.go @@ -6,12 +6,14 @@ package ui // import "miniflux.app/v2/internal/ui" import ( "log/slog" "net/http" + "strings" "miniflux.app/v2/internal/config" - "miniflux.app/v2/internal/http/client" "miniflux.app/v2/internal/http/request" "miniflux.app/v2/internal/http/response/html" "miniflux.app/v2/internal/http/route" + "miniflux.app/v2/internal/locale" + "miniflux.app/v2/internal/reader/fetcher" "miniflux.app/v2/internal/reader/opml" "miniflux.app/v2/internal/ui/session" "miniflux.app/v2/internal/ui/view" @@ -51,7 +53,7 @@ func (h *handler) uploadOPML(w http.ResponseWriter, r *http.Request) { view.Set("countErrorFeeds", h.store.CountUserFeedsWithErrors(user.ID)) if fileHeader.Size == 0 { - view.Set("errorMessage", "error.empty_file") + view.Set("errorMessage", locale.NewLocalizedError("error.empty_file").Translate(user.Language)) html.OK(w, r, view.Render("import")) return } @@ -73,15 +75,15 @@ func (h *handler) fetchOPML(w http.ResponseWriter, r *http.Request) { return } - url := r.FormValue("url") - if url == "" { + opmlFileURL := strings.TrimSpace(r.FormValue("url")) + if opmlFileURL == "" { html.Redirect(w, r, route.Path(h.router, "import")) return } slog.Info("Fetching OPML file remotely", slog.Int64("user_id", loggedUserID), - slog.String("opml_file_url", url), + slog.String("opml_file_url", opmlFileURL), ) sess := session.New(h.store, request.SessionID(r)) @@ -91,15 +93,21 @@ func (h *handler) fetchOPML(w http.ResponseWriter, r *http.Request) { view.Set("countUnread", h.store.CountUnreadEntries(user.ID)) view.Set("countErrorFeeds", h.store.CountUserFeedsWithErrors(user.ID)) - clt := client.NewClientWithConfig(url, config.Opts) - resp, err := clt.Get() - if err != nil { - view.Set("errorMessage", err) + requestBuilder := fetcher.NewRequestBuilder() + requestBuilder.WithTimeout(config.Opts.HTTPClientTimeout()) + requestBuilder.WithProxy(config.Opts.HTTPClientProxy()) + + responseHandler := fetcher.NewResponseHandler(requestBuilder.ExecuteRequest(opmlFileURL)) + defer responseHandler.Close() + + if localizedError := responseHandler.LocalizedError(); localizedError != nil { + slog.Warn("Unable to fetch OPML file", slog.String("opml_file_url", opmlFileURL), slog.Any("error", localizedError.Error())) + view.Set("errorMessage", localizedError.Translate(user.Language)) html.OK(w, r, view.Render("import")) return } - if impErr := opml.NewHandler(h.store).Import(user.ID, resp.Body); impErr != nil { + if impErr := opml.NewHandler(h.store).Import(user.ID, responseHandler.Body(config.Opts.HTTPClientMaxBodySize())); impErr != nil { view.Set("errorMessage", impErr) html.OK(w, r, view.Render("import")) return diff --git a/internal/ui/settings_update.go b/internal/ui/settings_update.go index a9a8b519..d580e8d7 100644 --- a/internal/ui/settings_update.go +++ b/internal/ui/settings_update.go @@ -44,8 +44,8 @@ func (h *handler) updateSettings(w http.ResponseWriter, r *http.Request) { view.Set("countUnread", h.store.CountUnreadEntries(loggedUser.ID)) view.Set("countErrorFeeds", h.store.CountUserFeedsWithErrors(loggedUser.ID)) - if err := settingsForm.Validate(); err != nil { - view.Set("errorMessage", err.Error()) + if validationErr := settingsForm.Validate(); validationErr != nil { + view.Set("errorMessage", validationErr.Translate(loggedUser.Language)) html.OK(w, r, view.Render("settings")) return } @@ -66,7 +66,7 @@ func (h *handler) updateSettings(w http.ResponseWriter, r *http.Request) { } if validationErr := validator.ValidateUserModification(h.store, loggedUser.ID, userModificationRequest); validationErr != nil { - view.Set("errorMessage", validationErr.TranslationKey) + view.Set("errorMessage", validationErr.Translate(loggedUser.Language)) html.OK(w, r, view.Render("settings")) return } diff --git a/internal/ui/subscription_choose.go b/internal/ui/subscription_choose.go index ac6ea7e3..3066dad3 100644 --- a/internal/ui/subscription_choose.go +++ b/internal/ui/subscription_choose.go @@ -41,14 +41,14 @@ func (h *handler) showChooseSubscriptionPage(w http.ResponseWriter, r *http.Requ view.Set("defaultUserAgent", config.Opts.HTTPClientUserAgent()) subscriptionForm := form.NewSubscriptionForm(r) - if err := subscriptionForm.Validate(); err != nil { + if validationErr := subscriptionForm.Validate(); validationErr != nil { view.Set("form", subscriptionForm) - view.Set("errorMessage", err.Error()) + view.Set("errorMessage", validationErr.Translate(user.Language)) html.OK(w, r, view.Render("add_subscription")) return } - feed, err := feedHandler.CreateFeed(h.store, user.ID, &model.FeedCreationRequest{ + feed, localizedError := feedHandler.CreateFeed(h.store, user.ID, &model.FeedCreationRequest{ CategoryID: subscriptionForm.CategoryID, FeedURL: subscriptionForm.URL, Crawler: subscriptionForm.Crawler, @@ -64,9 +64,9 @@ func (h *handler) showChooseSubscriptionPage(w http.ResponseWriter, r *http.Requ UrlRewriteRules: subscriptionForm.UrlRewriteRules, FetchViaProxy: subscriptionForm.FetchViaProxy, }) - if err != nil { + if localizedError != nil { view.Set("form", subscriptionForm) - view.Set("errorMessage", err) + view.Set("errorMessage", localizedError.Translate(user.Language)) html.OK(w, r, view.Render("add_subscription")) return } diff --git a/internal/ui/subscription_submit.go b/internal/ui/subscription_submit.go index 41e75a4a..ce444d79 100644 --- a/internal/ui/subscription_submit.go +++ b/internal/ui/subscription_submit.go @@ -10,6 +10,7 @@ import ( "miniflux.app/v2/internal/http/request" "miniflux.app/v2/internal/http/response/html" "miniflux.app/v2/internal/http/route" + "miniflux.app/v2/internal/locale" "miniflux.app/v2/internal/model" feedHandler "miniflux.app/v2/internal/reader/handler" "miniflux.app/v2/internal/reader/subscription" @@ -43,9 +44,9 @@ func (h *handler) submitSubscription(w http.ResponseWriter, r *http.Request) { v.Set("hasProxyConfigured", config.Opts.HasHTTPClientProxyConfigured()) subscriptionForm := form.NewSubscriptionForm(r) - if err := subscriptionForm.Validate(); err != nil { + if validationErr := subscriptionForm.Validate(); validationErr != nil { v.Set("form", subscriptionForm) - v.Set("errorMessage", err.Error()) + v.Set("errorMessage", validationErr.Translate(user.Language)) html.OK(w, r, v.Render("add_subscription")) return } @@ -55,7 +56,7 @@ func (h *handler) submitSubscription(w http.ResponseWriter, r *http.Request) { rssbridgeURL = intg.RSSBridgeURL } - subscriptions, findErr := subscription.FindSubscriptions( + subscriptions, localizedError := subscription.FindSubscriptions( subscriptionForm.URL, subscriptionForm.UserAgent, subscriptionForm.Cookie, @@ -65,9 +66,9 @@ func (h *handler) submitSubscription(w http.ResponseWriter, r *http.Request) { subscriptionForm.AllowSelfSignedCertificates, rssbridgeURL, ) - if findErr != nil { + if localizedError != nil { v.Set("form", subscriptionForm) - v.Set("errorMessage", findErr) + v.Set("errorMessage", localizedError.Translate(user.Language)) html.OK(w, r, v.Render("add_subscription")) return } @@ -76,10 +77,10 @@ func (h *handler) submitSubscription(w http.ResponseWriter, r *http.Request) { switch { case n == 0: v.Set("form", subscriptionForm) - v.Set("errorMessage", "error.subscription_not_found") + v.Set("errorMessage", locale.NewLocalizedError("error.subscription_not_found").Translate(user.Language)) html.OK(w, r, v.Render("add_subscription")) case n == 1: - feed, err := feedHandler.CreateFeed(h.store, user.ID, &model.FeedCreationRequest{ + feed, localizedError := feedHandler.CreateFeed(h.store, user.ID, &model.FeedCreationRequest{ CategoryID: subscriptionForm.CategoryID, FeedURL: subscriptions[0].URL, Crawler: subscriptionForm.Crawler, @@ -95,9 +96,9 @@ func (h *handler) submitSubscription(w http.ResponseWriter, r *http.Request) { UrlRewriteRules: subscriptionForm.UrlRewriteRules, FetchViaProxy: subscriptionForm.FetchViaProxy, }) - if err != nil { + if localizedError != nil { v.Set("form", subscriptionForm) - v.Set("errorMessage", err) + v.Set("errorMessage", localizedError.Translate(user.Language)) html.OK(w, r, v.Render("add_subscription")) return } diff --git a/internal/ui/user_save.go b/internal/ui/user_save.go index 982c4973..fb5f176e 100644 --- a/internal/ui/user_save.go +++ b/internal/ui/user_save.go @@ -9,6 +9,7 @@ import ( "miniflux.app/v2/internal/http/request" "miniflux.app/v2/internal/http/response/html" "miniflux.app/v2/internal/http/route" + "miniflux.app/v2/internal/locale" "miniflux.app/v2/internal/model" "miniflux.app/v2/internal/ui/form" "miniflux.app/v2/internal/ui/session" @@ -38,14 +39,14 @@ func (h *handler) saveUser(w http.ResponseWriter, r *http.Request) { view.Set("countErrorFeeds", h.store.CountUserFeedsWithErrors(user.ID)) view.Set("form", userForm) - if err := userForm.ValidateCreation(); err != nil { - view.Set("errorMessage", err.Error()) + if validationErr := userForm.ValidateCreation(); validationErr != nil { + view.Set("errorMessage", validationErr.Translate(user.Language)) html.OK(w, r, view.Render("create_user")) return } if h.store.UserExists(userForm.Username) { - view.Set("errorMessage", "error.user_already_exists") + view.Set("errorMessage", locale.NewLocalizedError("error.user_already_exists").Translate(user.Language)) html.OK(w, r, view.Render("create_user")) return } @@ -57,7 +58,7 @@ func (h *handler) saveUser(w http.ResponseWriter, r *http.Request) { } if validationErr := validator.ValidateUserCreationWithPassword(h.store, userCreationRequest); validationErr != nil { - view.Set("errorMessage", validationErr.TranslationKey) + view.Set("errorMessage", validationErr.Translate(user.Language)) html.OK(w, r, view.Render("create_user")) return } diff --git a/internal/ui/user_update.go b/internal/ui/user_update.go index 3e4229c1..f0cc1401 100644 --- a/internal/ui/user_update.go +++ b/internal/ui/user_update.go @@ -9,6 +9,7 @@ import ( "miniflux.app/v2/internal/http/request" "miniflux.app/v2/internal/http/response/html" "miniflux.app/v2/internal/http/route" + "miniflux.app/v2/internal/locale" "miniflux.app/v2/internal/ui/form" "miniflux.app/v2/internal/ui/session" "miniflux.app/v2/internal/ui/view" @@ -49,14 +50,14 @@ func (h *handler) updateUser(w http.ResponseWriter, r *http.Request) { view.Set("selected_user", selectedUser) view.Set("form", userForm) - if err := userForm.ValidateModification(); err != nil { - view.Set("errorMessage", err.Error()) + if validationErr := userForm.ValidateModification(); validationErr != nil { + view.Set("errorMessage", validationErr.Translate(loggedUser.Language)) html.OK(w, r, view.Render("edit_user")) return } if h.store.AnotherUserExists(selectedUser.ID, userForm.Username) { - view.Set("errorMessage", "error.user_already_exists") + view.Set("errorMessage", locale.NewLocalizedError("error.user_already_exists").Translate(loggedUser.Language)) html.OK(w, r, view.Render("edit_user")) return } diff --git a/internal/validator/category.go b/internal/validator/category.go index 54d74078..7be076db 100644 --- a/internal/validator/category.go +++ b/internal/validator/category.go @@ -4,31 +4,32 @@ package validator // import "miniflux.app/v2/internal/validator" import ( + "miniflux.app/v2/internal/locale" "miniflux.app/v2/internal/model" "miniflux.app/v2/internal/storage" ) // ValidateCategoryCreation validates category creation. -func ValidateCategoryCreation(store *storage.Storage, userID int64, request *model.CategoryRequest) *ValidationError { +func ValidateCategoryCreation(store *storage.Storage, userID int64, request *model.CategoryRequest) *locale.LocalizedError { if request.Title == "" { - return NewValidationError("error.title_required") + return locale.NewLocalizedError("error.title_required") } if store.CategoryTitleExists(userID, request.Title) { - return NewValidationError("error.category_already_exists") + return locale.NewLocalizedError("error.category_already_exists") } return nil } // ValidateCategoryModification validates category modification. -func ValidateCategoryModification(store *storage.Storage, userID, categoryID int64, request *model.CategoryRequest) *ValidationError { +func ValidateCategoryModification(store *storage.Storage, userID, categoryID int64, request *model.CategoryRequest) *locale.LocalizedError { if request.Title == "" { - return NewValidationError("error.title_required") + return locale.NewLocalizedError("error.title_required") } if store.AnotherCategoryExists(userID, categoryID, request.Title) { - return NewValidationError("error.category_already_exists") + return locale.NewLocalizedError("error.category_already_exists") } return nil diff --git a/internal/validator/feed.go b/internal/validator/feed.go index 3d3a1caf..25f7f1fc 100644 --- a/internal/validator/feed.go +++ b/internal/validator/feed.go @@ -4,82 +4,83 @@ package validator // import "miniflux.app/v2/internal/validator" import ( + "miniflux.app/v2/internal/locale" "miniflux.app/v2/internal/model" "miniflux.app/v2/internal/storage" ) // ValidateFeedCreation validates feed creation. -func ValidateFeedCreation(store *storage.Storage, userID int64, request *model.FeedCreationRequest) *ValidationError { +func ValidateFeedCreation(store *storage.Storage, userID int64, request *model.FeedCreationRequest) *locale.LocalizedError { if request.FeedURL == "" || request.CategoryID <= 0 { - return NewValidationError("error.feed_mandatory_fields") + return locale.NewLocalizedError("error.feed_mandatory_fields") } if !IsValidURL(request.FeedURL) { - return NewValidationError("error.invalid_feed_url") + return locale.NewLocalizedError("error.invalid_feed_url") } if store.FeedURLExists(userID, request.FeedURL) { - return NewValidationError("error.feed_already_exists") + return locale.NewLocalizedError("error.feed_already_exists") } if !store.CategoryIDExists(userID, request.CategoryID) { - return NewValidationError("error.feed_category_not_found") + return locale.NewLocalizedError("error.feed_category_not_found") } if !IsValidRegex(request.BlocklistRules) { - return NewValidationError("error.feed_invalid_blocklist_rule") + return locale.NewLocalizedError("error.feed_invalid_blocklist_rule") } if !IsValidRegex(request.KeeplistRules) { - return NewValidationError("error.feed_invalid_keeplist_rule") + return locale.NewLocalizedError("error.feed_invalid_keeplist_rule") } return nil } // ValidateFeedModification validates feed modification. -func ValidateFeedModification(store *storage.Storage, userID int64, request *model.FeedModificationRequest) *ValidationError { +func ValidateFeedModification(store *storage.Storage, userID int64, request *model.FeedModificationRequest) *locale.LocalizedError { if request.FeedURL != nil { if *request.FeedURL == "" { - return NewValidationError("error.feed_url_not_empty") + return locale.NewLocalizedError("error.feed_url_not_empty") } if !IsValidURL(*request.FeedURL) { - return NewValidationError("error.invalid_feed_url") + return locale.NewLocalizedError("error.invalid_feed_url") } } if request.SiteURL != nil { if *request.SiteURL == "" { - return NewValidationError("error.site_url_not_empty") + return locale.NewLocalizedError("error.site_url_not_empty") } if !IsValidURL(*request.SiteURL) { - return NewValidationError("error.invalid_site_url") + return locale.NewLocalizedError("error.invalid_site_url") } } if request.Title != nil { if *request.Title == "" { - return NewValidationError("error.feed_title_not_empty") + return locale.NewLocalizedError("error.feed_title_not_empty") } } if request.CategoryID != nil { if !store.CategoryIDExists(userID, *request.CategoryID) { - return NewValidationError("error.feed_category_not_found") + return locale.NewLocalizedError("error.feed_category_not_found") } } if request.BlocklistRules != nil { if !IsValidRegex(*request.BlocklistRules) { - return NewValidationError("error.feed_invalid_blocklist_rule") + return locale.NewLocalizedError("error.feed_invalid_blocklist_rule") } } if request.KeeplistRules != nil { if !IsValidRegex(*request.KeeplistRules) { - return NewValidationError("error.feed_invalid_keeplist_rule") + return locale.NewLocalizedError("error.feed_invalid_keeplist_rule") } } diff --git a/internal/validator/subscription.go b/internal/validator/subscription.go index d09ddc01..516f679d 100644 --- a/internal/validator/subscription.go +++ b/internal/validator/subscription.go @@ -3,12 +3,15 @@ package validator // import "miniflux.app/v2/internal/validator" -import "miniflux.app/v2/internal/model" +import ( + "miniflux.app/v2/internal/locale" + "miniflux.app/v2/internal/model" +) // ValidateSubscriptionDiscovery validates subscription discovery requests. -func ValidateSubscriptionDiscovery(request *model.SubscriptionDiscoveryRequest) *ValidationError { +func ValidateSubscriptionDiscovery(request *model.SubscriptionDiscoveryRequest) *locale.LocalizedError { if !IsValidURL(request.URL) { - return NewValidationError("error.invalid_site_url") + return locale.NewLocalizedError("error.invalid_site_url") } return nil diff --git a/internal/validator/user.go b/internal/validator/user.go index edaa3fe1..8c6cc9d2 100644 --- a/internal/validator/user.go +++ b/internal/validator/user.go @@ -10,13 +10,13 @@ import ( ) // ValidateUserCreationWithPassword validates user creation with a password. -func ValidateUserCreationWithPassword(store *storage.Storage, request *model.UserCreationRequest) *ValidationError { +func ValidateUserCreationWithPassword(store *storage.Storage, request *model.UserCreationRequest) *locale.LocalizedError { if request.Username == "" { - return NewValidationError("error.user_mandatory_fields") + return locale.NewLocalizedError("error.user_mandatory_fields") } if store.UserExists(request.Username) { - return NewValidationError("error.user_already_exists") + return locale.NewLocalizedError("error.user_already_exists") } if err := validatePassword(request.Password); err != nil { @@ -27,12 +27,12 @@ func ValidateUserCreationWithPassword(store *storage.Storage, request *model.Use } // ValidateUserModification validates user modifications. -func ValidateUserModification(store *storage.Storage, userID int64, changes *model.UserModificationRequest) *ValidationError { +func ValidateUserModification(store *storage.Storage, userID int64, changes *model.UserModificationRequest) *locale.LocalizedError { if changes.Username != nil { if *changes.Username == "" { - return NewValidationError("error.user_mandatory_fields") + return locale.NewLocalizedError("error.user_mandatory_fields") } else if store.AnotherUserExists(userID, *changes.Username) { - return NewValidationError("error.user_already_exists") + return locale.NewLocalizedError("error.user_already_exists") } } @@ -105,80 +105,80 @@ func ValidateUserModification(store *storage.Storage, userID int64, changes *mod return nil } -func validateReadingSpeed(readingSpeed int) *ValidationError { +func validateReadingSpeed(readingSpeed int) *locale.LocalizedError { if readingSpeed <= 0 { - return NewValidationError("error.settings_reading_speed_is_positive") + return locale.NewLocalizedError("error.settings_reading_speed_is_positive") } return nil } -func validatePassword(password string) *ValidationError { +func validatePassword(password string) *locale.LocalizedError { if len(password) < 6 { - return NewValidationError("error.password_min_length") + return locale.NewLocalizedError("error.password_min_length") } return nil } -func validateTheme(theme string) *ValidationError { +func validateTheme(theme string) *locale.LocalizedError { themes := model.Themes() if _, found := themes[theme]; !found { - return NewValidationError("error.invalid_theme") + return locale.NewLocalizedError("error.invalid_theme") } return nil } -func validateLanguage(language string) *ValidationError { +func validateLanguage(language string) *locale.LocalizedError { languages := locale.AvailableLanguages() if _, found := languages[language]; !found { - return NewValidationError("error.invalid_language") + return locale.NewLocalizedError("error.invalid_language") } return nil } -func validateTimezone(store *storage.Storage, timezone string) *ValidationError { +func validateTimezone(store *storage.Storage, timezone string) *locale.LocalizedError { timezones, err := store.Timezones() if err != nil { - return NewValidationError(err.Error()) + return locale.NewLocalizedError(err.Error()) } if _, found := timezones[timezone]; !found { - return NewValidationError("error.invalid_timezone") + return locale.NewLocalizedError("error.invalid_timezone") } return nil } -func validateEntryDirection(direction string) *ValidationError { +func validateEntryDirection(direction string) *locale.LocalizedError { if direction != "asc" && direction != "desc" { - return NewValidationError("error.invalid_entry_direction") + return locale.NewLocalizedError("error.invalid_entry_direction") } return nil } -func validateEntriesPerPage(entriesPerPage int) *ValidationError { +func validateEntriesPerPage(entriesPerPage int) *locale.LocalizedError { if entriesPerPage < 1 { - return NewValidationError("error.entries_per_page_invalid") + return locale.NewLocalizedError("error.entries_per_page_invalid") } return nil } -func validateDisplayMode(displayMode string) *ValidationError { +func validateDisplayMode(displayMode string) *locale.LocalizedError { if displayMode != "fullscreen" && displayMode != "standalone" && displayMode != "minimal-ui" && displayMode != "browser" { - return NewValidationError("error.invalid_display_mode") + return locale.NewLocalizedError("error.invalid_display_mode") } return nil } -func validateGestureNav(gestureNav string) *ValidationError { +func validateGestureNav(gestureNav string) *locale.LocalizedError { if gestureNav != "none" && gestureNav != "tap" && gestureNav != "swipe" { - return NewValidationError("error.invalid_gesture_nav") + return locale.NewLocalizedError("error.invalid_gesture_nav") } return nil } -func validateDefaultHomePage(defaultHomePage string) *ValidationError { +func validateDefaultHomePage(defaultHomePage string) *locale.LocalizedError { defaultHomePages := model.HomePages() if _, found := defaultHomePages[defaultHomePage]; !found { - return NewValidationError("error.invalid_default_home_page") + return locale.NewLocalizedError("error.invalid_default_home_page") } return nil } diff --git a/internal/validator/validator.go b/internal/validator/validator.go index b96b0aa7..9cedc5cd 100644 --- a/internal/validator/validator.go +++ b/internal/validator/validator.go @@ -4,32 +4,11 @@ package validator // import "miniflux.app/v2/internal/validator" import ( - "errors" "fmt" "net/url" "regexp" - - "miniflux.app/v2/internal/locale" ) -// ValidationError represents a validation error. -type ValidationError struct { - TranslationKey string -} - -// NewValidationError initializes a validation error. -func NewValidationError(translationKey string) *ValidationError { - return &ValidationError{TranslationKey: translationKey} -} - -func (v *ValidationError) String() string { - return locale.NewPrinter("en_US").Printf(v.TranslationKey) -} - -func (v *ValidationError) Error() error { - return errors.New(v.String()) -} - // ValidateRange makes sure the offset/limit values are valid. func ValidateRange(offset, limit int) error { if offset < 0 {