How to automate and publish docs in CI (github actions)? - github-actions

I want to automate the build and publishing of the docs of an open source typescript project hosted on Github.
I tried TypeDoc and the generated docs folder is 23Mo. I don't want to commit it in the project's repo.
Ideally, on each release, I would like to use github actions to:
generate the docs
push that generated docs folder to its own github repo.
Currently I added a npm script to generate the docs: docs: typedoc --out docs src and here is the starting point of my github action file:
name: Docs
on:
release:
branches:
- master
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout#v1
- name: Use Node.js
uses: actions/setup-node#v1
with:
node-version: 12
- name: Generate docs
run: |
npm ci
npm run docs
From this action, how can I commit and push this generated directory to its own repo on github?
(Maybe there is a more conventional way to do that. Let me know)

If you want to commit and push changes, you can refer to some actions in the Github's marketplace like github-push or push changes to see if they are fitting your situation. Also, you can write your own script to call Github's API, e.g. I use Pygithub to call Github's APT to help me generate changelog and update the file in the repo.

You can use the github-action-push-to-another-repository action for this purpose:
- name: Pushes to another repository
uses: cpina/github-action-push-to-another-repository#main
env:
API_TOKEN_GITHUB: ${{ secrets.API_TOKEN_GITHUB }}
with:
source-directory: <directory-where-the-dist-is-generated>
destination-github-username: <github-username>
destination-repository-name: <github-repository-name>
user-email: <github-email>
target-branch: <main/master>

Related

How to upload artifacts to existing release?

My workflow has automatic packaging and upload steps that package build artifacts and upload them to the workflow page. I also manually create releases.
I would like to do the following:
when I push to the tag that was created with a given release,
I would like to upload the zipped artifact file to that release, so users can download
the artifact. Any tips on how to do this ?
Here is my build yaml file.
Thanks!
Turns out it's dead simple to do this:
- name: upload binaries to release
uses: softprops/action-gh-release#v1
if: ${{startsWith(github.ref, 'refs/tags/') }}
with:
files: build/FOO.zip
It seems the action (softprops/action-gh-release#v1) mentioned also creates a release. But there is a much simpelere way upload an artifact to a release without the need of introducing action. The gh cli which is by default available on a GitHub hosted runners can upload the artifact for you.
assets:
name: upload assets
runs-on: ubuntu-latest
permissions:
contents: write # release changes require contents write
steps:
- uses: actions/checkout#v3
- name: Upload Release Asset
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run:
gh release upload <release_tag> <a_file>
Checkout full release example here.

Github action to lint after commit in previous step

I'm setting up Github action to lint the OpenAPI Spec using Spectral. Before linting, I would like to generate the single file spec and commit it.
I have set up a workflow that will first build and then lint. But the problem is, the lint is not considering the commit made by Github action in the previous step. It always lint for the commit that triggered this action. Is there any way to lint with the commit made as part of Github action?
You can see from the above image that Github workflow didn't run for the commit made by Github action.
Workflow file:
name: Run Spectral
on:
- pull_request
jobs:
build:
name: Build Spec
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout#v2
- name: Set up Node.js
uses: actions/setup-node#v1
with:
node-version: 12.x
- name: Install dependencies
run: npm install
- name: Build spec file
run: npm run build
- name: Commit build changes
uses: EndBug/add-and-commit#v7
with:
default_author: github_actions
message: 'Compiled spec file'
add: '_build/oas.yaml'
lint:
name: Lint
runs-on: ubuntu-latest
needs: build
steps:
- name: Checkout Repository
uses: actions/checkout#v2
- name: Spectral Linting
uses: stoplightio/spectral-action#v0.7.3
with:
file_glob: '_build/oas.yaml'
That's because commits made using the standard GITHUB_TOKEN aren't triggering workflows; you have to use a personal access token for an automated workflow that's supposed to kick off another workflow.
Quoting from the docs (linked above):
When you use the repository's GITHUB_TOKEN to perform tasks on behalf of the GitHub Actions app, events triggered by the GITHUB_TOKEN will not create a new workflow run. This prevents you from accidentally creating recursive workflow runs. [...]
If you would like to trigger a workflow from a workflow run, you can trigger the event using a personal access token. [...]

Does a job inside Github Action already have access to its repo contents?

I wanted to zip my entire repo using Github Action Workflow. So my question is, does the repository already available inside a job? Or do I need to install git and clone the repository to a location on the runner/container?
You can checkout the repository with the actions/checkout action. This will make your repository available for subsequent steps in the job.
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout#v2

Triggering a new workflow from another workflow?

Can I trigger a new workflow from another workflow?
I'm trying to run a workflow after the first workflow has pushed a new release and it seems to ignore it.
Found the answer here:
An action in a workflow run can't trigger a new workflow run. For example, if an action pushes code using the repository's GITHUB_TOKEN, a new workflow will not run even when the repository contains a workflow configured to run when push events occur.
EDIT:
The quote above might be confusing. When I add a Personal Access Token (PAT) to the checkout action with repo permissions granted (and not repository's GITHUB_TOKEN), the following commands DO trigger other workflows:
- name: Checkout Repo
uses: actions/checkout#v2
with:
token: ${{ secrets.PAT_TOKEN }}
(In my case, running semnatic-release after this checkout, which creates a new release with a new tag - did trigger another workflow that runs only if a tag was created)
As described here, you can trigger another workflow using the workflow_run event.
For example we could think of two workflow definitions like this (the only prerequisite is, that both reside in the same repository - but I'am sure, there's also an event for other repos as well):
release.yml
name: CI release
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout#v2
- name: Release artifact
run: ...
do-something-different.yml
name: Do anything after the release of the first workflow
on:
workflow_run:
workflows: ["CI release"]
types:
- completed
jobs:
notify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout#v2
- name: Do something
run: ...
A crucial point here is that the name: CI release definition of the first yaml file must exactly match the workflow_run: workflows: ["CI release"] definition in the second yaml file. Another point is that this approach needs to be done on the default branch (which is mostly main or master) as the docs state:
Note: This event will only trigger a workflow run if the workflow file
is on the default branch.
If you don't want to use a general Personal Access Token (which has access to all of your repos), you can generate a dedicated SSH keypair for this purpose and add it to the repository as a Deploy Key. This is done as follows:
Generate an SSH keypair:
ssh-keygen -N "" -f deploy_key -C "github-actions"
Add the private key (generated file deploy_key) as an encryped secret, e.g. COMMIT_KEY to the GitHub project.
Add the public key (generated file deploy_key.pub) as a deploy key with write access to the GitHub project. Tick the Allow write access checkbox.
When checking out the source code in your workflow, add the SSH key:
- name: Checkout
uses: actions/checkout#v3
with:
ssh-key: "${{secrets.COMMIT_KEY}}"
Subsequent push actions in the same workflow will then trigger any configured GitHub workflow as if they were pushed manually.

How can I reference other actions from my GitHub Action's action.yml file?

Is it possible to reference another GitHub Action from my action.yml file?
Note, I'm talking about an action here, not a workflow. I know this can be done with workflows, but can actions reference other actions?
The answer seems to be: You can (now, Aug. 2021)
GitHub Actions: Reduce duplication with action composition
Previously, actions written in YAML could only use scripts.
Now, they can also reference other actions.
This makes it easy to reduce duplication in your workflows.
For example, the following action uses 3 actions to setup buildx, log in to Docker, and publish an image.
By combining these into a single action it provides a larger unit of reuse that you can put into the job of any workflow.
name: "Publish to Docker"
description: "Pushes built artifacts to Docker"
inputs:
registry_username:
description: “Username for image registry”
required: true
registry_password:
description: “Password for image registry”
required: true
runs:
using: "composite"
steps:
- uses: docker/setup-buildx-action#v1
- uses: docker/login-action#v1
with:
username: ${{inputs.registry_username}}
password: ${{inputs.registry_password}}
- uses: docker/build-push-action#v2
with:
context: .
push: true
tags: user/app:latest
Developers can then reference this action in all of their repositories as a single action:
on: [push]
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout#v2
- uses: my-org/publish-docker#v1
with:
registry_username: ${{secrets.REGISTRY_USERNAME}}
registry_password: ${{secrets.REGISTRY_PASSWORD}}
Learn more about action composition.
So, as described in "runs for composite actions":
runs.steps[*].uses
[Optional] Selects an action to run as part of a step in your job.
An action is a reusable unit of code.
You can use an action defined in the same repository as the workflow, a public repository, or in a published Docker container image.
We strongly recommend that you include the version of the action you are using by specifying a Git ref, SHA, or Docker tag number.
If you don't specify a version, it could break your workflows or cause unexpected behavior when the action owner publishes an update.
runs:
using: "composite"
steps:
# Reference a specific commit
- uses: actions/checkout#a81bbbf8298c0fa03ea29cdc473d45769f953675
# Reference the major version of a release
- uses: actions/checkout#v2
# Reference a specific version
- uses: actions/checkout#v2.2.0
# Reference a branch
- uses: actions/checkout#main
# References a subdirectory in a public GitHub repository at a specific branch, ref, or SHA
- uses: actions/aws/ec2#main
# References a local action
- uses: ./.github/actions/my-action
# References a docker public registry action
- uses: docker://gcr.io/cloud-builders/gradle
# Reference a docker image published on docker hub
- uses: docker://alpine:3.8
The answer seems to be: You can't.
However, I ended up internally downloading the different actions from NPM, and then re-using them within my own action.
Probably not a good idea in general, but this particular action I am making is designed to run on my own projects without requiring too much configuration, so that makes it more okay.
If both actions are nodejs actions you are serving over GitHub and you don't mind them reading the one set of input, this works pretty well:
npm install --save MyGitHubOrg/MyRepo#master
git add -f node_modules/ package.json package-lock.json
async function run() {
try {
require('my-action');
} catch (err) {
core.setFailed(`Failed to run habitat-action: ${err.message}`);
return;
}
// ...
}