···11-/**
22- * Unit tests for the action's main functionality, src/main.ts
33- *
44- * These should be run as if the action was called from a workflow.
55- * Specifically, the inputs listed in `action.yml` should be set as environment
66- * variables following the pattern `INPUT_<INPUT_NAME>`.
77- */
88-99-// import * as core from '@actions/core'
1010-// import * as main from '../src/main'
1111-1212-// // Mock the action's main function
1313-// const runMock = jest.spyOn(main, 'run')
1414-1515-// // Other utilities
1616-// const timeRegex = /^\d{2}:\d{2}:\d{2}/
1717-1818-// // Mock the GitHub Actions core library
1919-// let debugMock: jest.SpiedFunction<typeof core.debug>
2020-// let errorMock: jest.SpiedFunction<typeof core.error>
2121-// let getInputMock: jest.SpiedFunction<typeof core.getInput>
2222-// let setFailedMock: jest.SpiedFunction<typeof core.setFailed>
2323-// let setOutputMock: jest.SpiedFunction<typeof core.setOutput>
2424-2525-// describe('action', () => {
2626-// beforeEach(() => {
2727-// jest.clearAllMocks()
2828-2929-// debugMock = jest.spyOn(core, 'debug').mockImplementation()
3030-// errorMock = jest.spyOn(core, 'error').mockImplementation()
3131-// getInputMock = jest.spyOn(core, 'getInput').mockImplementation()
3232-// setFailedMock = jest.spyOn(core, 'setFailed').mockImplementation()
3333-// setOutputMock = jest.spyOn(core, 'setOutput').mockImplementation()
3434-// })
3535-3636-// it('sets the time output', async () => {
3737-// // Set the action's inputs as return values from core.getInput()
3838-// getInputMock.mockImplementation(name => {
3939-// switch (name) {
4040-// case 'milliseconds':
4141-// return '500'
4242-// default:
4343-// return ''
4444-// }
4545-// })
4646-4747-// await main.run()
4848-// expect(runMock).toHaveReturned()
4949-5050-// // Verify that all of the core library functions were called correctly
5151-// expect(debugMock).toHaveBeenNthCalledWith(1, 'Waiting 500 milliseconds ...')
5252-// expect(debugMock).toHaveBeenNthCalledWith(
5353-// 2,
5454-// expect.stringMatching(timeRegex)
5555-// )
5656-// expect(debugMock).toHaveBeenNthCalledWith(
5757-// 3,
5858-// expect.stringMatching(timeRegex)
5959-// )
6060-// expect(setOutputMock).toHaveBeenNthCalledWith(
6161-// 1,
6262-// 'time',
6363-// expect.stringMatching(timeRegex)
6464-// )
6565-// expect(errorMock).not.toHaveBeenCalled()
6666-// })
6767-6868-// it('sets a failed status', async () => {
6969-// // Set the action's inputs as return values from core.getInput()
7070-// getInputMock.mockImplementation(name => {
7171-// switch (name) {
7272-// case 'milliseconds':
7373-// return 'this is not a number'
7474-// default:
7575-// return ''
7676-// }
7777-// })
7878-7979-// await main.run()
8080-// expect(runMock).toHaveReturned()
8181-8282-// // Verify that all of the core library functions were called correctly
8383-// expect(setFailedMock).toHaveBeenNthCalledWith(
8484-// 1,
8585-// 'milliseconds not a number'
8686-// )
8787-// expect(errorMock).not.toHaveBeenCalled()
8888-// })
8989-// })
···11-#!/bin/bash
22-33-# About:
44-#
55-# This is a helper script to tag and push a new release. GitHub Actions use
66-# release tags to allow users to select a specific version of the action to use.
77-#
88-# See: https://github.com/actions/typescript-action#publishing-a-new-release
99-#
1010-# This script will do the following:
1111-#
1212-# 1. Get the latest release tag
1313-# 2. Prompt the user for a new release tag
1414-# 3. Tag the new release
1515-# 4. Push the new tag to the remote
1616-#
1717-# Usage:
1818-#
1919-# script/release
2020-2121-# Terminal colors
2222-OFF='\033[0m'
2323-RED='\033[0;31m'
2424-GREEN='\033[0;32m'
2525-BLUE='\033[0;34m'
2626-2727-# Get the latest release tag
2828-latest_tag=$(git describe --tags "$(git rev-list --tags --max-count=1)")
2929-3030-if [[ -z "$latest_tag" ]]; then
3131- # There are no existing release tags
3232- echo -e "No tags found (yet) - Continue to create and push your first tag"
3333- latest_tag="[unknown]"
3434-fi
3535-3636-# Display the latest release tag
3737-echo -e "The latest release tag is: ${BLUE}${latest_tag}${OFF}"
3838-3939-# Prompt the user for the new release tag
4040-read -r -p 'Enter a new release tag (vX.X.X format): ' new_tag
4141-4242-# Validate the new release tag
4343-tag_regex='v[0-9]+\.[0-9]+\.[0-9]+$'
4444-if echo "$new_tag" | grep -q -E "$tag_regex"; then
4545- echo -e "Tag: ${BLUE}$new_tag${OFF} is valid"
4646-else
4747- # Release tag is not `vX.X.X` format
4848- echo -e "Tag: ${BLUE}$new_tag${OFF} is ${RED}not valid${OFF} (must be in vX.X.X format)"
4949- exit 1
5050-fi
5151-5252-# Tag the new release
5353-git tag -a "$new_tag" -m "$new_tag Release"
5454-echo -e "${GREEN}Tagged: $new_tag${OFF}"
5555-5656-# Push the new tag to the remote
5757-git push --tags
5858-echo -e "${GREEN}Release tag pushed to remote${OFF}"
5959-echo -e "${GREEN}Done!${OFF}"
-7
packages/upload-openapi-spec/src/index.ts
···11-/**
22- * The entrypoint for the action.
33- */
44-import { run } from './main'
55-66-// eslint-disable-next-line @typescript-eslint/no-floating-promises
77-run()
-22
packages/upload-openapi-spec/src/main.ts
···11-import * as core from '@actions/core'
22-import { upload } from './upload'
33-44-/**
55- * The main function for the action.
66- * @returns {Promise<void>} Resolves when the action is complete.
77- */
88-export async function run(): Promise<void> {
99- try {
1010- const pathToOpenApi: string = core.getInput('path-to-openapi', {
1111- required: true
1212- })
1313-1414- core.debug(`Path to OpenAPI: ${pathToOpenApi}`)
1515-1616- core.debug(`Upload started: ${new Date().toTimeString()}`)
1717- await upload(pathToOpenApi)
1818- core.debug(`Upload completed: ${new Date().toTimeString()}`)
1919- } catch (error) {
2020- if (error instanceof Error) core.setFailed(error.message)
2121- }
2222-}
-34
packages/upload-openapi-spec/src/upload.ts
···11-import { createClient } from '@supabase/supabase-js'
22-import { readFileSync } from 'node:fs'
33-44-const supabaseUrl = process.env.SUPABASE_URL!
55-const supabaseKey = process.env.SUPABASE_KEY!
66-const supabase = createClient(supabaseUrl, supabaseKey)
77-88-/**
99- * Wait for a number of milliseconds.
1010- * @param milliseconds The number of milliseconds to wait.
1111- * @returns {Promise<string>} Resolves with 'done!' after the wait is over.
1212- */
1313-export async function upload(pathToOpenApi: string): Promise<void> {
1414- return new Promise(async resolve => {
1515- // TODO: throw if path is invalid
1616- if (!pathToOpenApi) {
1717- throw new Error('OpenAPI path is invalid')
1818- }
1919-2020- // TODO: add timestamp/user id to name/bucket
2121- const fileBody = readFileSync(pathToOpenApi)
2222- const bucketId = 'openapi-specs'
2323- const parts = pathToOpenApi.split('/')
2424- const name = `test/${parts[parts.length - 1]}`
2525- const { data, error } = await supabase.storage
2626- .from(bucketId)
2727- .upload(name, fileBody, {
2828- cacheControl: '3600',
2929- upsert: false
3030- })
3131-3232- resolve()
3333- })
3434-}