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
142 changes: 142 additions & 0 deletions .github/workflows/validate-docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
name: Validate Documentation

on:
pull_request:
types: [opened, synchronize, reopened] # Run on PR open AND every commit
branches:
- main
paths:
- '**.mdx'
- '**.md'
- 'images/**'
- 'scripts/**'
- '.github/workflows/validate-docs.yml'

jobs:
validate:
name: Check Links and Images
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'

- name: Check for broken links
id: check-links
run: |
echo "::group::Checking for broken links"
node scripts/check-links.js > /tmp/check-links-output.txt 2>&1 || echo "issues_found=true" >> $GITHUB_OUTPUT
cat /tmp/check-links-output.txt
echo "::endgroup::"
continue-on-error: true

- name: Check image locations
id: check-images
run: |
echo "::group::Checking image locations"
node scripts/check-image-locations.js > /tmp/check-images-output.txt 2>&1 || echo "issues_found=true" >> $GITHUB_OUTPUT
cat /tmp/check-images-output.txt
echo "::endgroup::"
continue-on-error: true

- name: Post or update PR comment
if: always() # Always run to update comment even if issues are fixed
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');

// Build comment body
let comment = '## 📋 Documentation Validation Report\n\n';

const hasIssues = '${{ steps.check-links.outputs.issues_found }}' === 'true' ||
'${{ steps.check-images.outputs.issues_found }}' === 'true';

if (hasIssues) {
comment += '⚠️ Some issues were found in this PR. These are **informational warnings** and will not block merging.\n\n';
} else {
comment += '✅ All validation checks passed!\n\n';
}

if ('${{ steps.check-links.outputs.issues_found }}' === 'true') {
const linksOutput = fs.readFileSync('/tmp/check-links-output.txt', 'utf8');
const lines = linksOutput.split('\n');
const brokenLinks = lines.filter(line => line.includes('Broken link:') || line.includes('📄')).slice(0, 10);

comment += '### 🔗 Links\n';
if (brokenLinks.length > 0) {
comment += '<details><summary>❌ Found broken links (click to expand)</summary>\n\n';
comment += '```\n' + brokenLinks.join('\n') + '\n```\n';
comment += '</details>\n\n';
}
} else {
comment += '### 🔗 Links\n✅ All links valid\n\n';
}

if ('${{ steps.check-images.outputs.issues_found }}' === 'true') {
const imagesOutput = fs.readFileSync('/tmp/check-images-output.txt', 'utf8');
const lines = imagesOutput.split('\n');
const imageIssues = lines.filter(line => line.includes('📄') || line.includes('Expected in:')).slice(0, 10);

comment += '### 🖼️ Images\n';
if (imageIssues.length > 0) {
comment += '<details><summary>❌ Found image location issues (click to expand)</summary>\n\n';
comment += '```\n' + imageIssues.join('\n') + '\n```\n';
comment += '</details>\n\n';
}
} else {
comment += '### 🖼️ Images\n✅ All images in correct locations\n\n';
}

comment += '---\n';
comment += '💡 **Quick Reference:**\n';
comment += '- A page at `guides/dashboard.mdx` should use images from `images/guides/dashboard/`\n';
comment += '- Shared images can be placed in parent directories\n';
comment += '- All internal links must point to existing files\n\n';
comment += '📖 Run `node scripts/check-links.js` and `node scripts/check-image-locations.js` locally for full details.\n';

// Find existing comment from this bot
const { data: comments } = await github.rest.issues.listComments({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
});

const botComment = comments.find(c =>
c.user.type === 'Bot' && c.body.includes('📋 Documentation Validation Report')
);

// Update existing or create new
if (botComment) {
await github.rest.issues.updateComment({
comment_id: botComment.id,
owner: context.repo.owner,
repo: context.repo.repo,
body: comment
});
} else {
await github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: comment
});
}

- name: Report results
if: always()
run: |
if [ "${{ steps.check-links.outputs.issues_found }}" == "true" ] || [ "${{ steps.check-images.outputs.issues_found }}" == "true" ]; then
echo "## Documentation Validation Warnings ⚠️" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "Issues found - see PR comment for details" >> $GITHUB_STEP_SUMMARY
else
echo "## Documentation Validation Passed ✅" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "All links are valid and images are in the correct locations!" >> $GITHUB_STEP_SUMMARY
fi
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ Here's an example of our dbt project at Lightdash too see what that looks like i
- We have one `.yml` file per model (these are the files where all of your Tables' configuration sits)

<Frame>
<img src="/images/guides/dbt-repo-example.png" alt="" />
<img src="/images/get-started/develop-in-lightdash/adding-tables-to-lightdash/dbt-repo-example.png" alt="" />
</Frame>

**But, in my dbt project, I have a single schema.yml file. Not one for each model. Will that still work?**
Expand Down
2 changes: 1 addition & 1 deletion get-started/exploring-data/using-explores.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ Saved Charts allow you to save a specific chart or table so you can share, add i
When you open a saved chart, it will always update to display the latest data in your database since it will re-run the query each time you open it.

<Frame>
![](/images/get-started/exploring-data/dashboards/save-your-chart.png)
![](/images/get-started/exploring-data/using-explores/save-your-chart.png)
</Frame>

To save a chart, click the `Save chart` button at the top of the page, then give your chart a useful name and description. You'll have the option to save the chart to a Dashboard or a Space.
Expand Down
2 changes: 1 addition & 1 deletion guides/embedding/dashboards.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,7 @@ Filter data based on the viewing user's properties. See the [user attributes ref
Embed individual charts for focused displays
</Card>

<Card title="User attributes & row-level security" icon="shield-check" href="/references/user-attributes">
<Card title="User attributes & row-level security" icon="shield-check" href="/references/workspace/user-attributes">
Show different data to different users
</Card>

Expand Down
16 changes: 8 additions & 8 deletions guides/table-calculations.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ title: "Table calculations"
description: "Table calculations make it easy to create metrics on the fly (for example, aggregating the data in your table over some window, or getting a running total of a column)."
---

You add table calculations in the Explore view and they appear as green columns in your results table (remember, [dimensions](references/dimensions) are blue, and [metrics](references/metrics) are orange).
You add table calculations in the Explore view and they appear as green columns in your results table (remember, [dimensions](/references/dimensions) are blue, and [metrics](/references/metrics) are orange).

<Frame>
<img src="/images/guides/table-calculations/table-calculations-add-a932fb32af1dc604d4ef709886f9a833.jpg"/>
Expand All @@ -24,7 +24,7 @@ Table calculations work as an additional computational layer that builds on top
- Other table calculations (you can even stack them)

<Warning>
Table calculations are useful for specialized, temporary needs, but if you find yourself repeatedly reusing a table calculation, it's a sign to add it to dbt so it's tracked in the semantic layer. This keeps your organization's metrics centralized and consistently defined. You can read more about [adding metrics to your dbt project here](references/metrics).
Table calculations are useful for specialized, temporary needs, but if you find yourself repeatedly reusing a table calculation, it's a sign to add it to dbt so it's tracked in the semantic layer. This keeps your organization's metrics centralized and consistently defined. You can read more about [adding metrics to your dbt project here](/references/metrics).
</Warning>

## Creating table calculations
Expand All @@ -38,7 +38,7 @@ Table calculations work with whatever data you've already pulled into your resul
Quick calculations are shortcuts to the most common table calculations, these are only available to metrics in the contextual menu in the results table.

<Frame>
![](/images/references/quick-table-calculation-b1e76d3e54d84ca3c5066ffdf989514b.png)
![](/images/guides/table-calculations/quick-table-calculation-b1e76d3e54d84ca3c5066ffdf989514b.png)
</Frame>

To learn more about what these calculations are doing, check out the docs [here](/guides/table-calculations/sql-templates). Once the table calculation is generated you can edit it to modify the SQL query or update the format.
Expand All @@ -48,7 +48,7 @@ To learn more about what these calculations are doing, check out the docs [here]
Once you've got some data in your results table, you can create a table calculation by clicking on the `+ Table calculation` in the `Results` tab of the Explore view:

<Frame>
![](/images/references/create-new-table-calc-772add6d063a5122c0a25accf798fbb3.jpg)
![](/images/guides/table-calculations/create-new-table-calc-772add6d063a5122c0a25accf798fbb3.jpg)
</Frame>

##### Write the SQL for your table calculation in the pop-up box
Expand All @@ -58,7 +58,7 @@ Your table calculation is defined using raw SQL that you write up in this pop up
To reference the metrics and dimensions in your results table, you can either use the autocomplete, or you can manually write the full field name using the format `${table_name.field_name}`.

<Frame>
![](/images/references/add-table-calc-sql-20de5398dc117ef3d4087cf3b6d9939b.jpg)
![](/images/guides/table-calculations/add-table-calc-sql-20de5398dc117ef3d4087cf3b6d9939b.jpg)
</Frame>


Expand All @@ -67,7 +67,7 @@ To reference the metrics and dimensions in your results table, you can either us
If needed, you can update the format of your table calculation to things like percent formatting using the `format` tab.

<Frame>
![](/images/references/format-table-calc-c0e3828b6681db084b4ddd6799ff2c96.jpg)
![](/images/guides/table-calculations/format-table-calc-c0e3828b6681db084b4ddd6799ff2c96.jpg)
</Frame>

| Format types | Description | Raw value | How it might look like in Lightdash |
Expand All @@ -82,7 +82,7 @@ If needed, you can update the format of your table calculation to things like pe
If you need to edit or delete a table calculation, you can just click on the toggle beside the field and do what you need to do!

<Frame>
![](/images/references/edit-delete-table-calc-520776c8631697527bf3760000dce88e.jpg)
![](/images/guides/table-calculations/edit-delete-table-calc-520776c8631697527bf3760000dce88e.jpg)
</Frame>


Expand All @@ -102,7 +102,7 @@ Since all calculations are performed before filtering, table calculation filters
For example: You use table calculations to calculate the `percentage_of_shipping_method_amount`, then filter to hide rows below 30%. The filtered rows (shown in purple) will disappear but the `percentage_total` calculation still shows 100% even though the visible percentages in the `percentage_of_shipping_method_amount` column no longer add up to 100%.

<Frame>
![](/images/references/table_calculation_filter_example.jpg)
![](/images/guides/table-calculations/table_calculation_filter_example.jpg)
</Frame>

## Table calculation SQL templates
Expand Down
Loading