-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Update and add onto the Pipeline Handbook chapter #465
Conversation
The sections are ordered from simpler to progressively more complex subjects. | ||
The earlier sections are intended for those new to pipeline or unfamiliar with its | ||
latest features. The later sections with discuss expert-level considerations | ||
and corner-cases. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is intended as a note to contributors. Could we discuss your objections/thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With actual content present in the chapter I believe this stanza looses value and only serves to be confusing to readers.
It is fairly self-evident that the sections are more beginner-oriented ("Getting Started") and subsequent sections become more advanced.
If this is important to you to remain, then I am fine with it existing as a comment in AsciiDoc which would not be rendered in the final product
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, I see your point. I think it is worth keeping as a comment. The same with the "To contributors" note in the getting started section.
integrating continuous delivery pipelines into Jenkins Pipeline provides an | ||
extensible set of tools for modeling simple-to-complex delivery pipelines "as | ||
code" via the Pipeline DSL. | ||
footnoteref:[dsl,link:https://en.wikipedia.org/wiki/Domain-specific_language[Domain-Specific Language]] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"suite of plugins which supports modeling, implementing, and supporting continuous delivery pipelines in Jenkins, via code written in the "Pipeline DSL".
footnoteref:[dsl,link:https://en.wikipedia.org/wiki/Domain-specific_language[Domain-Specific Language]]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO "modeling" and "implementing" are redundant in this context (I might argue that "supporting" would be too).
Not sure the difference you might define between the three.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure either. Just trying to keep the intent, while getting rid of the bit about "simple-to-complex delivery pipelines".
code" via the Pipeline DSL. | ||
footnoteref:[dsl,link:https://en.wikipedia.org/wiki/Domain-specific_language[Domain-Specific Language]] | ||
|
||
Typically, this "Pipeline as Code" would be authored in a `Jenkinsfile` and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
authored in -> written to (or "put in")
("authored by ")
|
||
Some fundamental Pipeline terms such as "step," "node," and "stage" are a | ||
subset of the vocabulary used in Jenkins, but important to be aware of when | ||
reading the remainder of this chapter. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing some words after "Jenkins, but". Not sure what you were intending.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was "ported" from existing Pipeline documentation, I'll just junk the sentence and write something different.
0461f3c
to
ce7dd76
Compare
@bitwiseman resolved most of your comments and rebased atop the latest Still a work-in-progress until I can wrap up the Shared Libraries section and finish tidying the other existing documents |
[glossary] | ||
|
||
Freestyle Job:: | ||
A Freestyle Job |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tautology for the sake of place holder?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, I need to spend more time thinking about a crystal-clear definition for some terms in the glossary 👿
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@rtyler If you're trying to define something and having trouble, try thinking about it as it appears in the wild--who is using it? What do they use it for? What does it do that is unique within the product or feature set? What's the business case for it, ie why do your users care about it?
Thanks. Did a quick pass, looks good so far. |
ff140cc
to
4ce6472
Compare
NOTE: When referring to a Jenkins Pipeline via short-hand ("Pipeline"), it | ||
should always be title-cased. When referring to a conceptual pipeline | ||
("continuous delivery pipeline"), it it should always be lower-cased. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a guideline based on your comment comment to me:
a style thing that should probably not need to be said, but with sections that built into each other, I think there's a need for an "intro"/preamble at the beginning of one chapter section, and an "outtro" at the end
It shouldn't need to be said, but it still needs to be said.
* Jenkins 2.x or later (older versions back to 1.642.3 will work but are not | ||
recommended) | ||
* Pipeline plugin | ||
footnoteref:[pipeline, link:https://plugins.jenkins.io/workflow-aggregator[Pipeline plugin]] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To use Jenkins Pipeline, you will need:
- Jenkins 2.x or later (older versions back to 1.642.3 may work but are not
recommended) - Pipeline plugin
footnoteref:[pipeline, link:https://plugins.jenkins.io/workflow-aggregator[Pipeline plugin]]
|
||
== Defining a Pipeline | ||
|
||
Pipeline Script is written with |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
with -> in
echo 'Hello World' // <2> | ||
} | ||
---- | ||
<1> `node` to allocate an executor and workspace on the Jenkins cluster. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
to allocate -> allocates
} | ||
---- | ||
<1> `node` to allocate an executor and workspace on the Jenkins cluster. | ||
<2> `echo` to echo a simple string in the Console Output. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
to echo -> writes
node { // <1> | ||
echo 'Hello World' // <2> | ||
} | ||
---- |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No // Declarative
produces a warning.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, I think we need to play with the warnings a bit more. There is some documentation which refers explicitly to Pipeline Script.
I'm also not including any Declarative Pipeline in this pass since I expect to merge this before Declarative is made a dependency of the workflow-aggregator
plugin
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So what should go here is something like // Declarartive - TODO
or in the cases where it doesn't apply // Declarartive - Not applicable
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With the current extension, those will result in Decalarive blocks being printed on the page. IMO this is outside the scope of this pull request and should be discussed elsewhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I'm good with that.
<2> `echo` to echo a simple string in the Console Output. | ||
|
||
|
||
[CAUTION] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This block should appear on near line 66, "Enter a name for your Pipeline".
f7cdaa4
to
c8ff612
Compare
@daniel-beck that 'unrelated crap" is what has made it possible to due more useful review on GitHub pages. |
c8ff612
to
f8952f3
Compare
@rtyler Then you create a separate PR, and rebase your stuff once that's merged. Now independent work is in the same PR, making it unreviewable. |
@daniel-beck just for you pumpkin #476 |
|
||
= The Jenkinsfile | ||
|
||
== Audience and Purpose | ||
This section builds on the information covered in <<getting-started#, Getting Started>>, | ||
and introduces more useful steps, common patterns and demonstrates some |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comma after 'common patterns'
what specific steps are needed to perform a job for which you want to use | ||
Jenkins. You create a `Jenkinsfile` with your preferred Groovy editor, or through | ||
the configuration page on the web interface of your Jenkins instance. | ||
As discussed in the <<getting-started#defining-a-pipeline-in-scm, Getting Started>> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First sentence seems to mostly repeat the stuff said in the previous section. I would just remove it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some of the redundancies are intentional, speaking based on my own documentation-reading-habits, I won't necessarily go in chronological order, especially if I have landed on a document from a Google search. #
…Pipeline is Now with more Jenkinsfile!
This commit also rewords and corrects a lot of technical errors in the previous definitions of the terms.
190b56e
to
331822b
Compare
Step:: | ||
A single task; fundamentally steps tell Jenkins _what_ to do. In | ||
order to execute the shell command `make`, the `sh` | ||
step would be used. for example `sh 'make'`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for => For or add a comma
331822b
to
dff332e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor tweaks and typo fixes.
|
||
|
||
When needing to refer to the collection of executors and/or nodes it is best to | ||
refer to them collective as "the Jenkins environment", for example: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
collectively
== Handbook Style Guide | ||
|
||
* With sections that are related/build onto each other. THere should be a | ||
reasonable "intro" or preamble at the beginning of one chapter section and a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
beginning of one section and
The syntax for defining a Pipeline with either approach is the same, but while | ||
Jenkins supports entering Pipeline Script directly into the web UI, it's | ||
generally considered best practice to define the Pipeline in a `Jenkinsfile` | ||
which Jenkins can then load directly from source control. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can -> will
Accordingly, you also have the option of writing pipeline scripts (Jenkinsfiles) | ||
with the editor that you use in your IDE (integrated development environment) or | ||
SCM system, and then loading those scripts into Jenkins using the *Pipeline | ||
Script from SCM* option enabled by the workflow-scm-step plugin, which is one of |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If workflow-scm-step plugin is automatically loaded, do we need to mention it here?
To do this, select *Pipeline script from SCM* when defining the pipeline. | ||
|
||
With the *Pipeline script from SCM* option selected, you do not enter any Groovy | ||
code in the Jenkins UI; you just indicate by specifying a path where in source |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you just indicate by specifying a path where in source code you want to retrieve the pipeline from. -> you just specify a path to a file in source control.
To access additional information and/or documentation about the step selected, | ||
click on the help icon (blue question mark). | ||
|
||
=== Global Variable Reference |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we put a TODO here to move the details about specific global variables below to a different section? This feels a bit odd.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's part of "built-in documentation" though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The info about the globals is part of the built in docs. That first paragraph makes sense here.
But the details about each of the globals belongs in subsection of the general pipeline section.
@@ -110,6 +126,14 @@ By default, all of these use the class name as label, but that can be customized | |||
javadoc:hudson.scm.SCM#all()[a list of all known SCM implementations] | |||
---- | |||
|
|||
== Handbook Style Guide | |||
|
|||
* With sections that are related/build onto each other. THere should be a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For consecutive sections that are related to or build on each other, there should
This commit moves some unrelated portions of the original document into the Multibranch section which is still a work in progress.
This has only been marginally touched up from the original source (https://github.com/jenkinsci/workflow-cps-global-lib-plugin/blob/master/README.md) But will be pruned in future commits
…ve resources This comes after some discussion with @omehegan on how to refer to the concept
…nted Once Declarative is an integral part of Pipeline, these should be updated
I'm not superbly thrilled with this content yet, needs more iteration at a later date
dff332e
to
ce79b63
Compare
code" via the Pipeline DSL. | ||
footnoteref:[dsl,link:https://en.wikipedia.org/wiki/Domain-specific_language[Domain-Specific Language]] | ||
|
||
This section will introduce some of the key concepts to Jenkins Pipeline and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a nit, but "This section will introduce" could just be "This section introduces" Present tense is stronger, and the reader is literally in the section already--no need to talk about what will happen when they're reading right now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Docs edits--mostly grammar and punctuation, with some suggestions on structure.
|
||
|
||
|
||
* In the *Script* text-area, enter a Pipeline script and click *Save*. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
text-area probably does not need to be hypenated. "Text area" or "Text field" would both suffice.
image::hello-world-console-output.png["Click *Console Output* for the Pipeline", role=center] | ||
|
||
The example above shows a successful run of a basic Pipeline created in the Jenkins | ||
web UI, using two valuable steps. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lose "valuable" here, it's fluff. You don't need to sell the value of a product or service in its documentation; the product should speak for itself.
Node and echo are also two familiar terms for most readers of this doc, so reminding everyone how valuable they are is probably overkill.
Accordingly, you also have the option of writing Pipeline scripts | ||
(Jenkinsfiles) with a text editor and then loading those scripts into Jenkins | ||
using the *Pipeline Script from SCM* option. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Proposed rephrase, just to shorten and clarify:
"Complex pipelines are hard to write and maintain within the text area of the Jenkins job configuration page. If necessary, you can write Pipeline scripts (Jenkinsfiles) in a text editor and access them in Jenkins with the Pipeline Script from SCM option."
footnoteref:[shebang, https://en.wikipedia.org/wiki/Shebang_(Unix)] | ||
which text editors, IDEs, GitHub, etc will use to syntax highlight the | ||
`Jenkinsfile` properly as Groovy code. | ||
==== |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this get moved up to the beginning of this section? This tip seems more like instructions for how to prevent a fatal error--so, not optional, and probably worth mentioning as a prerequisite for writing Jenkinsfiles successfully.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it is not a prerequisite for the Pipeline to execute properly and only serves to signal an IDE/editor for syntax highlighting.
|
||
To generate a step snippet with the Snippet Generator: | ||
|
||
. Navigate to the Snippet Generator |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How does one navigate to the snippet generator? First step is vague, unless there's something dead-simple obvious in the image that I can't see. :)
|
||
In the <<jenkinsfile#, previous section>> a `Jenkinsfile` which could be | ||
checked into source control was implemented. This section covers the concept of | ||
*Multibranch* Pipelines which build on the `Jenkinsfile` foundation to provide |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/In the <<jenkinsfile#, previous section>> a Jenkinsfile
which could be checked into source control was implemented.
/In the <<jenkinsfile#, previous section>>, you implemented a Jenkinsfile
which could be checked into source control.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW, I'm avoiding the voice of "you should do X, Y or Z
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Gotcha. Any reason you're defaulting to the passive voice, rather than the second person?
"...was implemented" vs. "you implemented a..."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's more of a style preference for me than anything. Most of the documentation I have read employs passive voice (AFAIK) and it just feels more serious/legit.
For example, I might write a tutorial in second person, "hey you there, I'm going to teach you a think, here's some things you can do, you now know these things"
Whereas "official documentation" feels more officially with passive voice to me
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What other advantages does passive voice get us aside from sounding official-y? I feel it gains us sounding official at the cost of clarity.
If we can get away from passive voice, I vote we do so.
Active voice tends to be shorter and clearer:
The <<jenkinsfile#, previous section>> showed a `Jenkinsfile` which could be
checked into source control.
If we want to use a pronoun, I'd go with "we" rather than "you":
In the <<jenkinsfile#, previous section>>, we implemented a Jenkinsfile which could be checked into source control.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Active voice is fine for me too actually, it's the pronouns I abhor.
My brain is still sufficiently fried from this documentation, that I would suggest you take a pass through this at some point if you wish to change over to active voice.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bitwiseman That's a good suggestion, but I think we could tighten it even further.
In the <<jenkinsfile#, previous section>>, we implemented a Jenkinsfile to check into source control. This section covers the concept of +*Multibranch* Pipelines, which build on that
Jenkinsfile to provide...
@rtyler I'll go through this again today or this weekend and make active voice suggestions. Go unfry your brain!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@scribblingfox - rather than making comments, would you be will to commit your changes and do a PR? If that's too much work, no big deal, but it seems like your suggestions so far have basically been spot-on - you might was well just make them yourself. 😄 Either way, thanks for all the great work!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@scribblingfox - Nice! I knew there was a way to nuke that "could be" but I couldn't quite get there.
I've filed an issue to get this stuff into the style guide where possible.
https://issues.jenkins-ci.org/browse/WEBSITE-268
The *Multibranch Pipeline* project type enables you to implement different | ||
Jenkinsfiles for different branches of the same project. | ||
In a Multibranch Pipeline project, Jenkins automatically discovers, manages and | ||
executes Pipelines for branches which contain a `Jenkinsfile` in source control |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need a period at the end of line 25.
|
||
This eliminates the need for manual Pipeline creation and management, as would | ||
be necessary when, for example, a developer adds a new feature branch. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correcting some overexcited comma use here:
s/This eliminates the need for manual Pipeline creation and management, as would be necessary when, for example, a developer adds a new feature branch.
/This eliminates the need for manual Pipeline creation and management.
appropriate items for each branch in the repository which contains a | ||
`Jenkinsfile`. | ||
|
||
By default, Jenkins will not automatically reindex the repository for branch |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In a surprising deviation from my usual commentary, reindex should actually have an n-dash. :) This is optional, but recommended, since otherwise native English speakers will stumble over the two vowels side-by-side in reindex.
s/reindex/re-index
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you are talking about a hyphen (-
), not an n-dash (–
).
It is a pity that reïndex
has fallen out of fashion. Even the Dutch gave up zeeëend
for zee-eend
. 😞
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@scribblingfox Is there a general guideline we can define for cases like this? I wonder whether this applies to co-ordinate, co-operate, re-invent, re-enter, etc. as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@daniel-beck -
"Reindex" isn't an english word:
https://www.merriam-webster.com/dictionary/suggestions/reindex
https://en.oxforddictionaries.com/search?utf8=%E2%9C%93&filter=dictionary&query=reindex
To a cursory search, most of the others you named come up as non-hyphenated words:
https://www.merriam-webster.com/dictionary/coordinate
https://www.merriam-webster.com/dictionary/cooperate
https://www.merriam-webster.com/dictionary/reinvent
https://www.merriam-webster.com/dictionary/reenter
Merriam-webster certainly isn't the one true measure, but it's a place to start.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bitwiseman AFAICT there's nothing special about reindex over reinvent. It's just that not a lot of (non-technical) people are reindexing a lot. Reinventing (e.g. wheels) is more common. So I expect the only reason you don't find it is its niche usage.
Regarding the others: The New Yorker uses e.g. coöperate and coördinate to make it easier to read for non-native speakers. All variants (hyphen, diaeresis mark, and nothing) are possible spellings. The question is, which do we prefer? Ideally, we're consistent here. It's nice that the style guide now mentions re-index as the preferred spelling, but that's very specific. I'm trying to get something more generally applicable. If that rule is going to be "hyphenate nothing except re-index", that's weird, but also fine. Right now, we have nothing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@daniel-beck - added this to https://issues.jenkins-ci.org/browse/WEBSITE-268
By default, Jenkins will not automatically reindex the repository for branch | ||
additions or deletions (unless using an <<organization-folders,Organization Folder>>), | ||
so it is often useful to configure a Multibranch Pipeline to periodically | ||
reindex in the configuration: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comment as on ll 60.
Resolves WEBSITE-250
A "staging" version of these changes can be found on GitHub Pages (note: image references don't work, that's a known problem when publishing to GitHub Pages)