Skip to content

Commit

Permalink
Merge pull request #61 from Andrew-Chen-Wang/55-move-comments-from-so…
Browse files Browse the repository at this point in the history
…urce-code-to-wiki

Move comments from source code to wiki
  • Loading branch information
jcbhmr authored Jun 9, 2023
2 parents 727fbb2 + 249e319 commit 46a496d
Show file tree
Hide file tree
Showing 5 changed files with 234 additions and 240 deletions.
80 changes: 1 addition & 79 deletions src/clone.sh
Original file line number Diff line number Diff line change
@@ -1,117 +1,39 @@
#!/bin/bash
# Copyright 2023 Jacob Hummer
# SPDX-License-Identifier: Apache-2.0

# Remember, this enables fail-fast mode! We want this for scripts. If a command
# returns a non-zero exit code, this -e makes us exit then-and-there.
set -e
# When a job fails, you can re-run it with debug mode enabled. This is exposed
# to scripts via the ${{ runner.debug }} or $RUNNER_DEBUG variable. Here, we
# use the -n test to see if the $RUNNER_DEBUG exists. If so, we use the -x flag
# to print a '+ cmd arg1 arg2' of each command that's run in the script. This
# helps with debugging what commands and $VAR expansions are actually happening.
if [[ -n $RUNNER_DEBUG ]]; then
set -x
fi

# We overwrite the $GITHUB_* environment variables with user-provided ones.
# GitHub Actions normally provides a bunch of $GITHUB_* env vars. These can
# be used in scripts to tailor them to the current GitHub thing (repo, issue,
# etc). Here, we want to use these same variables, but with our custom
# user-provided values instead. We overwrite the originals (in this process;
# we can't affect our parent process) with the user-provided (or default)
# values so that we can use the same $GITHUB_REPOSITORY semantics to refer to
# the current repo that the action is on (the default) or the user-provided
# repo that we want to use instead. We use the same var names to make it
# familiar.
export GITHUB_TOKEN="$INPUT_TOKEN"
export GITHUB_SERVER_URL="$INPUT_GITHUB_SERVER_URL"
export GITHUB_REPOSITORY="$INPUT_REPOSITORY"
# This is the default host that gh uses for clones and commands without a repo
# context (a .git folder). We use Bash string magic to get the github.com part
# from a full origin (no pathname) like https://github.com => github.com. The
# '#*//' operation removes '*//' from the start of the string. That's the
# 'https://' chunk. With that gone, we are left with 'github.company.com' or
# something similar.
export GH_HOST="${GITHUB_SERVER_URL#*//}"

# We configure some special $GIT_* environment variables to make it so that
# we can have our special .git folder (you know, the one that holds all the
# critical repo information & history?) in a completely different location
# from our working tree! Normally, $GIT_DIR is automagically determined by
# walking up the folders from your $PWD until '.git/' is found. In this case,
# we want that in a temp folder. Then, we use $GIT_WORK_TREE to control what
# the base folder or "root" of the $GIT_DIR's repo should be. Normally, this
# would be the $PWD, but we want to set it to the $INPUT_PATH which is
# probably a subfolder of the project somwhere!
export GIT_DIR && GIT_DIR=$(mktemp -d)
export GIT_WORK_TREE="$INPUT_PATH"
# This is just good practice to clean up after yourself. It's not needed per-se.
# This is a one-off Actions runner that will delete every part of itself after
# completion. It's a good habit nonetheless.
trap 'rm -rf "$GIT_DIR"' SIGINT SIGTERM ERR EXIT

# This setup-git is a command is what makes it so that we can be authorized to
# do normal 'git clone' and 'git push' operations without using the gh CLI. It
# auto-adds the credentials for the host in $GH_HOST and any additional --host
# options passed to it. We need this to make it so that our 'git push' at the
# end of this script works!
gh auth setup-git
# We also need to preemptively mark the $GIT_DIR as safe to use. Normally Git
# will protect you against doing insecure stuff in untrusted areas, and that's
# a good thing! In this case, though, we know that what we are doing in this
# temp folder is OK.
git config --global --add safe.directory "$GIT_DIR"

# We clone the $GITHUB_REPOSITORY.wiki Git repo into a temp folder. This is
# a special Git repository that holds a flat file structure of markup files
# that are rendered on the Wiki tab in the GitHub web UI. We clone this repo
# into the aforementioned $GIT_DIR folder. We use the --bare option to make
# the underlying 'git clone' command that's run create just a .git folder
# without pulling out all the initial files (which is the default behaviour).
# So, we'll have a .git-like folder sitting in /tmp/id.1234 which we want to
# use as our .git folder that we commit to and use for the rest of the Git
# stuff. The $GIT_WORK_TREE is already set to use the $INPUT_PATH (likely a
# folder like 'wiki/').
git clone "$GITHUB_SERVER_URL/$GITHUB_REPOSITORY.wiki.git" "$GIT_DIR" --bare
# This is a trick to make the git CLI think that there should be a worktree too!
# By default, --bare Git repos are pretty inert. We unset this and then use our
# previously configured $GIT_WORK_TREE.
git config --unset core.bare

# We are using .gitignore syntax for the 'ignore' option. Here's where we put it
# to good use! We then immediately add everything verbosely to "apply" it.
echo "$INPUT_IGNORE" >>"$GIT_DIR/info/exclude"
git add -Av

# This sets the default author & committer for the Git commit that we make. If
# you want to change this, you can! You can set the $GIT_AUTHOR_* and
# $GIT_COMMITTER_* env vars in your workflow and they should pass down to this
# 'git commit' operation. These values are from one of the popular Git commit
# actions: stefanzweifel/git-auto-commit-action [1]
#
# [1]: https://github.com/stefanzweifel/git-auto-commit-action/blob/master/action.yml#L35-L42
# https://github.com/stefanzweifel/git-auto-commit-action/blob/master/action.yml#L35-L42
git config user.name github-actions[bot]
git config user.email 41898282+github-actions[bot]@users.noreply.github.com
# Allowing an empty commit is way easier than detecting empty commits! This also
# makes semantic sense. If you run this action, it adds a commit to your wiki.
# How large that commit is comes down to your changes. 0 change = commit with 0.
# This works well with the default "Update wiki ${{ github.sha }}" message so
# that even if the commit is empty, the message has the SHA there.
git commit --allow-empty -m "$INPUT_COMMIT_MESSAGE"

# If we are given 'dry-run: true', then we want to just print changes and stop
# without pushing. This is only used in testing right now.
if [[ $INPUT_DRY_RUN == true ]]; then
echo 'Dry run'
git remote show origin
git show
exit 0
fi

# This is the pushing operation! The origin remote looks something like:
# "https://github.com/octocat/awesome.wiki.git" with no token attached. That
# 'gh auth setup-git' is what makes the username & password automagically attach
# to that 'github.com' hostname! We aren't using -u or -f here since there
# shouldn't be a need.
git push origin master
45 changes: 0 additions & 45 deletions src/init.sh
Original file line number Diff line number Diff line change
@@ -1,66 +1,21 @@
#!/bin/bash
# Copyright 2023 Jacob Hummer
# SPDX-License-Identifier: Apache-2.0

# Remember, this enables fail-fast mode! We want this for scripts. If a command
# returns a non-zero exit code, this -e makes us exit then-and-there.
set -e
# When a job fails, you can re-run it with debug mode enabled. This is exposed
# to scripts via the ${{ runner.debug }} or $RUNNER_DEBUG variable. Here, we
# use the -n test to see if the $RUNNER_DEBUG exists. If so, we use the -x flag
# to print a '+ cmd arg1 arg2' of each command that's run in the script. This
# helps with debugging what commands and $VAR expansions are actually happening.
if [[ -n $RUNNER_DEBUG ]]; then
set -x
fi

# We overwrite the $GITHUB_* environment variables with user-provided ones.
# GitHub Actions normally provides a bunch of $GITHUB_* env vars. These can
# be used in scripts to tailor them to the current GitHub thing (repo, issue,
# etc). Here, we want to use these same variables, but with our custom
# user-provided values instead. We overwrite the originals (in this process;
# we can't affect our parent process) with the user-provided (or default)
# values so that we can use the same $GITHUB_REPOSITORY semantics to refer to
# the current repo that the action is on (the default) or the user-provided
# repo that we want to use instead. We use the same var names to make it
# familiar.
export GITHUB_TOKEN="$INPUT_TOKEN"
export GITHUB_SERVER_URL="$INPUT_GITHUB_SERVER_URL"
export GITHUB_REPOSITORY="$INPUT_REPOSITORY"
# This is the default host that gh uses for clones and commands without a repo
# context (a .git folder). We use Bash string magic to get the github.com part
# from a full origin (no pathname) like https://github.com => github.com. The
# '#*//' operation removes '*//' from the start of the string. That's the
# 'https://' chunk. With that gone, we are left with 'github.company.com' or
# something similar.
export GH_HOST="${GITHUB_SERVER_URL#*//}"

# We configure some special $GIT_* environment variables to make it so that
# we can have our special .git folder (you know, the one that holds all the
# critical repo information & history?) in a completely different location
# from our working tree! Normally, $GIT_DIR is automagically determined by
# walking up the folders from your $PWD until '.git/' is found. In this case,
# we want that in a temp folder. Then, we use $GIT_WORK_TREE to control what
# the base folder or "root" of the $GIT_DIR's repo should be. Normally, this
# would be the $PWD, but we want to set it to the $INPUT_PATH which is
# probably a subfolder of the project somwhere!
export GIT_DIR && GIT_DIR=$(mktemp -d)
export GIT_WORK_TREE="$INPUT_PATH"
# This is just good practice to clean up after yourself. It's not needed per-se.
# This is a one-off Actions runner that will delete every part of itself after
# completion. It's a good habit nonetheless.
trap 'rm -rf "$GIT_DIR"' SIGINT SIGTERM ERR EXIT

# This setup-git is a command is what makes it so that we can be authorized to
# do normal 'git clone' and 'git push' operations without using the gh CLI. It
# auto-adds the credentials for the host in $GH_HOST and any additional --host
# options passed to it. We need this to make it so that our 'git push' at the
# end of this script works!
gh auth setup-git
# We also need to preemptively mark the $GIT_DIR as safe to use. Normally Git
# will protect you against doing insecure stuff in untrusted areas, and that's
# a good thing! In this case, though, we know that what we are doing in this
# temp folder is OK.
git config --global --add safe.directory "$GIT_DIR"

git init -b master
Expand Down
124 changes: 8 additions & 116 deletions wiki/Home.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,121 +3,13 @@ Copyright 2023 Jacob Hummer
SPDX-License-Identifier: Apache-2.0
-->

## How `${{ github.token }}` works
👋 Hello! Welcome to our dual-purpose test wiki & dev wiki! If you're seeing
this in the <kbd>Wiki</kbd> tab, then the GitHub Action successfully pushed the
contents of the `wiki/` folder to the GitHub wiki. 🥳

When you interact with GitHub stuff, you need to be authenticated. In a GitHub
Action, this means using the `${{ github.token }}`.
To learn more about how this action works, check out the [How it works] page.
If you're more interested in using this action, head back to the [README] to get
started using it in your own repository! 🚀

The `${{ github.token }}` is a special access token that you can use to
authenticate on behalf of GitHub Actions. GitHub automatically creates
`${{ github.token }}` secret for you to use in your workflow, and you can use
it to authenticate in a workflow run.

The way this works is that when you enable GitHub Actions in a repository,
GitHub installs a GitHub App on your repository.
The `${{ github.token }}` secret is a GitHub App installation access token. You
can use the installation access token to authenticate on behalf of the GitHub
App installed on your repository. The token's permissions are limited to the
repository that contains your workflow.

Before each job begins, GitHub fetches an installation access token for the
job. The `${{ github.token }}` expires when a job finishes or after a maximum of
24 hours.

The token is also available as the `$GITHUB_TOKEN` env variable in most places
without needing to be explicitly passed around.

### Best practices

You can use the `${{ github.token }}` by using the standard syntax for
referencing secrets: `${{ secrets.GITHUB_TOKEN }}`. You can pass the token as an
input to an action, or use it to make an authenticated GitHub API request. If
you are using a custom PAT, you should also avoid hardcoding the token value in
your workflow file or scripts. Instead, use `${{ secrets.MY_PAT }}`.

Modern GitHub Actions will also default to using the current workflow's
`${{ github.token }}` value if non is provided by the user. This implicit token
passing makes workflows drasticly simpler. As a good security practice, you
should always make sure that actions only have the minimum access they require
by limiting the permissions granted to the `${{ github.token }}`.

### How it's generated

The `${{ github.token }}` is not a personal access token. It is a GitHub App
installation access token that is automatically created by GitHub when you
enable GitHub Actions in a repository.

You do not need to create or manage the token yourself. You also do not need to
renew or rotate the token, as GitHub does that for you before each job.

### Permissions

| Scope | Permissive | Restricted | Max fork perms |
| ------------------- | ---------- | ---------- | -------------- |
| actions | read/write | | read |
| checks | read/write | | read |
| contents | read/write | read | read |
| deployments | read/write | | read |
| id-token | | | read |
| issues | read/write | | read |
| metadata | read | read | read |
| packages | read/write | read | read |
| pages | read/write | | read |
| pull-requests | read/write | | read |
| repository-projects | read/write | | read |
| security-events | read/write | | read |
| statuses | read/write | | read |

You can change any of these permissions using the `permissions:` option in your
workflow `.yml` files.

```yaml
permissions:
issues: write
contents: read
```
### Authentication
You can use the `${{ github.token }}` to authenticate on the command line when
cloning a repository. You can enter the token instead of your password when
performing Git operations over HTTPS.

For example, on the command line you would enter the following:

```sh
git clone https://github.com/username/repo.git
```

```
Username: your_username
Password: your_token
```
You can also use the token as part of the URL, like this:
```sh
git clone https://your_username:[email protected]/username/repo.git
```

However, this is less secure and not recommended, as the token may be exposed in
plain text or in your shell history.

If you are not prompted for your username and password, your credentials may be
cached on your computer. You can update your credentials in the Keychain or
Credential Manager to replace your old password with the token.

Alternatively, you can use a credential helper to cache your token with a Git
client.

```sh
gh auth setup-git
```

You can use the runner builtin `gh` CLI to configure `git` to use GitHub CLI as
a credential helper for all authenticated hosts. Alternatively, you can use
the `--hostname` flag to specify a single host to be configured.

📚 Further reading: [Git - gitcredentials Documentation]

[Git - gitcredentials Documentation]: https://git-scm.com/docs/gitcredentials
[How it works]: How-it-works
[README]: https://github.com/Andrew-Chen-Wang/github-wiki-action#readme
Loading

0 comments on commit 46a496d

Please sign in to comment.