Guide On Format, Lint And Typecheck Github Actions For Astro
Published on:
Updated on:
read
If you have an Astro↗ project setup with Prettier↗, ESLint↗ and Typescript↗ and wanted to run a Github Action which checks for formatting, linting and typechecking, here’s guide which will help you in setup.
What is Github Action?
Github action are basically workflows which you can run in your repository. We can use existing workflows or create a custom one based on our project. Check out their docs for full guide https://docs.github.com/en/actions↗
Getting Started
In this guide we are using pnpm↗ as package manager. You can replace it with npm or yarn if you want.
Also in your package.json
add packageManager
value to pnpm
to let Github Action know that we are using pnpm as package manager.
package.json
{
"packageManager": "pnpm@9.12.3" // Add your preferred version
}
Setup Prettier
If you don’t have Prettier and installed in your project install it with by running the following command:
pnpm add -D prettier
To format .astro
files install Astro official prettier plugin prettier-plugin-astro↗.
pnpm add -D prettier-plugin-astro
Now, create a prettier.config.cjs
config file in root of your project and add the following content:
prettier.config.cjs
/**
* @type {import('prettier').Config}
*/
const config = {
arrowParens: "always",
printWidth: 80,
singleQuote: false,
jsxSingleQuote: false,
semi: true,
trailingComma: "all",
tabWidth: 2,
plugins: ["prettier-plugin-astro"],
overrides: [
{
files: "*.astro",
options: {
parser: "astro",
},
},
],
};
module.exports = config;
You can modify the config based on your project requirements.
Add two format script command in your package.json
to format and check formatting:
package.json
{
"scripts": {
"format": "prettier '**/*.{cjs,mjs,ts,tsx,md,mdx,json,astro}' --ignore-path ./.gitignore --ignore-unknown --write",
"format:check": "prettier '**/*.{cjs,mjs,ts,tsx,md,mdx,json,astro}' --ignore-path ./.gitignore --ignore-unknown --check"
}
}
Here, format
script will format all the files in the project and format:check
will check if the files are formatted correctly. Also we have set ignore path to ./.gitignore
means those will be ignored.
Creating Format Github Action
Now, let’s create a Github Action to run the format check.
.github/workflows/format-ci.yml
name: Format CI
on:
pull_request:
branches: ["*"]
merge_group:
jobs:
prettier:
runs-on: ubuntu-latest
name: Run prettier
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- uses: pnpm/action-setup@v3
name: Install pnpm
id: pnpm-install
with:
run_install: false
- name: Get pnpm store directory
id: pnpm-cache
run: |
echo "pnpm_cache_dir=$(pnpm store path)" >> $GITHUB_OUTPUT
- uses: actions/cache@v4
name: Setup pnpm cache
with:
path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-
- name: Install dependencies
run: pnpm install
- run: pnpm format:check
Workflow steps:
- Checkout the repository code
- Install Node.js
- Install pnpm
- Set up pnpm cache to speed up dependency installation
- Install project dependencies using pnpm
- Run
pnpm format:check
to verify code formatting
We are caching the installed dependencies with actions/cache↗ which will make it run faster on subsequent runs.
Note: for npm and yarn you have to cache their lock file
package-lock.json
oryarn.lock
.
Similarly, Let’s setup ESLint.
Setup ESLint
Install ESLint in your project with by running the following command:
pnpm add -D eslint
I recommend using eslint-plugin-astro↗ for Astro components. Also since we are using typescript we will install @typescript-eslint/parser
too.
pnpm add -D eslint-plugin-astro @typescript-eslint/parser
Create a eslint.config.cjs
config file in root of your project and add the following content:
eslint.config.cjs
import eslintPluginAstro from "eslint-plugin-astro";
export default [...eslintPluginAstro.configs.recommended];
Modify the config based on your project requirements.
Add two lint script command in your package.json
to lint and check linting:
package.json
{
"scripts": {
"lint:fix": "pnpm lint --fix",
"lint": "eslint . --report-unused-disable-directives"
}
}
Here, lint
script will check for lint errors and lint:fix
to fix lint errors.
Creating Lint Github Action
Now, let’s create a Github Action to run the lint check.
.github/workflows/lint-ci.yml
name: Lint CI
on:
pull_request:
branches: ["*"]
merge_group:
jobs:
lint:
runs-on: ubuntu-latest
name: Run ESLint
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- uses: pnpm/action-setup@v3
name: Install pnpm
id: pnpm-install
with:
run_install: false
- name: Get pnpm store directory
id: pnpm-cache
run: |
echo "pnpm_cache_dir=$(pnpm store path)" >> $GITHUB_OUTPUT
- uses: actions/cache@v4
name: Setup pnpm cache
with:
path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-
- name: Install dependencies
run: pnpm install
- run: pnpm lint
Now, Let’s create TypeCheck Github Action.
Creating TypeCheck Github Action
TypeCheck Github Action is pretty simple we don’t need to install any other packages cause astro does already have astro check
command which we can use to do typechecking.
Add typecheck
script command in your package.json
to do typechecking:
package.json
{
"scripts": {
"typecheck": "astro check"
}
}
Create typecheck-ci.yml
file and add the following content:
.gitub/workflows/typecheck-ci.yml
name: Typecheck CI
on:
pull_request:
branches: ["*"]
merge_group:
jobs:
prettier:
runs-on: ubuntu-latest
name: Run prettier
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- uses: pnpm/action-setup@v3
name: Install pnpm
id: pnpm-install
with:
run_install: false
- name: Get pnpm store directory
id: pnpm-cache
run: |
echo "pnpm_cache_dir=$(pnpm store path)" >> $GITHUB_OUTPUT
- uses: actions/cache@v4
name: Setup pnpm cache
with:
path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-
- name: Install dependencies
run: pnpm install
- run: pnpm typecheck
If you don’t want to create a separate yml
workflow file for each separately you can create one ci.yml
that does the same.
.github/workflows/ci.yml
name: CI
on:
pull_request:
branches: ["*"]
merge_group:
jobs:
prettier:
runs-on: ubuntu-latest
name: Run prettier
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- uses: pnpm/action-setup@v3
name: Install pnpm
id: pnpm-install
with:
run_install: false
- name: Get pnpm store directory
id: pnpm-cache
run: |
echo "pnpm_cache_dir=$(pnpm store path)" >> $GITHUB_OUTPUT
- uses: actions/cache@v4
name: Setup pnpm cache
with:
path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-
- name: Install dependencies
run: pnpm install
- run: pnpm format:check
lint:
runs-on: ubuntu-latest
name: Run ESLint
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- uses: pnpm/action-setup@v3
name: Install pnpm
id: pnpm-install
with:
run_install: false
- name: Get pnpm store directory
id: pnpm-cache
run: |
echo "pnpm_cache_dir=$(pnpm store path)" >> $GITHUB_OUTPUT
- uses: actions/cache@v4
name: Setup pnpm cache
with:
path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-
- name: Install dependencies
run: pnpm install
- run: pnpm lint
typecheck:
runs-on: ubuntu-latest
name: Run Typecheck
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- uses: pnpm/action-setup@v3
name: Install pnpm
id: pnpm-install
with:
run_install: false
- name: Get pnpm store directory
id: pnpm-cache
run: |
echo "pnpm_cache_dir=$(pnpm store path)" >> $GITHUB_OUTPUT
- uses: actions/cache@v4
name: Setup pnpm cache
with:
path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-
- name: Install dependencies
run: pnpm install
- run: pnpm typecheck
Now, whenever a new pull request is created in your github repository it will run this workflows.
Thank you for reading this and I hope you liked it!