-
Notifications
You must be signed in to change notification settings - Fork 0
feat: Initial version #2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| { | ||
| "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json", | ||
| "release-type": "node", | ||
| "packages": { | ||
| ".": {} | ||
| }, | ||
| "bump-minor-pre-major": true, | ||
| "bump-patch-for-minor-pre-major": true | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| { | ||
| ".": "0.0.0" | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,99 @@ | ||
| name: Prepare Release | ||
|
|
||
| on: | ||
| push: | ||
| branches: | ||
| - main | ||
|
|
||
| permissions: {} | ||
|
|
||
| jobs: | ||
| release-please: | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 15 | ||
| environment: release | ||
| permissions: | ||
| contents: write | ||
| issues: write | ||
| pull-requests: write | ||
| outputs: | ||
| pr_branch: ${{ steps.pr-branch.outputs.branch }} | ||
| steps: | ||
| - name: Generate GitHub App token | ||
| id: app-token | ||
| uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 | ||
| with: | ||
| client-id: ${{ secrets.APP_ID }} | ||
| private-key: ${{ secrets.APP_PRIVATE_KEY }} | ||
| permission-contents: write | ||
| permission-pull-requests: write | ||
|
|
||
| - name: Run release-please action | ||
| id: release-please-action | ||
| uses: googleapis/release-please-action@45996ed1f6d02564a971a2fa1b5860e934307cf7 # v5.0.0 | ||
| with: | ||
| token: ${{ steps.app-token.outputs.token }} | ||
| config-file: .github/release-please-config.json | ||
| manifest-file: .github/release-please-manifest.json | ||
|
|
||
| - name: Extract PR branch | ||
| id: pr-branch | ||
| if: steps.release-please-action.outputs.pr | ||
| env: | ||
| PR_JSON: ${{ steps.release-please-action.outputs.pr }} | ||
| run: | | ||
| branch=$(echo "$PR_JSON" | jq -r '.headBranchName') | ||
| echo "branch=${branch}" >> $GITHUB_OUTPUT | ||
|
|
||
| build-action: | ||
| needs: release-please | ||
| if: needs.release-please.outputs.pr_branch | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 15 | ||
| environment: release | ||
| permissions: | ||
| contents: write | ||
| steps: | ||
| - name: Generate GitHub App token | ||
| id: app-token | ||
| uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 | ||
| with: | ||
| client-id: ${{ secrets.APP_ID }} | ||
| private-key: ${{ secrets.APP_PRIVATE_KEY }} | ||
| permission-contents: write | ||
| permission-pull-requests: write | ||
|
|
||
| - name: Checkout PR branch | ||
| uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 | ||
| with: | ||
| ref: ${{ needs.release-please.outputs.pr_branch }} | ||
| token: ${{ steps.app-token.outputs.token }} | ||
| persist-credentials: false | ||
|
|
||
| - name: Install pnpm | ||
Check warningCode scanning / CodeQL Checkout of untrusted code in a trusted context Medium
Potential unsafe checkout of untrusted pull request on privileged workflow.
|
||
| uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 | ||
|
|
||
| - name: Use Node.js 24.x | ||
| uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 | ||
| with: | ||
| node-version: 24.x | ||
| cache: "pnpm" | ||
|
|
||
| - name: Install dependencies | ||
| run: pnpm install --frozen-lockfile | ||
|
|
||
| - name: Build | ||
| run: pnpm build | ||
|
|
||
| - name: Commit dist to PR branch | ||
| env: | ||
| GH_TOKEN: ${{ steps.app-token.outputs.token }} | ||
| APP_SLUG: ${{ steps.app-token.outputs.app-slug }} | ||
| run: | | ||
| bot_id=$(gh api "/users/${APP_SLUG}[bot]" --jq .id) | ||
| git config user.name "${APP_SLUG}[bot]" | ||
| git config user.email "${bot_id}+${APP_SLUG}[bot]@users.noreply.github.com" | ||
| gh auth setup-git | ||
| git add dist/ | ||
| git diff --staged --quiet || git commit -m "chore: build dist" | ||
| git push | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| name: Tests | ||
|
|
||
| on: | ||
| push: | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| jobs: | ||
| test: | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 5 | ||
| permissions: | ||
| contents: read | ||
| pull-requests: read | ||
| id-token: write # For Codecov upload | ||
| steps: | ||
| - name: Checkout repository | ||
| uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 | ||
| with: | ||
| persist-credentials: false | ||
|
|
||
| - name: Install pnpm | ||
| uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 | ||
|
|
||
| - name: Use Node.js 24.x | ||
| uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 | ||
| with: | ||
| node-version: 24.x | ||
| cache: "pnpm" | ||
|
|
||
| - name: Install dependencies | ||
| run: pnpm install --frozen-lockfile | ||
|
|
||
| - name: Run tests | ||
| run: node --run test:coverage | ||
|
|
||
| - name: Upload coverage | ||
| uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0 | ||
| with: | ||
| use_oidc: true | ||
| fail_ci_if_error: true | ||
| files: ./lcov.info |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,2 @@ | ||
| node_modules/ | ||
| lcov.info |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,184 @@ | ||
| import { after, beforeEach, describe, mock, test } from "node:test"; | ||
| import assert from "node:assert/strict"; | ||
|
|
||
| const getInputMock = mock.fn<(name: string, options?: { required?: boolean }) => string>(); | ||
| const getBooleanInputMock = mock.fn<(name: string) => boolean>(); | ||
|
|
||
| mock.module("@actions/core", { | ||
| exports: { | ||
| getInput: getInputMock, | ||
| getBooleanInput: getBooleanInputMock, | ||
| }, | ||
| }); | ||
|
|
||
| const { getConfig } = await import("./config.ts"); | ||
|
|
||
| function setHub(value: string) { | ||
| getInputMock.mock.mockImplementation(() => value); | ||
| } | ||
|
|
||
| function setFlags(syncRepo: boolean, pullImages: boolean) { | ||
| getBooleanInputMock.mock.mockImplementation((name: string) => { | ||
| if (name === "syncRepo") { | ||
| return syncRepo; | ||
| } | ||
| if (name === "pullImages") { | ||
| return pullImages; | ||
| } | ||
| return false; | ||
| }); | ||
| } | ||
|
|
||
| beforeEach(() => { | ||
| getInputMock.mock.resetCalls(); | ||
| getBooleanInputMock.mock.resetCalls(); | ||
| setHub("https://orca.example.com"); | ||
| setFlags(true, false); | ||
| }); | ||
|
|
||
| after(() => { | ||
| mock.restoreAll(); | ||
| }); | ||
|
|
||
| describe("getConfig()", () => { | ||
| describe("URL normalization: trailing slashes", () => { | ||
| test("strips a single trailing slash", () => { | ||
| setHub("https://orca.example.com/"); | ||
| const result = getConfig(); | ||
| assert.equal(result.hubUrl, "https://orca.example.com"); | ||
| }); | ||
|
|
||
| test("strips multiple trailing slashes", () => { | ||
| setHub("https://orca.example.com///"); | ||
| const result = getConfig(); | ||
| assert.equal(result.hubUrl, "https://orca.example.com"); | ||
| }); | ||
|
|
||
| test("leaves URL without trailing slash unchanged", () => { | ||
| setHub("https://orca.example.com"); | ||
| const result = getConfig(); | ||
| assert.equal(result.hubUrl, "https://orca.example.com"); | ||
| }); | ||
| }); | ||
|
|
||
| describe("URL normalization: protocol", () => { | ||
| test("prepends https:// when no protocol is given", () => { | ||
| setHub("orca.example.com"); | ||
| const result = getConfig(); | ||
| assert.equal(result.hubUrl, "https://orca.example.com"); | ||
| }); | ||
|
|
||
| test("prepends https:// and strips trailing slash together", () => { | ||
| setHub("orca.example.com/"); | ||
| const result = getConfig(); | ||
| assert.equal(result.hubUrl, "https://orca.example.com"); | ||
| }); | ||
|
|
||
| test("preserves explicit https:// protocol", () => { | ||
| setHub("https://orca.example.com"); | ||
| const result = getConfig(); | ||
| assert.equal(result.hubUrl, "https://orca.example.com"); | ||
| }); | ||
|
|
||
| test("preserves explicit http:// protocol", () => { | ||
| setHub("http://orca.example.com"); | ||
| const result = getConfig(); | ||
| assert.equal(result.hubUrl, "http://orca.example.com"); | ||
| }); | ||
| }); | ||
|
|
||
| describe("URL validation: path component", () => { | ||
| test("throws when URL contains a path component", () => { | ||
| setHub("https://orca.example.com/some/path"); | ||
| assert.throws( | ||
| () => getConfig(), | ||
| (err: Error) => { | ||
| assert(err instanceof Error); | ||
| assert(err.message.includes("contains a path")); | ||
| return true; | ||
| }, | ||
| ); | ||
| }); | ||
|
|
||
| test("throws when bare hostname has a path component", () => { | ||
| setHub("orca.example.com/path"); | ||
| assert.throws( | ||
| () => getConfig(), | ||
| (err: Error) => { | ||
| assert(err instanceof Error); | ||
| assert(err.message.includes("contains a path")); | ||
| return true; | ||
| }, | ||
| ); | ||
| }); | ||
| }); | ||
|
|
||
| describe("URL validation: invalid URL", () => { | ||
| test("throws TypeError for a syntactically invalid URL", () => { | ||
| setHub("not a valid url with spaces"); | ||
| assert.throws(() => getConfig(), TypeError); | ||
| }); | ||
| }); | ||
|
|
||
| describe("flag validation", () => { | ||
| test("throws when both syncRepo and pullImages are false", () => { | ||
| setFlags(false, false); | ||
| assert.throws( | ||
| () => getConfig(), | ||
| (err: Error) => { | ||
| assert(err instanceof Error); | ||
| assert.equal(err.message, "At least one of syncRepo or pullImages must be set to true."); | ||
| return true; | ||
| }, | ||
| ); | ||
| }); | ||
|
|
||
| test("succeeds when only syncRepo is true", () => { | ||
| setFlags(true, false); | ||
| const result = getConfig(); | ||
| assert.equal(result.syncRepo, true); | ||
| assert.equal(result.pullImages, false); | ||
| }); | ||
|
|
||
| test("succeeds when only pullImages is true", () => { | ||
| setFlags(false, true); | ||
| const result = getConfig(); | ||
| assert.equal(result.syncRepo, false); | ||
| assert.equal(result.pullImages, true); | ||
| }); | ||
|
|
||
| test("succeeds when both are true", () => { | ||
| setFlags(true, true); | ||
| const result = getConfig(); | ||
| assert.equal(result.syncRepo, true); | ||
| assert.equal(result.pullImages, true); | ||
| }); | ||
| }); | ||
|
|
||
| describe("return value shape", () => { | ||
| test("constructs endpoint from hubUrl", () => { | ||
| setHub("https://orca.example.com"); | ||
| const result = getConfig(); | ||
| assert.equal(result.endpoint, "https://orca.example.com/api/v1/github-actions"); | ||
| }); | ||
|
|
||
| test("endpoint uses the normalized hubUrl (no trailing slash)", () => { | ||
| setHub("orca.example.com/"); | ||
| const result = getConfig(); | ||
| assert.equal(result.endpoint, "https://orca.example.com/api/v1/github-actions"); | ||
| }); | ||
|
|
||
| test("calls getInput once with 'hub'", () => { | ||
| getConfig(); | ||
| assert.equal(getInputMock.mock.callCount(), 1); | ||
| assert.equal(getInputMock.mock.calls[0]?.arguments[0], "hub"); | ||
| }); | ||
|
|
||
| test("calls getBooleanInput for 'syncRepo' and 'pullImages'", () => { | ||
| getConfig(); | ||
| const names = getBooleanInputMock.mock.calls.map((c) => c.arguments[0]); | ||
| assert(names.includes("syncRepo")); | ||
| assert(names.includes("pullImages")); | ||
| }); | ||
| }); | ||
| }); |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.