Skip to content

Conversation

dfuenzalida
Copy link

This PR adds documentation on how to deploy Ktor web apps to Azure App Service either by creating a new web app or deploying to an existing one.

Feel free to suggest any edits, rewording and clarifications.


Disclaimer: I'm in the App Service Java team so I'm invested in attracting devs using Ktor to our service offering.

Copy link

coderabbitai bot commented Sep 7, 2025

Walkthrough

Adds a new Publishing TOC entry for Azure App Service and a new topic file topics/azure-app-service.md containing step-by-step instructions for port handling, Gradle setup, fat JAR configuration, and deployment to Azure App Service.

Changes

Cohort / File(s) Summary of changes
TOC update
ktor.tree
Added a toc-element with topic="azure-app-service.md" under the toc-element with toc-title="Publishing", placed before google-app-engine.md.
New publishing topic
topics/azure-app-service.md
Added a new guide covering prerequisites (Azure account, Azure CLI), sample app options, PORT handling (env var or application.conf), Gradle plugin additions (io.ktor.plugin, com.microsoft.azure.azurewebapp), azurewebapp deployment configuration (subscription, resourceGroup, appName, pricingTier, region, runtime, auth), fat JAR rename/disable default jar, and deployment steps for both new and existing Azure Web Apps (with sample commands and logs).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • vnikolova
  • e5l

Pre-merge checks (3 passed)

✅ Passed checks (3 passed)
Check name Status Explanation
Title Check ✅ Passed The pull request title "Add docs on deployment of Ktor apps to Azure App Service" accurately and concisely reflects the primary change: adding a new topics/azure-app-service.md file and its TOC entry in ktor.tree. It is specific, clear, and free of noise or misleading details. This makes the intent easy to understand for reviewers scanning the project history.
Description Check ✅ Passed The PR description states that documentation for deploying Ktor apps to Azure App Service was added and invites edits, which directly matches the added azure-app-service topic and TOC modification in the changeset. It is on-topic and sufficiently informative for this lenient check. The author's disclosure about their App Service team affiliation does not make the description unrelated.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.

Tip

👮 Agentic pre-merge checks are now available in preview!

Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.

  • Built-in checks – Quickly apply ready-made checks to enforce title conventions, require pull request descriptions that follow templates, validate linked issues for compliance, and more.
  • Custom agentic checks – Define your own rules using CodeRabbit’s advanced agentic capabilities to enforce organization-specific policies and workflows. For example, you can instruct CodeRabbit’s agent to verify that API documentation is updated whenever API schema files are modified in a PR. Note: Upto 5 custom checks are currently allowed during the preview period. Pricing for this feature will be announced in a few weeks.

Please see the documentation for more information.

Example:

reviews:
  pre_merge_checks:
    custom_checks:
      - name: "Undocumented Breaking Changes"
        mode: "warning"
        instructions: |
          Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).

Please share your feedback with us on this Discord post.

✨ Finishing touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@dfuenzalida dfuenzalida changed the title Add docs on deployment Ktor apps to Azure App Service Add docs on deployment of Ktor apps to Azure App Service Sep 7, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (10)
topics/azure-app-service.md (10)

37-46: Add language to fenced block (application.conf) to satisfy MD040

Specify the language for proper highlighting and to appease markdownlint.

Apply:

-```
+```hocon
 ...
-```
+```

47-48: Add a blank line after the heading

Improves readability and fixes the grammar/lint warning.

-### Step 2: Add plugins {id="plugins"}
-Open the `build.gradle.kts` file and add the following lines to the `plugins` section:
+### Step 2: Add plugins {id="plugins"}
+
+Open the `build.gradle.kts` file and add the following lines to the `plugins` section:

60-66: Call out EngineMain mainClass alternative

Readers following the EngineMain sample need a different mainClass.

 }

+If you used the EngineMain variant:
+
+```kotlin
+application {

  • mainClass.set("io.ktor.server.netty.EngineMain")
    +}
    +```

---

`74-86`: **Fix code fence language and typo (“farJar” → “fatJar”)**

Small polish + better highlighting.

```diff
-```
+```kotlin
 // Rename the fat JAR to the name that the deploy task expects
 ktor {
     fatJar {
         archiveFileName.set("embedded-server.jar")
     }
 }
 
 // Disable the `jar` task that Azure Plugin would normally run
-// to deploy the archive created by the `farJar` task instead
+// to deploy the archive created by the `fatJar` task instead
 tasks.named("jar") {
     enabled = false
 }
-```
+```

111-115: Avoid intra-page anchor flagged by MD051

The fragment link to #plugins appears to trip MD051. Rephrase to avoid the anchor.

-First, to build the fat JAR, execute the `buildFatJar` task provided by the [Ktor plugin](#plugins) running the command below:
+First, to build the fat JAR, execute the `buildFatJar` task provided by the Ktor Gradle plugin:

115-122: Clarify multi-project vs single-project task invocation

Your commands assume a subproject. Add a note for single-project users.

 </tabs>
 
+Note: For single-project builds, omit the `:embedded-server:` prefix (for example, `./gradlew buildFatJar`).
+

128-131: Tighten wording on authentication

Minor clarity and concision.

-The authentication method used by the Azure Web App Deploy plugin used in the configuration added earlier will use the Azure CLI. If you haven't done so, log in once with `az login` and follow the instructions.
+The Azure Web App Gradle plugin is configured to authenticate via the Azure CLI. If you haven't already, run `az login` and follow the prompts.

143-157: Add language to fenced block (deployment logs) to satisfy MD040

Mark as text for readability and linter happiness.

-```
+```text
 ...
-```
+```

165-167: Add language to fenced block (CLI) to satisfy MD040

Mark as bash.

-```
+```bash
 az webapp deploy -g RESOURCE-GROUP-NAME -n WEBAPP-NAME --src-path ./path/to/embedded-server.jar --restart true
-```
+```

88-104: Add closureOf import and deploy fat JAR via setDeployment

  • Import org.gradle.kotlin.dsl.closureOf at the top of your build.gradle.kts so closureOf<…> resolves.
  • Replace renaming/disabling tasks with an explicit setDeployment block pointing at your fat JAR:
import org.gradle.kotlin.dsl.closureOf

plugins {
    id("com.microsoft.azure.azurewebapp") version "1.10.0"
}

azurewebapp {
    subscription    = "<YOUR_SUBSCRIPTION_ID>"
    resourceGroup   = "<YOUR_RESOURCE_GROUP>"
    appName         = "<YOUR_APP_NAME>"
    pricingTier     = "P1v2"
    region          = "centralus"

    setRuntime(closureOf<com.microsoft.azure.gradle.configuration.GradleRuntimeConfig> {
        os("Linux")
        webContainer("Java SE")
        javaVersion("Java 21")
    })

    setDeployment(closureOf<com.microsoft.azure.gradle.configuration.GradleDeploymentConfig> {
        resources(closureOf<com.microsoft.azure.gradle.configuration.GradleDeploymentResources> {
            resource(closureOf<com.microsoft.azure.gradle.configuration.GradleDeploymentResource> {
                type("jar")
                directory("${project.buildDir}/libs")
                includes(closureOf<MutableList<String>> { add("embedded-server-all.jar") })
            })
        })
    })

    setAuth(closureOf<com.microsoft.azure.gradle.auth.GradleAuthConfig> {
        type = "azure_cli"
    })
}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 215f95e and 26e4697.

📒 Files selected for processing (2)
  • ktor.tree (1 hunks)
  • topics/azure-app-service.md (1 hunks)
🧰 Additional context used
🪛 LanguageTool
topics/azure-app-service.md

[grammar] ~47-~47: There might be a mistake here.
Context: ... ### Step 2: Add plugins {id="plugins"} Open the build.gradle.kts file and add...

(QB_NEW_EN)

🪛 markdownlint-cli2 (0.17.2)
topics/azure-app-service.md

37-37: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


74-74: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


113-113: Link fragments should be valid

(MD051, link-fragments)


143-143: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


165-165: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


171-171: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🔇 Additional comments (1)
ktor.tree (1)

261-261: TOC entry looks good

Nice addition under Publishing; consistent with neighboring entries.

…updated version of Ktor plugin, renamed JAR file in log example
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (7)
topics/azure-app-service.md (7)

22-26: Tighten wording for clarity.

-Here we'll specify the port number where to listen for requests.
+Specify the port the app listens on.

38-46: Add language to fenced code block (fixes MD040).

-   ```
+   ```hocon
    ktor {
        deployment {
            port = ${PORT:8080}
        }
    }
    ```

74-104: Code fence language + typo in comment ("farJar" → "fatJar").

-```
+```kotlin
 // Rename the fat JAR to the name that the deploy task expects
 ktor {
     fatJar {
         archiveFileName.set("embedded-server.jar")
     }
 }
 
 // Disable the `jar` task that Azure Plugin would normally run
-// to deploy the archive created by the `farJar` task instead
+// to deploy the archive created by the `fatJar` task instead
 tasks.named("jar") {
     enabled = false
 }
 
 // Azure Webapp Plugin configuration
 azurewebapp {

113-113: Fix linted fragment link (MD051).

The custom ID may not be recognized by markdownlint. Simplest: drop the fragment link.

-First, to build the fat JAR, execute the `buildFatJar` task provided by the [Ktor plugin](#plugins) running the command below:
+First, to build the fat JAR, execute the `buildFatJar` task provided by the Ktor plugin:

143-157: Add language to log block (fixes MD040).

-```
+```text
 > Task: :embedded-server:azureWebAppDeploy
 Auth type: AZURE_CLI
 Username: [email protected]
 Subscription: Some Subscription(13936cf1-cc18-40be-a0d4-177fe532b3dd)
 Start creation Resource Group(resource-group) in region (Some Region)
 Resource Group (resource-group) is successfully created.
 Start creating App Service plan (asp-your-webapp-name)...
 App Service plan (asp-your-webapp-name) is successfully created
 Start creating Web App(your-webapp-name)...
 Web App(your-webapp-name) is successfully created
 Trying to deploy artifact to your-webapp-name...
 Deploying (C:\docs\ktor-documentation\codeSnippets\snippets\embedded-server\build\libs\embedded-server.jar)[jar] ...
 Application url: https://your-webapp-name.azurewebsites.net

---

`165-167`: **Add language to CLI block (fixes MD040).**


```diff
-```
+```bash
 az webapp deploy -g RESOURCE-GROUP-NAME -n WEBAPP-NAME --src-path ./path/to/embedded-server.jar --restart true

---

`171-184`: **Add language to log block (fixes MD040).**


```diff
-```
+```text
 Deployment type: jar. To override deployment type, please specify the --type parameter. Possible values: war, jar, ear, zip, startup, script, static
 Initiating deployment
 Deploying from local path: ./snippets/embedded-server/build/libs/embedded-server.jar
 Warming up Kudu before deployment.
 Warmed up Kudu instance successfully.
 Polling the status of sync deployment. Start Time: 2025-09-07 00:07:14.729383+00:00 UTC
 Status: Build successful. Time: 5(s)
 Status: Starting the site... Time: 23(s)
 Status: Starting the site... Time: 41(s)
 Status: Site started successfully. Time: 44(s)
 Deployment has completed successfully
 You can visit your app at: http://your-app-name.some-region.azurewebsites.net

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used**: CodeRabbit UI

**Review profile**: CHILL

**Plan**: Pro

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 26e469797f53b1f96e3652b5b945ec695409a984 and 35dbe8502e45687b13281c1c1d75ecfdbcb62f48.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `topics/azure-app-service.md` (1 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🪛 markdownlint-cli2 (0.17.2)</summary>

<details>
<summary>topics/azure-app-service.md</summary>

38-38: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

---

74-74: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

---

113-113: Link fragments should be valid

(MD051, link-fragments)

---

143-143: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

---

165-165: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

---

171-171: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

</details>

</details>

</details>

<details>
<summary>🔇 Additional comments (4)</summary><blockquote>

<details>
<summary>topics/azure-app-service.md (4)</summary><blockquote>

`28-35`: **Good: safe PORT handling with fallback.**

Reading PORT via toIntOrNull with 8080 default is correct and avoids crashes.

---

`16-16`: **Fix empty link text (renders nothing).**

Provide anchor text for the link.


```diff
-Create a sample application as described in [](server-create-a-new-project.topic). This example will show code and commands based on the following projects: [embedded-server](https://github.com/ktorio/ktor-documentation/tree/%ktor_version%/codeSnippets/snippets/embedded-server) and [engine-main](https://github.com/ktorio/ktor-documentation/tree/%ktor_version%/codeSnippets/snippets/engine-main).
+Create a sample application as described in [Create a new Ktor project](server-create-a-new-project.topic). This example will show code and commands based on the following projects: [embedded-server](https://github.com/ktorio/ktor-documentation/tree/%ktor_version%/codeSnippets/snippets/embedded-server) and [engine-main](https://github.com/ktorio/ktor-documentation/tree/%ktor_version%/codeSnippets/snippets/engine-main).
⛔ Skipped due to learnings
Learnt from: osipxd
PR: ktorio/ktor-documentation#602
File: topics/client-responses.md:91-91
Timestamp: 2025-03-24T15:17:05.086Z
Learning: In Writerside (the documentation engine used for Ktor docs), empty link brackets `[]()` are a special syntax feature. Without any text in the brackets, Writerside will automatically use the title of the referenced element or the URL if it is an external link. This is intentional and not an error.

132-139: No changes required; azureWebAppDeploy is the correct, case-sensitive task name.


49-56: No update needed for Azure WebApp Gradle plugin version. Version 1.10.0 (released Jan 10, 2024) is the latest stable release.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (1)
topics/azure-app-service.md (1)

72-104: Kotlin DSL: add missing import for closureOf or the snippet won’t compile

Without this import, copy-paste fails in build.gradle.kts.

 Otherwise, add the following entries to `build.gradle.kts` at the end of the file so that the Azure Webapp Plugin creates one for you:
 
+Add this import at the very top of `build.gradle.kts`:
+
+```kotlin
+import org.gradle.kotlin.dsl.closureOf
+```
+
 ```kotlin
  // Rename the fat JAR to the name that the deploy task expects
 ktor {
🧹 Nitpick comments (6)
topics/azure-app-service.md (6)

12-12: Update Azure CLI link to Learn domain

Use the Learn URL to avoid redirects.

-* The [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli) installed in your machine.
+* The [Azure CLI](https://learn.microsoft.com/cli/azure/install-azure-cli) installed on your machine.

38-44: Add language to fenced code block (HOCON) to satisfy markdownlint

This fixes MD040 and improves highlighting.

-   ```
+   ```hocon
    ktor {
        deployment {
            port = ${PORT:8080}
        }
    }
    ```

24-35: Add note to bind to 0.0.0.0 (not only localhost)

Avoids “listens only on loopback” issues on App Service.

    }.start(wait = true)
 }

+> Note: Ensure the server binds to 0.0.0.0 (the default for Netty). Do not bind only to localhost, or the app won’t be reachable from App Service.


---

`60-66`: **Clarify mainClass for engine-main projects**

Users of engine-main should set EngineMain.


```diff
 }

+If you created the project with the “engine-main” template, set:
+
+```kotlin
+application {

  • mainClass.set("io.ktor.server.netty.EngineMain")
    +}
    +```

---

`75-86`: **Make deployment depend on fat JAR build**

Prevents deploying a stale or missing artifact.


```diff
 tasks.named("jar") {
     enabled = false
 }
 
+// Ensure the deploy task builds the fat JAR first
+tasks.named("azureWebAppDeploy") {
+    dependsOn("buildFatJar")
+}

Please verify that the Gradle task name matches the plugin’s deploy task in your environment.


183-183: Use HTTPS for final app URL (consistency and security)

Earlier example uses HTTPS; align this one too.

-You can visit your app at: http://your-app-name.some-region.azurewebsites.net
+You can visit your app at: https://your-app-name.some-region.azurewebsites.net
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 35dbe85 and e79c31b.

📒 Files selected for processing (1)
  • topics/azure-app-service.md (1 hunks)
🧰 Additional context used
🪛 markdownlint-cli2 (0.17.2)
topics/azure-app-service.md

38-38: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


113-113: Link fragments should be valid

(MD051, link-fragments)

🔇 Additional comments (2)
topics/azure-app-service.md (2)

113-115: Anchor check: verify (#plugins) resolves on the site

Static analysis flagged MD051. If your site generator doesn’t honor {id="plugins"}, consider linking to the generated heading anchor or keep the explicit id but confirm it renders.


53-55: Confirm plugin versions before publishing

%ktor_version% is good; please verify the Azure WebApp Gradle plugin version is the latest recommended at release time.

If needed, I can help run a quick check and update the pin.

…ldFatJar, moved buildFatJar paragraph to existing webapp case
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
topics/azure-app-service.md (1)

108-116: Kotlin DSL: add missing closureOf import or avoid it.

Without import org.gradle.kotlin.dsl.closureOf, copy-paste fails. Alternatively, use the plugin’s Kotlin lambda overloads if available.

Add at the top of build.gradle.kts:

import org.gradle.kotlin.dsl.closureOf

Or replace with actions (if supported by the plugin):

setRuntime(Action<com.microsoft.azure.gradle.configuration.GradleRuntimeConfig> {
  os("Linux"); webContainer("Java SE"); javaVersion("Java 21")
})
setAuth(Action<com.microsoft.azure.gradle.auth.GradleAuthConfig> {
  type = "azure_cli"
})
🧹 Nitpick comments (5)
topics/azure-app-service.md (5)

38-46: Specify code-fence language for application.conf.

Adds syntax highlighting and fixes MD040.

-   ```
+   ```hocon
    ktor {
        deployment {
            port = ${PORT:8080}
        }
    }
    ```

24-35: Consider documenting bind host = 0.0.0.0.

Some setups bind to loopback by default; being explicit avoids “site up but not reachable” issues.

    fun runBasicServer() {
       val port = System.getenv("PORT")?.toIntOrNull() ?: 8080
-      embeddedServer(Netty, port = port) {
+      embeddedServer(Netty, port = port, host = "0.0.0.0") {
           // ...
       }.start(wait = true)
    }

Alternatively, in application.conf:

ktor {
  deployment {
    host = 0.0.0.0
    port = ${PORT:8080}
  }
}

163-171: Tighten grammar and ensure internal anchor passes linters.

Small grammar fix; also rephrase the link text while keeping the same #plugins anchor.

-If you had an existing Java web app in Azure App Service build the fat JAR, executing the `buildFatJar` task provided by the [Ktor plugin](#plugins):
+If you have an existing Java web app in Azure App Service, build the fat JAR by executing the `buildFatJar` task provided in [Step 2: Add plugins](#plugins):

176-178: Be explicit about deployment type.

az webapp deploy usually auto-detects, but --type jar removes ambiguity.

-az webapp deploy -g RESOURCE-GROUP-NAME -n WEBAPP-NAME --src-path ./path/to/embedded-server.jar --restart true
+az webapp deploy -g RESOURCE-GROUP-NAME -n WEBAPP-NAME --type jar --src-path ./path/to/embedded-server.jar --restart true

5-7: Avoid repeating the opening sentence.

The paragraph duplicates the link-summary.

-This tutorial shows how to build, configure and deploy your Ktor application to Azure App Service.
+This tutorial shows how to build, configure, and deploy your Ktor application to Azure App Service.

(If you keep both, at least fix the serial comma.)

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e79c31b and 6daaa34.

📒 Files selected for processing (1)
  • topics/azure-app-service.md (1 hunks)
🧰 Additional context used
🪛 markdownlint-cli2 (0.17.2)
topics/azure-app-service.md

38-38: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


163-163: Link fragments should be valid

(MD051, link-fragments)

🔇 Additional comments (3)
topics/azure-app-service.md (3)

90-100: Confirm deployment artifact selection with the Azure plugin.

Disabling jar and renaming the fat JAR is fine; please verify the plugin indeed picks build/libs/embedded-server.jar without extra config, and that no other JARs in that folder cause ambiguity.


16-16: Fix empty link text (broken Markdown).

The link has no visible text, which renders incorrectly.

-Create a sample application as described in [](server-create-a-new-project.topic). This example will show code and commands based on the following projects: [embedded-server](https://github.com/ktorio/ktor-documentation/tree/%ktor_version%/codeSnippets/snippets/embedded-server) and [engine-main](https://github.com/ktorio/ktor-documentation/tree/%ktor_version%/codeSnippets/snippets/engine-main).
+Create a sample application as described in [Create a new Ktor project](server-create-a-new-project.topic). This example will show code and commands based on the following projects: [embedded-server](https://github.com/ktorio/ktor-documentation/tree/%ktor_version%/codeSnippets/snippets/embedded-server) and [engine-main](https://github.com/ktorio/ktor-documentation/tree/%ktor_version%/codeSnippets/snippets/engine-main).
⛔ Skipped due to learnings
Learnt from: osipxd
PR: ktorio/ktor-documentation#602
File: topics/client-responses.md:91-91
Timestamp: 2025-03-24T15:17:05.086Z
Learning: In Writerside (the documentation engine used for Ktor docs), empty link brackets `[]()` are a special syntax feature. Without any text in the brackets, Writerside will automatically use the title of the referenced element or the URL if it is an external link. This is intentional and not an error.

50-55: Bump Ktor plugin version to 3.1.3
Azure WebApp plugin 1.10.0 is already the latest stable release; update the Ktor placeholder to match the current io.ktor.plugin version:

- id("io.ktor.plugin") version "%ktor_version%"
+ id("io.ktor.plugin") version "3.1.3"

Likely an incorrect or invalid review comment.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (1)
topics/azure-app-service.md (1)

101-116: Kotlin DSL: closureOf requires an import; or switch to Action-style blocks.

As-is, users copying this into build.gradle.kts will hit “Unresolved reference: closureOf.” Add the import, or (if supported by the plugin) use Kotlin Action-lambda overloads.

Add at the top of build.gradle.kts:

import org.gradle.kotlin.dsl.closureOf

Or replace with Action-style configuration (if available):

azurewebapp {
  // ...
  runtime {
    os = "Linux"
    webContainer = "Java SE"
    javaVersion = "Java 21"
  }
  auth {
    type = "azure_cli"
  }
}

Can you confirm whether the plugin exposes these Kotlin DSL accessors? If not, keep closureOf with the import.

🧹 Nitpick comments (6)
topics/azure-app-service.md (6)

5-8: Avoid repeating the intro sentence.

The sentence on Line 7 duplicates the link-summary. Consider removing or rephrasing Line 7.

-This tutorial shows how to build, configure and deploy your Ktor application to Azure App Service.
+In this guide, you’ll build, configure, and deploy a Ktor app to Azure App Service.

38-44: Add language to fenced code block (HOCON).

This fixes MD040 and improves highlighting.

-```
+```hocon
 ktor {
     deployment {
         port = ${PORT:8080}
     }
 }

---

`121-123`: **Tiny enhancement: show how to fetch subscription/regions.**

Consider adding a tip under this list for quick retrieval.  

```diff
 * The list of values for `region` can be obtained with the following Azure CLI command: `az account list-locations --query "[].name" --output tsv` or search "App Service" in [this page](https://go.microsoft.com/fwlink/?linkid=2300348&clcid=0x409).
+* To get your current subscription ID: `az account show --query id -o tsv`

128-131: Tighten wording around authentication.

Minor grammar/readability tweak.

-The authentication method used by the Azure Web App Deploy plugin used in the configuration added earlier will use the Azure CLI. If you haven't done so, log in once with `az login` and follow the instructions.
+The Azure WebApp Gradle plugin is configured to authenticate via the Azure CLI. If you haven’t already, run `az login` and follow the prompts.

176-178: Be explicit about artifact type in az webapp deploy.

App Service usually auto-detects, but adding --type jar makes the command unambiguous.

-az webapp deploy -g RESOURCE-GROUP-NAME -n WEBAPP-NAME --src-path ./path/to/embedded-server.jar --restart true
+az webapp deploy -g RESOURCE-GROUP-NAME -n WEBAPP-NAME --type jar --src-path ./path/to/embedded-server.jar --restart true

49-56: Update plugin version notes

  • com.microsoft.azure.azurewebapp 1.10.0 is current; io.ktor.plugin latest stable is 3.1.3 (docs continue to use the %ktor_version% placeholder)
  • Clarify where the Kotlin/JVM plugin version is defined (e.g., settings.gradle[kts], version catalog, or gradle.properties)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6daaa34 and aae58af.

📒 Files selected for processing (1)
  • topics/azure-app-service.md (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-09-08T05:54:33.810Z
Learnt from: dfuenzalida
PR: ktorio/ktor-documentation#671
File: topics/azure-app-service.md:11-13
Timestamp: 2025-09-08T05:54:33.810Z
Learning: The Gradle wrapper (gradlew) generated by Ktor projects is sufficient for building and deploying to Azure App Service, eliminating the need for local Gradle installation as a prerequisite.

Applied to files:

  • topics/azure-app-service.md
📚 Learning: 2025-09-08T05:54:33.810Z
Learnt from: dfuenzalida
PR: ktorio/ktor-documentation#671
File: topics/azure-app-service.md:11-13
Timestamp: 2025-09-08T05:54:33.810Z
Learning: Azure App Service Java 21 runtime can run applications compiled with earlier Java versions, so specifying the exact JDK version as a requirement is unnecessary for Azure App Service deployments.

Applied to files:

  • topics/azure-app-service.md
🪛 markdownlint-cli2 (0.17.2)
topics/azure-app-service.md

38-38: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


163-163: Link fragments should be valid

(MD051, link-fragments)

🔇 Additional comments (6)
topics/azure-app-service.md (6)

11-13: Prereqs look lean and accurate (no hard JDK pin or local Gradle requirement).

Good call keeping this minimal; the Gradle wrapper suffices and Java 21 runtime on App Service can run apps compiled for earlier targets.


24-35: PORT handling is correct and resilient.

Reading PORT with a safe Int fallback (8080) and providing the application.conf alternative is spot on for App Service.


60-73: Main class examples are clear for both templates.

Good clarity for embedded-server vs engine-main.


83-99: Build pipeline wiring is correct.

Renaming the fat JAR, disabling jar, and making azureWebAppDeploy depend on buildFatJar is a pragmatic setup.


163-171: MD051 appears to be a false positive.

The fragment (#plugins) matches the explicit id on the heading. No action needed.


16-16: Fix empty link text.

The link to “server-create-a-new-project.topic” has no anchor text, which will render poorly.

-Create a sample application as described in [](server-create-a-new-project.topic).
+Create a sample application as described in [Create a new Ktor project](server-create-a-new-project.topic).
⛔ Skipped due to learnings
Learnt from: osipxd
PR: ktorio/ktor-documentation#602
File: topics/client-responses.md:91-91
Timestamp: 2025-03-24T15:17:05.086Z
Learning: In Writerside (the documentation engine used for Ktor docs), empty link brackets `[]()` are a special syntax feature. Without any text in the brackets, Writerside will automatically use the title of the referenced element or the URL if it is an external link. This is intentional and not an error.

@vnikolova vnikolova requested a review from e5l September 8, 2025 14:38
Copy link
Member

@e5l e5l left a comment

Choose a reason for hiding this comment

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

Hey @dfuenzalida, thank you for the PR. LGTM

@vnikolova, @nomisRev could you also check?

@e5l e5l requested a review from vnikolova September 9, 2025 07:25
Copy link
Collaborator

@vnikolova vnikolova left a comment

Choose a reason for hiding this comment

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

Thanks for the contribution @dfuenzalida ! 🙏 It already looks pretty good. I’ve added some suggestions to improve clarity and bring it more in line with our documentation style.

Copy link

@nomisRev nomisRev left a comment

Choose a reason for hiding this comment

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

Hi @dfuenzalida,

Thank you for opening this PR 🥳

Can Azure Container Registry be used instead of fatJar? This is often a preferred approach by many. Ktor has a Gradle plugin that allows publishing to external registries.

I think we can shorten the Set up the application by mostly referring to the original pages, and perhaps introducing I'm afraid we otherwise introduce too much duplication on the website. Instead just focusing on the Azure related configuration. WDYT @vnikolova @e5l?

@vnikolova
Copy link
Collaborator

I think we can shorten the Set up the application by mostly referring to the original pages, and perhaps introducing I'm afraid we otherwise introduce too much duplication on the website. Instead just focusing on the Azure related configuration. WDYT @vnikolova @e5l?

I think this amount of duplication is fine as it's short and it saves the user time from switching between different topics. I see we also include this set up in other deployment topics, such as for Heroku and Sevalla.

@dfuenzalida
Copy link
Author

@nomisRev

Can Azure Container Registry be used instead of fatJar? This is often a preferred approach by many. Ktor has a Gradle plugin that allows publishing to external registries.

I can look into publishing to Azure Container Registry from the Gradle plugin in an upcoming PR. My impression is that while there are some similarities with other cloud providers, the Azure Webapp Plugin might be an easier experience.

dfuenzalida and others added 11 commits September 9, 2025 23:43
Co-authored-by:  Vik Nikolova <[email protected]>
Co-authored-by:  Vik Nikolova <[email protected]>
Co-authored-by:  Vik Nikolova <[email protected]>
Co-authored-by:  Vik Nikolova <[email protected]>
Co-authored-by:  Vik Nikolova <[email protected]>
Co-authored-by:  Vik Nikolova <[email protected]>
Co-authored-by:  Vik Nikolova <[email protected]>
Co-authored-by:  Vik Nikolova <[email protected]>
Co-authored-by:  Vik Nikolova <[email protected]>
Co-authored-by:  Vik Nikolova <[email protected]>
Co-authored-by:  Vik Nikolova <[email protected]>
@dfuenzalida
Copy link
Author

@coderabbitai review

Copy link

coderabbitai bot commented Sep 11, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
topics/azure-app-service.md (1)

108-116: closureOf requires an import in Kotlin DSL (or avoid closureOf entirely)

As written, copy-paste into build.gradle.kts fails without the import. Either add the import or switch to the plugin’s Kotlin lambda overloads if available.

// Place at the top of build.gradle.kts
import org.gradle.kotlin.dsl.closureOf

Optionally replace setRuntime/setAuth + closureOf with Kotlin lambdas if supported by the plugin.

🧹 Nitpick comments (7)
topics/azure-app-service.md (7)

38-45: Add a language to the application.conf code fence to satisfy MD040

Specify HOCON for syntax highlighting and to fix the linter warning.

-   ```
+   ```hocon
    ktor {
        deployment {
            port = ${PORT:8080}
        }
    }
    ```

128-129: Tighten wording of the authentication sentence

Minor clarity and style tweak.

-The authentication method used by the Azure Web App Deploy plugin uses the Azure CLI. If you haven't already, log in once with `az login` and follow the instructions.
+The Azure Web App Deploy plugin authenticates via the Azure CLI. If you haven't already, run `az login` and follow the instructions.

101-116: Consider explicitly setting the deployment artifact to avoid implicit detection

You disable the jar task and depend on buildFatJar, which works in many setups, but future plugin changes might not pick the intended JAR automatically. Consider explicitly pointing the plugin to embedded-server.jar in the deployment config. Please verify exact DSL with the plugin docs.


119-123: Add a note on globally unique appName

appName must be globally unique (affects the azurewebsites.net hostname). This saves users a failed first run.

Example addition right below this paragraph:

  • Note: appName must be unique across all Azure App Service apps (it determines https://.azurewebsites.net).

11-13: Add a JDK prerequisite (version‑agnostic)

Building the sample requires a local JDK; the App Service runtime can still be Java 21 even if you compile for an earlier target.

 Before starting this tutorial, you will need the following:
 * An Azure account ([Free trial here](https://azure.microsoft.com/en-us/free/)).
 * The [Azure CLI](https://learn.microsoft.com/cli/azure/install-azure-cli) installed on your machine.
+* A local JDK compatible with your project (for example, Java 17 or 21). The App Service Java 21 runtime can run applications compiled with earlier Java versions.

163-165: Fix or verify the local anchor link to “Ktor plugin”

The linter flags (#plugins). If this doc engine requires fully qualified topic anchors, switch to a topic‑scoped link; otherwise, confirm the build recognizes the custom {id="plugins"} anchor.

-If you already have an existing Java web app in Azure App Service, first build the fat JAR by executing the `buildFatJar` task provided by the [Ktor plugin](#plugins):
+If you already have an existing Java web app in Azure App Service, first build the fat JAR by executing the `buildFatJar` task provided by the [Ktor plugin](azure-app-service.md#plugins):

If the site generator auto-resolves (#plugins), keep it and ignore this change.


83-88: Rephrase “expects” to avoid implying a hard requirement

The plugin doesn’t inherently “expect” this name; we’re standardizing it for consistency with the commands/logs.

- // Rename the fat JAR to the name that the deploy task expects
+ // Rename the fat JAR to a predictable name used by the deploy task and examples
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between aae58af and 473ae3e.

📒 Files selected for processing (1)
  • topics/azure-app-service.md (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-09-08T05:54:33.821Z
Learnt from: dfuenzalida
PR: ktorio/ktor-documentation#671
File: topics/azure-app-service.md:11-13
Timestamp: 2025-09-08T05:54:33.821Z
Learning: The Gradle wrapper (gradlew) generated by Ktor projects is sufficient for building and deploying to Azure App Service, eliminating the need for local Gradle installation as a prerequisite.

Applied to files:

  • topics/azure-app-service.md
📚 Learning: 2025-09-08T05:54:33.821Z
Learnt from: dfuenzalida
PR: ktorio/ktor-documentation#671
File: topics/azure-app-service.md:11-13
Timestamp: 2025-09-08T05:54:33.821Z
Learning: Azure App Service Java 21 runtime can run applications compiled with earlier Java versions, so specifying the exact JDK version as a requirement is unnecessary for Azure App Service deployments.

Applied to files:

  • topics/azure-app-service.md
🪛 markdownlint-cli2 (0.17.2)
topics/azure-app-service.md

38-38: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


163-163: Link fragments should be valid

(MD051, link-fragments)

🔇 Additional comments (3)
topics/azure-app-service.md (3)

24-36: PORT handling is correct and resilient

Reading PORT with toIntOrNull and defaulting to 8080 is the right approach for App Service.


60-73: Good call-out on mainClass for fat JAR entrypoint

This avoids common deployment pitfalls.


49-55: Verify pinned plugin versions before publishing — confirmed

As of September 11, 2025: com.microsoft.azure.azurewebapp 1.10.0 is the latest stable (published January 10, 2024); io.ktor.plugin latest stable is 3.1.2 (published March 27, 2025). Keeping %ktor_version% is fine — no changes required. Confirm compatibility with your Gradle/Kotlin DSL before release.

@dfuenzalida
Copy link
Author

Hi @vnikolova @nomisRev , I wanted to check if you have any other comments or changes you'd want on this PR. Thanks!

Copy link
Collaborator

@vnikolova vnikolova left a comment

Choose a reason for hiding this comment

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

Thanks for the update, looks good to me! 👍

@vnikolova vnikolova requested a review from nomisRev September 30, 2025 10:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants