Skip to content
Open
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
117 changes: 59 additions & 58 deletions .github/workflows/build-and-preview-docs.yml
Original file line number Diff line number Diff line change
@@ -1,87 +1,87 @@
name: Build and Preview Docs

on:
workflow_run:
workflows: ["Build PR Preview"]
types: [completed]
pull_request_target:
branches: [master]
types: [opened, synchronize, reopened, closed]
types: [closed]

permissions:
contents: write
pull-requests: write
Comment thread
coderabbitai[bot] marked this conversation as resolved.
actions: read

concurrency:
group: preview-${{ github.event.pull_request.number || github.run_id }}
group: preview-${{ github.event.workflow_run.id || github.event.pull_request.number || github.run_id }}
cancel-in-progress: true

defaults:
run:
shell: bash

jobs:
build-and-deploy-preview:
deploy-preview:
runs-on: ubuntu-24.04
outputs:
removed_prs_json: ${{ steps.prune-previews.outputs.removed_prs_json }}
if: >
(github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success') ||
(github.event_name == 'pull_request_target' && github.event.action == 'closed')
Comment on lines +27 to +29

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

Do not deploy a preview after its PR has closed.

A build can complete after the close-triggered cleanup finishes; this job will then redeploy the closed PR’s preview and leave it until retention pruning. Resolve the PR first, query its current state, and gate artifact download, deployment, retention, and comments on it still being open.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/build-and-preview-docs.yml around lines 26 - 28, Update
the workflow job condition around the existing trigger checks to resolve the
associated pull request and query its current state before proceeding. Gate
artifact download, deployment, retention, and comment steps on the pull request
still being open, so delayed workflow_run completions cannot redeploy a closed
PR preview.

env:
HUGO_VERSION: 0.158.0
PREVIEW_RETENTION_LIMIT: 6

steps:
- name: Checkout PR code
if: github.event.action != 'closed'
uses: actions/checkout@v6
- name: Download preview artifact
if: github.event_name == 'workflow_run'
uses: actions/download-artifact@v4
with:
repository: ${{ github.event.pull_request.head.repo.full_name }}
ref: ${{ github.event.pull_request.head.sha }}
persist-credentials: false
submodules: recursive
fetch-depth: 0
name: pr-preview-site
path: ./public
github-token: ${{ secrets.GITHUB_TOKEN }}
run-id: ${{ github.event.workflow_run.id }}

- name: Resolve PR number
id: pr-info
run: |
if [ "${{ github.event_name }}" = "workflow_run" ]; then
if [ -f ./public/PR_NUMBER.txt ]; then
PR_NUM=$(cat ./public/PR_NUMBER.txt | tr -d '[:space:]')
else
PR_NUM="${{ github.event.workflow_run.pull_requests[0].number }}"
fi
else
PR_NUM="${{ github.event.pull_request.number }}"
fi
echo "pr_number=$PR_NUM" >> "$GITHUB_OUTPUT"

- name: Check PR status
id: check-pr
if: github.event_name == 'workflow_run'
uses: actions/github-script@v7
with:
script: |
const prNumber = '${{ steps.pr-info.outputs.pr_number }}';
if (!prNumber) {
core.setFailed('Could not determine PR number');
return;
}
const { data: pr } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: Number(prNumber)
});
core.info(`PR #${prNumber} state: ${pr.state}`);
core.setOutput('is_open', pr.state === 'open');

- name: Checkout for cleanup
if: github.event.action == 'closed'
if: github.event_name == 'pull_request_target' && github.event.action == 'closed'
uses: actions/checkout@v6
with:
ref: gh-pages
fetch-depth: 0

- name: Install Hugo CLI
if: github.event.action != 'closed'
run: |
wget -O ${{ runner.temp }}/hugo.deb https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.deb \
&& sudo dpkg -i ${{ runner.temp }}/hugo.deb

- name: Install Dart Sass (npm)
if: github.event.action != 'closed'
run: |
npm i -g sass
sass --version

- name: Setup Node
if: github.event.action != 'closed'
uses: actions/setup-node@v4
with:
node-version: '20'

- name: Install dependencies
if: github.event.action != 'closed'
run:
'[[ -f package-lock.json || -f npm-shrinkwrap.json ]] && npm ci ||
true'

- name: Build PR preview
if: github.event.action != 'closed'
env:
BASE_URL: /pr-preview/pr-${{ github.event.pull_request.number }}/
HUGO_PREVIEW: 'true'
run: |
npm run build:preview
cat > public/robots.txt <<'EOF'
User-agent: *
Disallow: /
EOF

- name: Deploy PR preview
if: github.event.action != 'closed'
if: github.event_name == 'workflow_run' && steps.check-pr.outputs.is_open == 'true'
uses: rossjrw/pr-preview-action@v1.6.3
with:
source-dir: ./public
Expand All @@ -91,7 +91,7 @@ jobs:
comment: false

- name: Checkout gh-pages for preview retention
if: github.event.action != 'closed'
if: github.event_name == 'workflow_run' && steps.check-pr.outputs.is_open == 'true'
uses: actions/checkout@v6
with:
ref: gh-pages
Expand All @@ -100,7 +100,7 @@ jobs:

- name: Prune old PR previews
id: prune-previews
if: github.event.action != 'closed'
if: github.event_name == 'workflow_run' && steps.check-pr.outputs.is_open == 'true'
run: |
cd gh-pages-maintenance
mkdir -p pr-preview
Expand Down Expand Up @@ -141,16 +141,17 @@ jobs:
echo "removed_prs_json=$(printf '%s\n' "${removed_prs[@]}" | jq -R . | jq -sc .)" >> "$GITHUB_OUTPUT"

- name: Comment PR with Preview URL
if: github.event.action != 'closed'
if: github.event_name == 'workflow_run' && steps.check-pr.outputs.is_open == 'true'
uses: marocchino/sticky-pull-request-comment@v2
with:
header: pr-preview
number: ${{ steps.pr-info.outputs.pr_number }}
message: |
🚀 Preview deployment: https://docs.layer5.io/pr-preview/pr-${{ github.event.pull_request.number }}/
🚀 Preview deployment: https://docs.layer5.io/pr-preview/pr-${{ steps.pr-info.outputs.pr_number }}/
> *Note: Preview may take a moment (GitHub Pages deployment in progress). Please wait and refresh. Track deployment [here](https://github.com/${{ github.repository }}/actions/workflows/pages/pages-build-deployment)*

- name: Comment on pruned previews
if: github.event.action != 'closed' && steps.prune-previews.outputs.removed_prs_json != '[]'
if: github.event_name == 'workflow_run' && steps.check-pr.outputs.is_open == 'true' && steps.prune-previews.outputs.removed_prs_json != '[]'
uses: actions/github-script@v7
env:
REMOVED_PRS_JSON: ${{ steps.prune-previews.outputs.removed_prs_json }}
Expand Down Expand Up @@ -200,7 +201,7 @@ jobs:
}

- name: Cleanup PR preview on close
if: github.event.action == 'closed'
if: github.event_name == 'pull_request_target' && github.event.action == 'closed'
uses: rossjrw/pr-preview-action@v1.6.3
with:
preview-branch: gh-pages
Expand Down
71 changes: 71 additions & 0 deletions .github/workflows/build-pr-preview.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
name: Build PR Preview

on:
pull_request:
branches: [master]
types: [opened, synchronize, reopened]

permissions:
contents: read

concurrency:
group: build-preview-${{ github.event.pull_request.number || github.run_id }}
cancel-in-progress: true

defaults:
run:
shell: bash

jobs:
build:
runs-on: ubuntu-24.04
env:
HUGO_VERSION: 0.158.0

steps:
- name: Checkout PR code
uses: actions/checkout@v6
with:
persist-credentials: false
submodules: recursive
fetch-depth: 0
Comment thread
coderabbitai[bot] marked this conversation as resolved.

- name: Install Hugo CLI
run: |
wget -O ${{ runner.temp }}/hugo.deb https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.deb \
&& sudo dpkg -i ${{ runner.temp }}/hugo.deb

- name: Install Dart Sass (npm)
run: |
npm i -g sass
sass --version

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '20'

- name: Install dependencies
run: |
if [[ -f package-lock.json || -f npm-shrinkwrap.json ]]; then
npm ci
fi

- name: Build PR preview
env:
BASE_URL: /pr-preview/pr-${{ github.event.pull_request.number }}/
HUGO_PREVIEW: 'true'
run: |
npm run build:preview
cat > public/robots.txt <<'EOF'
User-agent: *
Disallow: /
EOF
echo "${{ github.event.pull_request.number }}" > public/PR_NUMBER.txt

- name: Upload preview artifact
uses: actions/upload-artifact@v4
with:
name: pr-preview-site
path: public/
retention-days: 1
6 changes: 6 additions & 0 deletions content/en/cloud/concepts/identity-and-security/tokens.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ Access tokens are opaque tokens that conform to the OAuth 2.0 framework. They co
Layer5 Cloud API tokens are scoped to your user account, not to a specific organization. This means a single API token provides access to all organizations you are a member of, similar to how [GitHub Personal Access Tokens](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens) work. For users who belong to multiple organizations, see [Specifying Organization Context]({{< ref "cloud/reference/api-reference/_index.md#specifying-organization-context" >}}) in the REST API documentation to learn how to control which organization your API requests operate on.
{{< /alert >}}

## Privilege Scoping

API tokens in Layer5 are **identity-scoped**. This means they inherently carry the exact same privileges, roles, and permissions as your user account within the organization and environment selected by the request context.

Users can have different roles and permissions in different organizations, meaning a token does not grant one uniform privilege set across every organization. However, Layer5 does not currently support fine-grained, token-specific privilege scopes (for example, generating a strictly "read-only" token if you have "read-write" permissions).

## Creating tokens

You can create a token for your user account at any time. Tokens never expire, but can be revoked. You can also give the token a descriptive label. This label will be shown in the list of tokens on your user account's security tokens page.
Expand Down
Loading