Skip to content
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
52 changes: 51 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,62 @@ name: test
on:
push:
branches: [main, master]
pull_request:
workflow_dispatch:
permissions:
contents: read
concurrency:
group: pages
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
- os: ubuntu-latest
path: docs
version: 9.25.0
options: -v --output=public
- os: macos-latest
- os: windows-latest
runs-on: ${{ matrix.os }}
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Create a dummy page
shell: bash
run: |
mkdir -p "${{ matrix.path || '.' }}/pages"
cat > "${{ matrix.path || '.' }}/pages/index.md" <<EOL
This is a test page for the Cecil GitHub Action.
EOL
- name: Run Action
id: cecil
uses: ./
with:
path: ${{ matrix.path || '.' }}
version: ${{ matrix.version }}
options: ${{ matrix.options || '-v' }}
pages: false
- name: Check output
shell: bash
env:
OUTPUT_DIR: ${{ steps.cecil.outputs.output_dir }}
CECIL_VERSION: ${{ steps.cecil.outputs.cecil_version }}
EXPECTED_VERSION: ${{ matrix.version }}
run: |
echo "Cecil $CECIL_VERSION, output: $OUTPUT_DIR"
test -f "$OUTPUT_DIR/index.html"
if [[ -n "$EXPECTED_VERSION" ]]; then
test "$CECIL_VERSION" = "$EXPECTED_VERSION"
fi
build:
if: github.event_name != 'pull_request'
permissions:
contents: read
pages: read
runs-on: ubuntu-latest
steps:
- name: Checkout
Expand Down
51 changes: 45 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,40 @@ This GitHub Action builds a [_Cecil_](https://cecil.app) site and uploads a GitH

```yaml
- name: Build site
uses: Cecilapp/Cecil-Action@v4
uses: Cecilapp/Action@v4
# optional
with:
path: docs # default: "." (repository root)
version: 8.0.0 # default: latest version
version: 9.25.0 # default: latest version
php_version: "8.4" # default: "8.3"
install_themes: "yes" # default: "yes"
options: -v --config=config.yml # default: "-v" (verbose)
pages: "true" # default: "true"
cache: "true" # default: "true"
```

### Inputs

| Name | Description | Default |
| ---------------- | --------------------------------------------------------------------------------------------- | -------- |
| `path` | Path to the site source directory, relative to the repository root. | `.` |
| `version` | Cecil version (e.g. `9.25.0`). | latest |
| `php_version` | PHP version (Cecil requires PHP 8.3+ since version 9). | `8.3` |
| `install_themes` | Set to `no` to skip installing theme(s) with Composer (when a `composer.json` file exists). | `yes` |
| `options` | Cecil `build` command options. `--baseurl` is set to the GitHub Pages URL unless provided. | `-v` |
| `pages` | Set to `false` to skip GitHub Pages setup and artifact upload (e.g. to deploy elsewhere). | `true` |
| `cache` | Set to `false` to disable Cecil (`.cache`) and Composer cache. | `true` |

> [!NOTE]
> If the output directory is changed in the configuration file, also set it with the `--output` option so the Action can find it.

### Outputs

| Name | Description |
| --------------- | ---------------------------------------- |
| `output_dir` | Path to the generated site directory. |
| `cecil_version` | Version of Cecil used to build the site. |

### Workflow example

The following workflow:
Expand All @@ -26,9 +51,10 @@ The following workflow:
3. setup PHP
4. downloads Cecil
5. installs theme(s)
6. runs Cecil build
7. upload pages artifact
8. deploys to GitHub Pages
6. configures GitHub Pages
7. runs Cecil build
8. upload pages artifact
9. deploys to GitHub Pages

```yaml
name: Build and deploy to GitHub Pages
Expand All @@ -46,7 +72,7 @@ jobs:
- name: Checkout source
uses: actions/checkout@v6
- name: Build site
uses: Cecilapp/Cecil-Action@v4
uses: Cecilapp/Action@v4
deploy:
needs: build
permissions:
Expand All @@ -62,6 +88,19 @@ jobs:
uses: actions/deploy-pages@v5
```

### Without GitHub Pages

```yaml
- name: Build site
id: cecil
uses: Cecilapp/Action@v4
with:
pages: false
options: -v --baseurl=https://example.com/
- name: Deploy
run: ./deploy.sh "${{ steps.cecil.outputs.output_dir }}"
```

## License

_Cecil build Action_ is a free software distributed under the terms of the MIT license.
Expand Down
165 changes: 122 additions & 43 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,97 +7,176 @@ inputs:
default: "."
version:
description: "Cecil version (optional, last version by default)."
php_version:
description: "PHP version (optional, `8.3` by default)."
default: "8.3"
install_themes:
description: "Set to `no` to skip installing theme(s) (optional, `yes` by default)."
default: "yes"
options:
description: "Cecil options (optional, `-v` by default)."
default: -v
pages:
description: "Set to `false` to skip GitHub Pages configuration and artifact upload (optional, `true` by default)."
default: "true"
cache:
description: "Set to `false` to disable Cecil and Composer cache (optional, `true` by default)."
default: "true"
outputs:
output_dir:
description: "Path to the generated site directory."
value: ${{ steps.build.outputs.output_dir }}
cecil_version:
description: "Version of Cecil used to build the site."
value: ${{ steps.download.outputs.version }}
branding:
icon: package
color: white
runs:
using: composite
steps:
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: pre-installed
extensions: mbstring, fileinfo, gd, imagick, intl, gettext, :redis
- name: Validate site path
id: path
- name: Validate inputs
id: inputs
shell: bash
env:
SITE_PATH: ${{ inputs.path }}
VERSION: ${{ inputs.version }}
INSTALL_THEMES: ${{ inputs.install_themes }}
PAGES: ${{ inputs.pages }}
CACHE: ${{ inputs.cache }}
run: |
path="${SITE_PATH:-.}"
path="${path%/}"
path="${path:-.}"
if [[ ! -d "$path" ]]; then
echo "Site path not found: '$path'" >&2
echo "::error::Site path not found: '$path'"
exit 1
fi
echo "path=$path" >> "$GITHUB_OUTPUT"
- name: Validate Cecil version
shell: bash
run: |
version="${{ inputs.version }}"
if [[ -z "$version" ]]; then
if [[ -z "$VERSION" ]]; then
echo "No Cecil version provided; using latest release."
elif [[ ! "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+([\-+].*)?$ ]]; then
echo "Invalid Cecil version: '$version' (expected e.g. 8.76.3)" >&2
elif [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+([\-+][0-9A-Za-z.\-]+)?$ ]]; then
echo "::error::Invalid Cecil version: '$VERSION' (expected e.g. 9.25.0)"
exit 1
fi
# normalizes boolean inputs
bool() { [[ "$(echo "$1" | tr '[:upper:]' '[:lower:]')" =~ ^(yes|true|1|on)$ ]] && echo true || echo false; }
echo "install_themes=$(bool "$INSTALL_THEMES")" >> "$GITHUB_OUTPUT"
echo "pages=$(bool "$PAGES")" >> "$GITHUB_OUTPUT"
echo "cache=$(bool "$CACHE")" >> "$GITHUB_OUTPUT"
if [[ -f "$path/composer.json" ]]; then
echo "composer=true" >> "$GITHUB_OUTPUT"
fi
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ inputs.php_version }}
extensions: mbstring, fileinfo, gd, imagick, intl, gettext, :redis
tools: composer
- name: Downloading Cecil
id: download
shell: bash
env:
VERSION: ${{ inputs.version }}
run: |
if [[ -z "${{ inputs.version }}" ]]; then
phar="$RUNNER_TEMP/cecil.phar"
if [[ -z "$VERSION" ]]; then
echo "Downloading latest Cecil..."
curl -sSOL https://cecil.app/cecil.phar
curl -fsSL -o "$phar" https://cecil.app/cecil.phar
sha1=$(curl -fsSL https://cecil.app/cecil.phar.sha1 || true)
else
echo "Downloading Cecil ${{ inputs.version }}..."
curl -sSOL https://cecil.app/download/${{ inputs.version }}/cecil.phar
echo "Downloading Cecil $VERSION..."
curl -fsSL -o "$phar" "https://github.com/Cecilapp/Cecil/releases/download/$VERSION/cecil.phar"
sha1=$(curl -fsSL "https://cecil.app/download/$VERSION/cecil.phar.sha1" || true)
fi
# checksum is not published for all versions
sha1=$(echo "$sha1" | grep -oE '^[0-9a-f]{40}' || true)
if [[ -n "$sha1" ]]; then
actual=$( (sha1sum < "$phar" 2>/dev/null || shasum -a 1 < "$phar") | cut -d' ' -f1)
if [[ "$actual" != "$sha1" ]]; then
echo "::error::Checksum mismatch for cecil.phar (expected $sha1, got $actual)"
exit 1
fi
echo "Checksum verified."
else
echo "::warning::No checksum available for this Cecil version; skipping verification."
fi
version=$(php "$phar" --version --no-ansi | grep -oE '[0-9]+\.[0-9]+\.[0-9]+[^ ]*' | head -1)
echo "Cecil $version"
echo "phar=$phar" >> "$GITHUB_OUTPUT"
echo "version=$version" >> "$GITHUB_OUTPUT"
- name: Get Composer cache directory
id: composer-cache
if: steps.inputs.outputs.composer == 'true' && steps.inputs.outputs.install_themes == 'true' && steps.inputs.outputs.cache == 'true'
shell: bash
run: echo "dir=$(composer config cache-files-dir)" >> "$GITHUB_OUTPUT"
- name: Cache Composer
if: steps.composer-cache.outputs.dir != ''
uses: actions/cache@v6
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: cecil-composer-${{ runner.os }}-${{ hashFiles(format('{0}/composer.lock', steps.inputs.outputs.path), format('{0}/composer.json', steps.inputs.outputs.path)) }}
restore-keys: cecil-composer-${{ runner.os }}-
- name: Installing theme(s)
if: steps.inputs.outputs.composer == 'true' && steps.inputs.outputs.install_themes == 'true'
shell: bash
working-directory: ${{ steps.path.outputs.path }}
working-directory: ${{ steps.inputs.outputs.path }}
run: |
if [[ -f "composer.json" && ( "${{ inputs.install_themes }}" = "yes" || "${{ inputs.install_themes }}" = "true" ) ]]; then
echo "Installing theme(s)..."
composer install --prefer-dist --no-dev --no-progress --no-interaction --quiet
fi
echo "Installing theme(s)..."
composer install --prefer-dist --no-dev --no-progress --no-interaction
- name: Cache Cecil
if: steps.inputs.outputs.cache == 'true'
uses: actions/cache@v6
with:
path: ${{ steps.inputs.outputs.path }}/.cache
key: cecil-cache-${{ runner.os }}-${{ steps.download.outputs.version }}-${{ github.sha }}
restore-keys: cecil-cache-${{ runner.os }}-${{ steps.download.outputs.version }}-
- name: Setup GitHub Pages
id: pages
if: steps.inputs.outputs.pages == 'true'
uses: actions/configure-pages@v6
- name: Building site with Cecil
id: build
shell: bash
env:
PHAR: ${{ steps.download.outputs.phar }}
SITE_PATH: ${{ steps.inputs.outputs.path }}
OPTIONS: ${{ inputs.options }}
BASE_URL: ${{ steps.pages.outputs.base_url }}
VERSION: ${{ steps.download.outputs.version }}
run: |
php cecil.phar build "${{ steps.path.outputs.path }}" ${{ inputs.options }} --baseurl="${{ steps.pages.outputs.base_url }}/"
# Summary
if [ $? == 0 ]; then
echo "Site built with Cecil ${{ inputs.version }}" >> $GITHUB_STEP_SUMMARY
# splits options like a shell would (quotes are honored), without evaluating them
opts=()
if [[ -n "$OPTIONS" ]]; then
while IFS= read -r opt; do opts+=("$opt"); done < <(xargs -n1 printf '%s\n' <<< "$OPTIONS")
fi
- name: Resolve output directory
id: output
shell: bash
run: |
options='${{ inputs.options }}'
output_dir="_site"
if [[ "$options" =~ (^|[[:space:]])--output=([^[:space:]]+) ]]; then
output_dir="${BASH_REMATCH[2]}"
elif [[ "$options" =~ (^|[[:space:]])--output[[:space:]]+([^[:space:]]+) ]]; then
output_dir="${BASH_REMATCH[2]}"
elif [[ "$options" =~ (^|[[:space:]])-o[[:space:]]+([^[:space:]]+) ]]; then
output_dir="${BASH_REMATCH[2]}"
elif [[ "$options" =~ (^|[[:space:]])-o([^[:space:]]+) ]]; then
output_dir="${BASH_REMATCH[2]}"
has_baseurl=false
for ((i = 0; i < ${#opts[@]}; i++)); do
case "${opts[i]}" in
--output=*) output_dir="${opts[i]#--output=}" ;;
--output|-o) output_dir="${opts[i+1]}" ;;
-o*) output_dir="${opts[i]#-o}" ;;
--baseurl|--baseurl=*|-u|-u*) has_baseurl=true ;;
esac
done
# uses the GitHub Pages base URL, unless provided by options
if [[ -n "$BASE_URL" && "$has_baseurl" == false ]]; then
opts+=("--baseurl=${BASE_URL%/}/")
fi
php "$PHAR" build "$SITE_PATH" "${opts[@]}"
# output directory is relative to the site path
if [[ "$output_dir" != /* ]]; then
output_dir="${{ steps.path.outputs.path }}/$output_dir"
output_dir="$SITE_PATH/$output_dir"
fi
if [[ ! -d "$output_dir" ]]; then
echo "::error::Output directory not found: '$output_dir' (if it is set in the configuration file, also set it with the '--output' option)"
exit 1
fi
echo "output_dir=$output_dir" >> "$GITHUB_OUTPUT"
echo "Site built with Cecil $VERSION in \`$output_dir\`." >> "$GITHUB_STEP_SUMMARY"
- name: Upload GitHub Pages artifact
if: steps.inputs.outputs.pages == 'true'
uses: actions/upload-pages-artifact@v5
with:
path: ${{ steps.output.outputs.output_dir }}
path: ${{ steps.build.outputs.output_dir }}
Loading