Skip to content

Commit fdb0334

Browse files
authored
Implement CI pipeline (#11)
- support Changelog files and automatic update after a release - workflows to build and publish release drafts - support for automatic dependencies update via Github's dependabot.
1 parent 57e48ea commit fdb0334

File tree

8 files changed

+305
-23
lines changed

8 files changed

+305
-23
lines changed

.github/dependabot.yml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Dependabot configuration:
2+
# https://docs.github.com/en/free-pro-team@latest/github/administering-a-repository/configuration-options-for-dependency-updates
3+
4+
version: 2
5+
updates:
6+
# Maintain dependencies for Gradle dependencies
7+
- package-ecosystem: "gradle"
8+
directory: "/"
9+
target-branch: "main"
10+
schedule:
11+
interval: "weekly"
12+
time: "06:00"
13+
timezone: "America/Chicago"
14+
ignore:
15+
# these depend on the toolbox API and should be updated manually
16+
- dependency-name: "org.jetbrains.kotlin.jvm"
17+
- dependency-name: "org.jetbrains.kotlin.plugin.serialization"
18+
- dependency-name: "com.google.devtools.ksp"
19+
# these can have breaking changes
20+
- dependency-name: "com.jetbrains.toolbox:core-api"
21+
- dependency-name: "com.jetbrains.toolbox:ui-api"
22+
- dependency-name: "com.jetbrains.toolbox:remote-dev-api"
23+
commit-message:
24+
prefix: "chore"
25+
# Maintain dependencies for GitHub Actions
26+
- package-ecosystem: "github-actions"
27+
directory: "/"
28+
target-branch: "main"
29+
schedule:
30+
interval: "weekly"
31+
time: "06:00"
32+
timezone: "America/Chicago"
33+
commit-message:
34+
prefix: "chore"

.github/workflows/build.yml

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
# GitHub Actions workflow for testing and preparing the plugin release.
2+
# GitHub Actions reference: https://help.github.com/en/actions
3+
4+
name: Coder Toolbox Plugin Build
5+
6+
on:
7+
push:
8+
branches:
9+
- main
10+
pull_request:
11+
12+
jobs:
13+
# Run plugin tests on every supported platform.
14+
test:
15+
strategy:
16+
matrix:
17+
platform:
18+
- ubuntu-latest
19+
- macos-latest
20+
- windows-latest
21+
runs-on: ${{ matrix.platform }}
22+
steps:
23+
- uses: actions/checkout@v4.2.2
24+
25+
- uses: actions/setup-java@v4
26+
with:
27+
distribution: zulu
28+
java-version: 21
29+
cache: gradle
30+
31+
- uses: gradle/wrapper-validation-action@v3.5.0
32+
33+
# Run tests
34+
- run: ./gradlew test --info
35+
36+
# Collect Tests Result of failed tests
37+
- if: ${{ failure() }}
38+
uses: actions/upload-artifact@v4
39+
with:
40+
name: tests-result
41+
path: ${{ github.workspace }}/build/reports/tests
42+
43+
build:
44+
name: Build
45+
needs: test
46+
runs-on: ubuntu-latest
47+
outputs:
48+
version: ${{ steps.properties.outputs.version }}
49+
changelog: ${{ steps.properties.outputs.changelog }}
50+
steps:
51+
# Check out current repository
52+
- name: Fetch Sources
53+
uses: actions/checkout@v4.2.2
54+
55+
# Setup Java 21 environment for the next steps
56+
- name: Setup Java
57+
uses: actions/setup-java@v4
58+
with:
59+
distribution: zulu
60+
java-version: 21
61+
cache: gradle
62+
63+
# Set environment variables
64+
- name: Export Properties
65+
id: properties
66+
shell: bash
67+
run: |
68+
PROPERTIES="$(./gradlew properties --console=plain -q)"
69+
VERSION="$(echo "$PROPERTIES" | grep "^version:" | cut -f2- -d ' ')"
70+
NAME="$(echo "$PROPERTIES" | grep "^group:" | cut -f2- -d ' ')"
71+
CHANGELOG="$(./gradlew getChangelog --unreleased --no-header --console=plain -q)"
72+
CHANGELOG="${CHANGELOG//'%'/'%25'}"
73+
CHANGELOG="${CHANGELOG//$'\n'/'%0A'}"
74+
CHANGELOG="${CHANGELOG//$'\r'/'%0D'}"
75+
echo "version=$VERSION" >> $GITHUB_OUTPUT
76+
echo "name=$NAME" >> $GITHUB_OUTPUT
77+
echo "changelog=$CHANGELOG" >> $GITHUB_OUTPUT
78+
79+
# Run plugin build
80+
- name: Run Build
81+
run: ./gradlew clean pluginZip --info
82+
83+
# Prepare plugin archive content for creating artifact
84+
- name: Prepare Plugin Artifact
85+
id: artifact
86+
shell: bash
87+
run: |
88+
cd ${{ github.workspace }}/build/distributions
89+
FILENAME=$(ls *.zip)
90+
unzip "$FILENAME" -d content
91+
echo "filename=${FILENAME:0:-4}" >> $GITHUB_OUTPUT
92+
93+
# Store already-built plugin as an artifact for downloading
94+
- name: Upload artifact
95+
uses: actions/upload-artifact@v4
96+
with:
97+
name: ${{ steps.artifact.outputs.filename }}
98+
path: ./build/distributions/content/*/*
99+
100+
# Prepare a draft release for GitHub Releases page for the manual verification
101+
# If accepted and published, release workflow would be triggered
102+
releaseDraft:
103+
name: Release Draft
104+
if: github.event_name != 'pull_request'
105+
needs: build
106+
runs-on: ubuntu-latest
107+
steps:
108+
109+
# Check out current repository
110+
- name: Fetch Sources
111+
uses: actions/checkout@v4.2.2
112+
113+
# Remove old release drafts by using GitHub CLI
114+
- name: Remove Old Release Drafts
115+
env:
116+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
117+
run: |
118+
gh api repos/${{ github.repository }}/releases \
119+
--jq '.[] | select(.draft == true) | .id' \
120+
| xargs -I '{}' gh api -X DELETE repos/${{ github.repository }}/releases/{}
121+
122+
# Create new release draft - which is not publicly visible and requires manual acceptance
123+
- name: Create Release Draft
124+
env:
125+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
126+
run: |
127+
echo "${{ needs.build.outputs.changelog }}" > RELEASE_NOTES.md
128+
gh release create v${{ needs.build.outputs.version }} \
129+
--draft \
130+
--target ${GITHUB_REF_NAME} \
131+
--title "v${{ needs.build.outputs.version }}" \
132+
--notes-file RELEASE_NOTES.md

.github/workflows/release.yml

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
# GitHub Actions Workflow created for handling the release process based on the draft release prepared with the Build workflow.
2+
3+
name: Release
4+
on:
5+
release:
6+
types: [ prereleased, released ]
7+
8+
jobs:
9+
10+
# Prepare and publish the plugin to the Marketplace repository
11+
release:
12+
name: Publish Plugin
13+
runs-on: ubuntu-latest
14+
steps:
15+
16+
# Check out current repository
17+
- name: Fetch Sources
18+
uses: actions/checkout@v4.2.2
19+
with:
20+
ref: ${{ github.event.release.tag_name }}
21+
22+
# Setup Java 21 environment for the next steps
23+
- name: Setup Java
24+
uses: actions/setup-java@v4
25+
with:
26+
distribution: zulu
27+
java-version: 21
28+
cache: gradle
29+
30+
# Set environment variables
31+
- name: Export Properties
32+
id: properties
33+
shell: bash
34+
run: |
35+
CHANGELOG="$(cat << 'EOM' | sed -e 's/^[[:space:]]*$//g' -e '/./,$!d'
36+
${{ github.event.release.body }}
37+
EOM
38+
)"
39+
40+
CHANGELOG="${CHANGELOG//'%'/'%25'}"
41+
CHANGELOG="${CHANGELOG//$'\n'/'%0A'}"
42+
CHANGELOG="${CHANGELOG//$'\r'/'%0D'}"
43+
44+
echo "changelog=$CHANGELOG" >> $GITHUB_OUTPUT
45+
46+
# Update Unreleased section with the current release note
47+
- name: Patch Changelog
48+
if: ${{ steps.properties.outputs.changelog != '' }}
49+
env:
50+
CHANGELOG: ${{ steps.properties.outputs.changelog }}
51+
run: |
52+
./gradlew patchChangelog --release-note="$CHANGELOG"
53+
54+
# Publish the plugin to the Marketplace
55+
# TODO - enable this step (by removing the `if` block) when JetBrains is clear about release procedures
56+
- name: Publish Plugin
57+
if: false
58+
env:
59+
PUBLISH_TOKEN: ${{ secrets.PUBLISH_TOKEN }}
60+
CERTIFICATE_CHAIN: ${{ secrets.CERTIFICATE_CHAIN }}
61+
PRIVATE_KEY: ${{ secrets.PRIVATE_KEY }}
62+
PRIVATE_KEY_PASSWORD: ${{ secrets.PRIVATE_KEY_PASSWORD }}
63+
run: ./gradlew publishPlugin --info
64+
65+
# Upload artifact as a release asset
66+
- name: Upload Release Asset
67+
env:
68+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
69+
run: gh release upload ${{ github.event.release.tag_name }} ./build/distributions/*
70+
71+
# Create pull request
72+
- name: Create Pull Request
73+
if: ${{ steps.properties.outputs.changelog != '' }}
74+
env:
75+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
76+
run: |
77+
VERSION="${{ github.event.release.tag_name }}"
78+
BRANCH="changelog-update-$VERSION"
79+
80+
git config user.email "action@github.com"
81+
git config user.name "GitHub Action"
82+
83+
git checkout -b $BRANCH
84+
git commit -am "Changelog update - $VERSION"
85+
git push --set-upstream origin $BRANCH
86+
87+
gh pr create \
88+
--title "Changelog update - \`$VERSION\`" \
89+
--body "Current pull request contains patched \`CHANGELOG.md\` file for the \`$VERSION\` version." \
90+
--base main \
91+
--head $BRANCH

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,7 @@ build
44
jvm/
55

66
# IntelliJ IDEA
7-
.idea
7+
.idea
8+
9+
# hidden macOS metadata files
10+
.DS_Store

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Coder Toolbox Plugin Changelog
2+
3+
## Unreleased
4+
5+
### Added
6+
7+
- initial support for JetBrains Toolbox 2.6.0.38311 with the possibility to manage the workspaces - i.e. start, stop,
8+
update and delete actions and also quick shortcuts to templates, web terminal and dashboard.

build.gradle.kts

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ plugins {
1313
alias(libs.plugins.dependency.license.report)
1414
alias(libs.plugins.ksp)
1515
alias(libs.plugins.gradle.wrapper)
16+
alias(libs.plugins.changelog)
1617
}
1718

1819
buildscript {
@@ -50,6 +51,16 @@ dependencies {
5051
testImplementation(kotlin("test"))
5152
}
5253

54+
val pluginId = properties("group")
55+
val pluginName = properties("name")
56+
val pluginVersion = properties("version")
57+
58+
changelog {
59+
version.set(pluginVersion)
60+
groups.set(emptyList())
61+
title.set("Coder Toolbox Plugin Changelog")
62+
}
63+
5364
licenseReport {
5465
renderers = arrayOf(JsonReportRenderer("dependencies.json"))
5566
filters = arrayOf(ExcludeTransitiveDependenciesFilter())
@@ -65,17 +76,19 @@ tasks.test {
6576
useJUnitPlatform()
6677
}
6778

68-
val pluginId = "com.coder.toolbox"
69-
val pluginVersion = "0.0.1"
70-
7179
val assemblePlugin by tasks.registering(Jar::class) {
7280
archiveBaseName.set(pluginId)
7381
from(sourceSets.main.get().output)
7482
}
7583

7684
val copyPlugin by tasks.creating(Sync::class.java) {
7785
dependsOn(assemblePlugin)
86+
fromCompileDependencies()
87+
88+
into(getPluginInstallDir())
89+
}
7890

91+
fun CopySpec.fromCompileDependencies() {
7992
from(assemblePlugin.get().outputs.files)
8093
from("src/main/resources") {
8194
include("extension.json")
@@ -97,8 +110,14 @@ val copyPlugin by tasks.creating(Sync::class.java) {
97110
}
98111
},
99112
)
113+
}
100114

101-
into(getPluginInstallDir())
115+
val pluginZip by tasks.creating(Zip::class) {
116+
dependsOn(assemblePlugin)
117+
118+
fromCompileDependencies()
119+
into(pluginId)
120+
archiveBaseName.set(pluginName)
102121
}
103122

104123
tasks.register("cleanAll", Delete::class.java) {
@@ -126,26 +145,14 @@ private fun getPluginInstallDir(): Path {
126145
return pluginsDir / pluginId
127146
}
128147

129-
val pluginZip by tasks.creating(Zip::class) {
130-
dependsOn(assemblePlugin)
131-
132-
from(assemblePlugin.get().outputs.files)
133-
from("src/main/resources") {
134-
include("extension.json")
135-
include("dependencies.json")
136-
}
137-
from("src/main/resources") {
138-
include("icon.svg")
139-
rename("icon.svg", "pluginIcon.svg")
140-
}
141-
archiveBaseName.set("$pluginId-$pluginVersion")
142-
}
143-
144-
val uploadPlugin by tasks.creating {
148+
val publishPlugin by tasks.creating {
145149
dependsOn(pluginZip)
146150

147151
doLast {
148-
val instance = PluginRepositoryFactory.create("https://plugins.jetbrains.com", project.property("pluginMarketplaceToken").toString())
152+
val instance = PluginRepositoryFactory.create(
153+
"https://plugins.jetbrains.com",
154+
project.property("PUBLISH_TOKEN").toString()
155+
)
149156

150157
// first upload
151158
// instance.uploader.uploadNewPlugin(pluginZip.outputs.files.singleFile, listOf("toolbox", "gateway"), LicenseUrl.APACHE_2_0, ProductFamily.TOOLBOX)
@@ -163,3 +170,5 @@ tasks.register("classpath") {
163170
)
164171
}
165172
}
173+
174+
fun properties(key: String) = project.findProperty(key).toString()

gradle.properties

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
version=0.1.0
2+
group=com.coder.toolbox
3+
name=coder-toolbox

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy