Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CI - no absolute links to local pages #849

Merged
merged 18 commits into from
Dec 29, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[submodule "tests/src/github.com/gdevillele/frontparser"]
path = tests/src/github.com/gdevillele/frontparser
url = https://github.com/gdevillele/frontparser.git
branch = f28e87c7b9dae139855b574e96f22822986249a8
[submodule "tests/src/golang.org/x/net"]
path = tests/src/golang.org/x/net
url = https://go.googlesource.com/net
branch = 45e771701b814666a7eb299e6c7a57d0b1799e91
[submodule "tests/src/gopkg.in/yaml.v2"]
path = tests/src/gopkg.in/yaml.v2
url = https://gopkg.in/yaml.v2
branch = a5b47d31c556af34a302ce5d659e6fea44d90de0

17 changes: 15 additions & 2 deletions Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,21 @@ wrappedNode(label: 'linux && x86_64') {
deleteDir()
stage "checkout"
checkout scm
sh "git submodule update --init --recursive"
stage "test"

/* Jekyll creates html files to implement client side redirects.
There are absolute links to docs.docker.com in these htmls
we don't want them to be parsed by the tests for now.
Removing jekyll-redirect-from option will make sure these pages
are not generated when building with Jekyll. */
sh "awk '/jekyll-redirect-from/{n=1}; n {n--; next}; 1' < _config.yml > _config.yml.tmp"
sh "mv _config.yml.tmp _config.yml"

sh "docker build -t docs `pwd`"
sh "docker build -t tests `pwd`/tests"
sh "docker run --rm -v `pwd`:/docs tests"
sh "docker rmi tests"
sh "docker run -v /usr/src/app/allvbuild --name docs docs /bin/true"
sh "docker run --rm --volumes-from docs -v `pwd`:/docs tests"
sh "docker rm -fv docs"
sh "docker rmi docs tests"
}
2 changes: 1 addition & 1 deletion datacenter/ucp/2.0/guides/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ by Docker.
When you deploy UCP, it starts running a globally scheduled service called
`ucp-agent`. This service monitors the node where it is running and starts
and stops UCP services, based on whether that node is a
[manager or a worker node](https://docs.docker.com/engine/swarm/key-concepts/).
[manager or a worker node](/engine/swarm/key-concepts/).

If the node is a:

Expand Down
2 changes: 1 addition & 1 deletion docker-cloud/builds/advanced.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ docker build --build-arg CUSTOM=$VAR -t $IMAGE_NAME
used by the builder, so you must include a similar build command in the hook or
the automated build will fail.

To learn more about Docker build-time variables, see the [docker build documentation]( https://docs.docker.com/engine/reference/commandline/build/#/set-build-time-variables---build-arg).
To learn more about Docker build-time variables, see the [docker build documentation](/engine/reference/commandline/build/#/set-build-time-variables---build-arg).

#### Two-phase build

Expand Down
2 changes: 1 addition & 1 deletion docker-cloud/builds/automated-build.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ the code repository service where the image's source code is stored.

10. For each branch or tag, enable or disable the **Build Caching** toggle.

[Build caching](https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/#/build-cache) can save time if you are building a large image frequently or have many dependencies. You might want to leave build caching disabled to make sure all of your dependencies are resolved at build time, or if you have a large layer that is quicker to build locally.
[Build caching](/engine/userguide/eng-image/dockerfile_best-practices/#/build-cache) can save time if you are building a large image frequently or have many dependencies. You might want to leave build caching disabled to make sure all of your dependencies are resolved at build time, or if you have a large layer that is quicker to build locally.

11. Click **Save** to save the settings, or click **Save and build** to save and
run an initial test.
Expand Down
14 changes: 7 additions & 7 deletions docker-for-windows/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ enabled](troubleshoot.md#virtualization-must-be-enabled) in Troubleshooting.
<p />
* Nested virtualization scenarios, such as running Docker for Windows on a VMWare or Parallels instance, might work, but come with no guarantees (i.e., not officially supported).
<p />
* **What the Docker for Windows install includes**: The installation provides [Docker Engine](https://docs.docker.com/engine/userguide/intro/), Docker CLI client, [Docker Compose](https://docs.docker.com/compose/overview/), and [Docker Machine](https://docs.docker.com/machine/overview/).
* **What the Docker for Windows install includes**: The installation provides [Docker Engine](/engine/userguide/intro.md), Docker CLI client, [Docker Compose](/compose/overview/), and [Docker Machine](/machine/overview.md).

### About Windows containers and Windows Server 2016

Expand Down Expand Up @@ -478,15 +478,15 @@ You can configure options on the Docker daemon in the given JSON configuration f

![Docker Daemon](images/docker-daemon.png)

For a full list of options on the Docker daemon, see <a href="https://docs.docker.com/engine/reference/commandline/dockerd/" target="_blank">daemon</a> in the Docker Engine command line reference.
For a full list of options on the Docker daemon, see [daemon](/engine/reference/commandline/dockerd/){:target="_blank"} in the Docker Engine command line reference.

In that topic, see also:

* [Daemon configuration file](https://docs.docker.com/engine/reference/commandline/dockerd/#/daemon-configuration-file)
* [Daemon configuration file](/engine/reference/commandline/dockerd/#/daemon-configuration-file)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not introduced here, but these should point to the .md file if possible.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mstanleyjones I can fix it if you're sure we should always link to md files

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The correct Markdown should be:

[Daemon configuration file](/engine/reference/commandline/dockerd.md#daemon-configuration-file)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe it expects relative URLs; ../engine/reference/commandline/docker.md#daemon-configuration-file ?


* [Linux configuration file](https://docs.docker.com/engine/reference/commandline/dockerd/#/linux-configuration-file)
* [Linux configuration file](/engine/reference/commandline/dockerd/#/linux-configuration-file)

* [Windows configuration file](https://docs.docker.com/engine/reference/commandline/dockerd/#/windows-configuration-file)
* [Windows configuration file](/reference/commandline/dockerd/#/windows-configuration-file)

Note that updating these settings requires a reconfiguration and reboot of the Linux VM.

Expand Down Expand Up @@ -543,7 +543,7 @@ Server:
##### Custom registries

Also starting with with Beta 34, you can set up your own
[registries](/registry/introduction/) on the **Basic** Daemon settings.
[registries](/registry/introduction.md) on the **Basic** Daemon settings.

As an alternative to using [Docker Hub](https://hub.docker.com/) to store your
public or private images or [Docker Trusted
Expand All @@ -557,7 +557,7 @@ the FAQs.)

The **Advanced** daemon settings provide the original option to directly edit
the JSON configuration file for the <a
href="https://docs.docker.com/engine/reference/commandline/dockerd/"
href="/engine/reference/commandline/dockerd/"
target="_blank">daemon</a>. (This is the only option currently available on stable releases, as described in [Docker daemon](#docker-daemon).)

![Docker Daemon](images/docker-daemon_advanced.png)
Expand Down
2 changes: 1 addition & 1 deletion engine/installation/binaries.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ is `https://get.docker.com/builds/Linux/x86_64/docker-1.11.0.tgz`.
> **Note** These instructions are for Docker Engine 1.11 and up. Engine 1.10 and
> under consists of a single binary, and instructions for those versions are
> different. To install version 1.10 or below, follow the instructions in the
> [1.10 documentation](https://docs.docker.com/v1.10/engine/installation/binaries/){:target="_blank"}.
> [1.10 documentation](/v1.10/engine/installation/binaries/){:target="_blank"}.

#### Verify downloaded files

Expand Down
2 changes: 1 addition & 1 deletion machine/concepts.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ For a complete list of `docker-machine` subcommands, see the [Docker Machine sub

Users using their own Docker Registry will experience `x509: certificate signed by unknown authority`
error messages if their registry is signed by custom root Certificate Authority and it is
not registered with Docker Engine. As discussed in the [Docker Engine documentation](https://docs.docker.com/engine/security/certificates/#/understanding-the-configuration)
not registered with Docker Engine. As discussed in the [Docker Engine documentation](/engine/security/certificates/#/understanding-the-configuration)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As above, link to the .md if possible.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mstanleyjones Same as above... Losing the anchor link

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mstanleyjones Also, one important point. Currently it is somehow better to use a path of this form: https://docs.docker.com/engine/reference/commandline/dockerd/
Instead of https://docs.docker.com/engine/reference/commandline/dockerd.md

Because the non-md form leads you right to the page you want. While the md form returns a terrible 404 error with a client side JS script that takes you to the non-md path...

We already mentioned that in the past, I really think it's an issue for SEO.

But I also think it makes more sense to link to local markdowns within markdowns. Maybe we should just update these links at build time.

certificates should be placed at `/etc/docker/certs.d/hostname/ca.crt`
where `hostname` is your Registry server's hostname.

Expand Down
1 change: 1 addition & 0 deletions tests/src/github.com/gdevillele/frontparser
Submodule frontparser added at f28e87
1 change: 1 addition & 0 deletions tests/src/golang.org/x/net
Submodule net added at 45e771
1 change: 1 addition & 0 deletions tests/src/gopkg.in/yaml.v2
Submodule yaml.v2 added at a5b47d
135 changes: 135 additions & 0 deletions tests/src/validator/html_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
package main

import (
"bytes"
"errors"
"fmt"
"golang.org/x/net/html"
"os"
"path/filepath"
"regexp"
"strings"
"testing"
)

var countLinks = 0
var countImages = 0

// TestURLs tests if we're not using absolute paths for URLs
// when pointing to local pages.
func TestURLs(t *testing.T) {
count := 0

filepath.Walk("/usr/src/app/allvbuild", func(path string, info os.FileInfo, err error) error {

relPath := strings.TrimPrefix(path, "/usr/src/app/allvbuild")

isArchive, err := regexp.MatchString(`^/v[0-9]+\.[0-9]+/.*`, relPath)
if err != nil {
t.Error(err.Error(), "-", relPath)
}
// skip archives for now, only test URLs in current version
// TODO: test archives
if isArchive {
return nil
}

if err != nil {
t.Error(err.Error(), "-", relPath)
}
b, htmlBytes, err := isHTML(path)
if err != nil {
t.Error(err.Error(), "-", relPath)
}
// don't check non-html files
if b == false {
return nil
}

count++

err = testURLs(htmlBytes)
if err != nil {
t.Error(err.Error(), "-", relPath)
}
return nil
})

fmt.Println("found", count, "html files (excluding archives)")
fmt.Println("found", countLinks, "links (excluding archives)")
fmt.Println("found", countImages, "images (excluding archives)")
}

// testURLs tests if we're not using absolute paths for URLs
// when pointing to local pages.
func testURLs(htmlBytes []byte) error {

reader := bytes.NewReader(htmlBytes)

z := html.NewTokenizer(reader)

for {
tt := z.Next()

switch tt {
case html.ErrorToken:
// End of the document, we're done
return nil
case html.StartTagToken:
t := z.Token()

url := ""

// check tag types
switch t.Data {
case "a":
countLinks++
ok, href := getHref(t)
// skip, it may just be an anchor
if !ok {
break
}
url = href

case "img":
countImages++
ok, src := getSrc(t)
if !ok {
return errors.New("img with no src: " + t.String())
}
url = src
}

// there's an url to test!
if url != "" {
if strings.HasPrefix(url, "http://docs.docker.com") || strings.HasPrefix(url, "https://docs.docker.com") {
return errors.New("found absolute link: " + t.String())
}
}
}
}

return nil
}

// helpers

func getHref(t html.Token) (ok bool, href string) {
for _, a := range t.Attr {
if a.Key == "href" {
href = a.Val
ok = true
}
}
return
}

func getSrc(t html.Token) (ok bool, src string) {
for _, a := range t.Attr {
if a.Key == "src" {
src = a.Val
ok = true
}
}
return
}
36 changes: 0 additions & 36 deletions tests/src/validator/markdown_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@ package main
import (
"errors"
"github.com/gdevillele/frontparser"
"io/ioutil"
"os"
"path/filepath"
"strings"
"testing"
)

Expand Down Expand Up @@ -88,37 +86,3 @@ func testFrontMatterKeywords(mdBytes []byte) error {

return nil
}

//-----------------
// utils
//-----------------

// isPublishedMarkdown returns wether a file is a published markdown or not
// as a convenience it also returns the markdown bytes to avoid reading files twice
func isPublishedMarkdown(path string) (bool, []byte, error) {
if strings.HasSuffix(path, ".md") {
fileBytes, err := ioutil.ReadFile(path)
if err != nil {
return false, nil, err
}
if frontparser.HasFrontmatterHeader(fileBytes) {
fm, _, err := frontparser.ParseFrontmatterAndContent(fileBytes)
if err != nil {
return false, nil, err
}
// skip markdowns that are not published
if published, exists := fm["published"]; exists {
if publishedBool, ok := published.(bool); ok {
if publishedBool {
// file is markdown, has frontmatter and is published
return true, fileBytes, nil
}
}
} else {
// if "published" field is missing, it means published == true
return true, fileBytes, nil
}
}
}
return false, nil, nil
}
57 changes: 57 additions & 0 deletions tests/src/validator/utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package main

import (
"github.com/gdevillele/frontparser"
"io/ioutil"
"os"
"strings"
)

// isPublishedMarkdown returns wether a file is a published markdown or not
// as a convenience it also returns the markdown bytes to avoid reading files twice
func isPublishedMarkdown(path string) (bool, []byte, error) {
if strings.HasSuffix(path, ".md") {
fileBytes, err := ioutil.ReadFile(path)
if err != nil {
return false, nil, err
}
if frontparser.HasFrontmatterHeader(fileBytes) {
fm, _, err := frontparser.ParseFrontmatterAndContent(fileBytes)
if err != nil {
return false, nil, err
}
// skip markdowns that are not published
if published, exists := fm["published"]; exists {
if publishedBool, ok := published.(bool); ok {
if publishedBool {
// file is markdown, has frontmatter and is published
return true, fileBytes, nil
}
}
} else {
// if "published" field is missing, it means published == true
return true, fileBytes, nil
}
}
}
return false, nil, nil
}

// isHTML returns wether a file is an html file or not
// as a convenience it also returns the markdown bytes to avoid reading files twice
func isHTML(path string) (bool, []byte, error) {
if strings.HasSuffix(path, ".html") {
fileBytes, err := ioutil.ReadFile(path)
if err != nil {
return false, nil, err
}
return true, fileBytes, nil
}
return false, nil, nil
}

// fileExists returns true if the given file exists
func fileExists(name string) bool {
_, err := os.Stat(name)
return err == nil
}
Loading