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
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
---
title: About billing for GitHub Spark
title: GitHub Spark billing
intro: 'Learn how {% data variables.product.prodname_spark %} is billed for users.'
versions:
feature: spark
topics:
- Copilot
shortTitle: Billing for Spark
shortTitle: GitHub Spark
redirect_from:
- /copilot/concepts/copilot-billing/about-billing-for-github-spark
- /copilot/concepts/copilot-billing/billing-for-spark
Expand Down
1 change: 1 addition & 0 deletions content/billing/concepts/product-billing/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ children:
- /github-models
- /github-packages
- /git-lfs
- /github-spark
contentType: concepts
---

1 change: 0 additions & 1 deletion content/copilot/concepts/billing/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ children:
- /individual-plans
- /billing-for-individuals
- /organizations-and-enterprises
- /billing-for-spark
redirect_from:
- /managing-copilot/managing-copilot-as-an-individual-subscriber/billing-and-payments
- /copilot/managing-copilot/understanding-and-managing-copilot-usage
Expand Down
2 changes: 1 addition & 1 deletion content/copilot/concepts/spark.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ Benefits include:
### Billing

Each natural-language prompt in {% data variables.product.prodname_spark_short %} consumes four premium requests.
See [AUTOTITLE](/copilot/concepts/billing/billing-for-spark).
See [AUTOTITLE](/billing/concepts/product-billing/github-spark).

### Infrastructure

Expand Down
27 changes: 27 additions & 0 deletions content/enterprise-onboarding/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,33 @@ featuredLinks:
- '/enterprise-onboarding/github-actions-for-your-enterprise'
- '/enterprise-onboarding/feature-enhancements'
layout: product-landing
journeyTracks:
- id: 'getting_started'
title: 'Getting started with your enterprise'
description: 'Learn how to start a trial of {% data variables.product.prodname_enterprise %}, and about enterprise billing and migrations.'
guides:
- '/enterprise-onboarding/getting-started-with-your-enterprise/setting-up-a-trial-of-github-enterprise'
- '/enterprise-onboarding/getting-started-with-your-enterprise/ending-a-trial-of-github-enterprise'
- '/enterprise-onboarding/getting-started-with-your-enterprise/about-enterprise-billing'
- '/enterprise-onboarding/getting-started-with-your-enterprise/about-migrating-to-github-enterprise-cloud'
- '/enterprise-onboarding/getting-started-with-your-enterprise/securing-your-enterprise-with-managed-users'
- '/enterprise-onboarding/getting-started-with-your-enterprise/securing-enterprise-resources-with-single-sign-on'
- id: 'organizations_and_teams'
title: 'Setting up organizations and teams in your enterprise'
description: 'Learn how to add and manage organizations and teams in your enterprise.'
guides:
- '/enterprise-onboarding/setting-up-organizations-and-teams/setting-up-an-organization'
- '/enterprise-onboarding/setting-up-organizations-and-teams/managing-organization-members'
- '/enterprise-onboarding/setting-up-organizations-and-teams/managing-your-organizations'
- '/enterprise-onboarding/setting-up-organizations-and-teams/creating-teams'
- '/enterprise-onboarding/setting-up-organizations-and-teams/best-practices-for-organizations-in-your-enterprise'
- id: 'support'
title: 'Creating a support model for your enterprise'
description: 'Learn about {% data variables.product.github %} support and how to set up a support model for your enterprise.'
guides:
- '/enterprise-onboarding/support-for-your-enterprise/understanding-support'
- '/enterprise-onboarding/support-for-your-enterprise/using-the-support-portal'
- '/enterprise-onboarding/support-for-your-enterprise/managing-support-entitlements'
versions:
ghec: '*'
topics:
Expand Down
5 changes: 5 additions & 0 deletions data/ui.yml
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,11 @@ learning_track_nav:
next_guide: Next
more_guides: More guides →
current_progress: '{i} of {n} in learning path'
journey_track_nav:
prev_article: Previous
next_article: Next
more_articles: More articles →
current_progress: 'Article {i} of {n}'
scroll_button:
scroll_to_top: Scroll to top
popovers:
Expand Down
13 changes: 13 additions & 0 deletions src/fixtures/fixtures/content/get-started/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,19 @@ featuredLinks:
- /get-started/foo/bar
guideCards:
- /get-started/foo/autotitling
journeyTracks:
- id: 'getting_started'
title: 'Getting started'
description: 'Learn the basics of our platform.'
guides:
- '/get-started/start-your-journey/hello-world'
- '/get-started/foo/bar'
- id: 'advanced'
title: 'Advanced topics'
description: 'Dive deeper into advanced features.'
guides:
- '/get-started/foo/autotitling'
- '/get-started/start-your-journey/hello-world'
children:
- /start-your-journey
- /foo
Expand Down
1 change: 1 addition & 0 deletions src/fixtures/fixtures/content/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ children:
# as if the URL had been `/en/free-pro-team@latest/get-started/anything`.
- search
- get-started
- test-journey
- early-access
- pages
- code-security
Expand Down
24 changes: 24 additions & 0 deletions src/fixtures/fixtures/content/test-journey/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
title: Test Journey Landing
intro: 'Test page for journey tracks functionality'
layout: journey-landing
versions:
fpt: '*'
ghes: '*'
ghec: '*'
journeyTracks:
- id: 'getting_started'
title: 'Getting started'
description: 'Learn the basics of our platform.'
guides:
- '/get-started/start-your-journey/hello-world'
- '/get-started/foo/bar'
- id: 'advanced'
title: 'Advanced topics'
description: 'Dive deeper into advanced features.'
guides:
- '/get-started/foo/autotitling'
- '/get-started/start-your-journey/hello-world'
---

This is a test page for journey tracks.
5 changes: 5 additions & 0 deletions src/fixtures/fixtures/data/ui.yml
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,11 @@ learning_track_nav:
next_guide: Next
more_guides: More guides →
current_progress: '{i} of {n} in learning path'
journey_track_nav:
prev_article: Previous
next_article: Next
more_articles: More articles →
current_progress: 'Article {i} of {n}'
scroll_button:
scroll_to_top: Scroll to top
popovers:
Expand Down
99 changes: 99 additions & 0 deletions src/fixtures/tests/playwright-rendering.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1056,3 +1056,102 @@ test.describe('LandingCarousel component', () => {
await expect(cards).toHaveCount(1)
})
})

test.describe('Journey Tracks', () => {
test('displays journey tracks on landing pages', async ({ page }) => {
await page.goto('/get-started?feature=journey-landing')

const journeyTracks = page.locator('[data-testid="journey-tracks"]')
await expect(journeyTracks).toBeVisible()

// Check that at least one track is displayed
const tracks = page.locator('[data-testid="journey-track"]')
await expect(tracks.first()).toBeVisible()

// Verify track has proper structure
const firstTrack = tracks.first()
await expect(firstTrack.locator('h3')).toBeVisible() // Track title
await expect(firstTrack.locator('p')).toBeVisible() // Track description
})

test('track expansion and collapse functionality', async ({ page }) => {
await page.goto('/get-started?feature=journey-landing')

const firstTrack = page.locator('[data-testid="journey-track"]').first()
const expandButton = firstTrack.locator('summary')

// Initially collapsed
const articlesList = firstTrack.locator('[data-testid="journey-articles"]')
await expect(articlesList).not.toBeVisible()

await expandButton.click()
await expect(articlesList).toBeVisible()

const articles = articlesList.locator('li')
await expect(articles.first()).toBeVisible()

await expandButton.click()
await expect(articlesList).not.toBeVisible()
})

test('article navigation within tracks', async ({ page }) => {
await page.goto('/get-started?feature=journey-landing')

const firstTrack = page.locator('[data-testid="journey-track"]').first()
const expandButton = firstTrack.locator('summary')

await expandButton.click()

// Click on first article
const firstArticle = firstTrack.locator('[data-testid="journey-articles"] li a').first()
await expect(firstArticle).toBeVisible()

const articleTitle = await firstArticle.textContent()
expect(articleTitle).toBeTruthy()
expect(articleTitle!.length).toBeGreaterThan(0)
})

test('preserves version in journey track links', async ({ page }) => {
await page.goto('/enterprise-cloud@latest/get-started?feature=journey-landing')

const firstTrack = page.locator('[data-testid="journey-track"]').first()
const expandButton = firstTrack.locator('summary')
await expandButton.click()

// article links should preserve the language and version
const firstArticle = firstTrack.locator('[data-testid="journey-articles"] li a').first()
const href = await firstArticle.getAttribute('href')

expect(href).toContain('/en/')
expect(href).toContain('enterprise-cloud@latest')
})

test('handles liquid template rendering in track content', async ({ page }) => {
await page.goto('/get-started?feature=journey-landing')

const tracks = page.locator('[data-testid="journey-track"]')

// Check that liquid templates are rendered (no raw template syntax visible)
const trackContent = await tracks.first().textContent()
expect(trackContent).not.toContain('{{')
expect(trackContent).not.toContain('}}')
expect(trackContent).not.toContain('{%')
expect(trackContent).not.toContain('%}')
})

test('journey navigation components show on article pages', async ({ page }) => {
// go to an article that's part of a journey track
await page.goto('/get-started/start-your-journey/hello-world?feature=journey-navigation')

// journey next/prev nav components should rende
const journeyCard = page.locator('[data-testid="journey-track-card"]')
if (await journeyCard.isVisible()) {
await expect(journeyCard).toBeVisible()
}

const journeyNav = page.locator('[data-testid="journey-track-nav"]')
if (await journeyNav.isVisible()) {
await expect(journeyNav).toBeVisible()
}
})
})
18 changes: 18 additions & 0 deletions src/frame/components/article/ArticlePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import { DefaultLayout } from '@/frame/components/DefaultLayout'
import { ArticleTitle } from '@/frame/components/article/ArticleTitle'
import { useArticleContext } from '@/frame/components/context/ArticleContext'
import { LearningTrackNav } from '@/learning-track/components/article/LearningTrackNav'
import { JourneyTrackNav } from '@/journeys/components/JourneyTrackNav'
import { JourneyTrackCard } from '@/journeys/components/JourneyTrackCard'
import { MarkdownContent } from '@/frame/components/ui/MarkdownContent'
import { Lead } from '@/frame/components/ui/Lead'
import { PermissionsStatement } from '@/frame/components/ui/PermissionsStatement'
Expand Down Expand Up @@ -42,10 +44,14 @@ export const ArticlePage = () => {
productVideoUrl,
miniTocItems,
currentLearningTrack,
currentJourneyTrack,
supportPortalVaIframeProps,
currentLayout,
} = useArticleContext()
const isLearningPath = !!currentLearningTrack?.trackName
const isJourneyPath = !!currentJourneyTrack?.trackId
// Only show journey track components when feature flag is enabled
const showJourneyTracks = isJourneyPath && router.query?.feature === 'journey-navigation'
const { t } = useTranslation(['pages'])

const introProp = (
Expand All @@ -72,6 +78,7 @@ export const ArticlePage = () => {
const toc = (
<>
{isLearningPath && <LearningTrackCard track={currentLearningTrack} />}
{showJourneyTracks && <JourneyTrackCard journey={currentJourneyTrack} />}
{miniTocItems.length > 1 && <MiniTocs miniTocItems={miniTocItems} />}
</>
)
Expand Down Expand Up @@ -122,6 +129,11 @@ export const ArticlePage = () => {
<LearningTrackNav track={currentLearningTrack} />
</div>
) : null}
{showJourneyTracks ? (
<div className="container-lg mt-4 px-3">
<JourneyTrackNav context={currentJourneyTrack} />
</div>
) : null}
</>
) : (
<div className="container-xl px-3 px-md-6 my-4">
Expand All @@ -148,6 +160,12 @@ export const ArticlePage = () => {
<LearningTrackNav track={currentLearningTrack} />
</div>
) : null}

{showJourneyTracks ? (
<div className="mt-4">
<JourneyTrackNav context={currentJourneyTrack} />
</div>
) : null}
</div>
)}
</DefaultLayout>
Expand Down
3 changes: 3 additions & 0 deletions src/frame/components/context/ArticleContext.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { SupportPortalVaIframeProps } from '@/frame/components/article/SupportPortalVaIframe'
import { createContext, useContext } from 'react'
import type { JourneyContext } from '@/journeys/lib/journey-path-resolver'

export type LearningTrack = {
trackTitle: string
Expand Down Expand Up @@ -34,6 +35,7 @@ export type ArticleContextT = {
product?: string
productVideoUrl?: string
currentLearningTrack?: LearningTrack
currentJourneyTrack?: JourneyContext
detectedPlatforms: Array<string>
detectedTools: Array<string>
allTools: Record<string, string>
Expand Down Expand Up @@ -98,6 +100,7 @@ export const getArticleContextFromRequest = (req: any): ArticleContextT => {
product: page.product || '',
productVideoUrl: page.product_video || '',
currentLearningTrack: req.context.currentLearningTrack,
currentJourneyTrack: req.context.currentJourneyTrack,
detectedPlatforms: page.detectedPlatforms || [],
detectedTools: page.detectedTools || [],
allTools: page.allToolsParsed || [], // this is set at the page level, see lib/page.js
Expand Down
33 changes: 33 additions & 0 deletions src/frame/lib/frontmatter.js
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,39 @@ export const schema = {
learningTracks: {
type: 'array',
},
// Journey tracks for journey landing pages
journeyTracks: {
type: 'array',
items: {
type: 'object',
required: ['id', 'title', 'guides'],
properties: {
id: {
type: 'string',
description: 'Unique identifier for the journey track',
},
title: {
type: 'string',
translatable: true,
description: 'Display title for the journey track',
},
description: {
type: 'string',
translatable: true,
description: 'Optional description for the journey track',
},
guides: {
type: 'array',
items: {
type: 'string',
},
description: 'Array of article paths that make up this journey track',
},
},
additionalProperties: false,
},
description: 'Array of journey tracks for journey landing pages',
},
// Used in `product-landing.html`
beta_product: {
type: 'boolean',
Expand Down
2 changes: 2 additions & 0 deletions src/frame/middleware/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import productExamples from './context/product-examples'
import productGroups from './context/product-groups'
import featuredLinks from '@/landings/middleware/featured-links'
import learningTrack from '@/learning-track/middleware/learning-track'
import journeyTrack from '@/journeys/middleware/journey-track'
import next from './next'
import renderPage from './render-page'
import assetPreprocessing from '@/assets/middleware/asset-preprocessing'
Expand Down Expand Up @@ -270,6 +271,7 @@ export default function (app: Express) {
app.use(asyncMiddleware(featuredLinks))
app.use(asyncMiddleware(resolveRecommended))
app.use(asyncMiddleware(learningTrack))
app.use(asyncMiddleware(journeyTrack))

if (ENABLE_FASTLY_TESTING) {
// The fastlyCacheTest middleware is intended to be used with Fastly to test caching behavior.
Expand Down
Loading
Loading