diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d2eca6c..724df0b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -6,33 +6,51 @@ on: branches: [ main ] jobs: - build-all-clis: - name: Build Only (No Release) - runs-on: [ubuntu-latest] - steps: - - uses: actions/checkout@v5 - - - name: Set up Go - uses: actions/setup-go@v6 - with: - go-version-file: 'go.mod' - - - name: Storage-CLI Build for Linux - env: - GOOS: linux - GOARCH: amd64 - CGO_ENABLED: 0 - run: | - echo "Building Storage CLI for Linux" - go build -o "storage-cli-linux-amd64" - sha1sum "storage-cli-linux-amd64" - - - name: Storage-CLI Build for Windows - env: - GOOS: windows - GOARCH: amd64 - CGO_ENABLED: 0 - run: | - echo "Building Storage CLI for Windows" - go build -o "storage-cli-windows-amd64.exe" - sha1sum "storage-cli-windows-amd64.exe" \ No newline at end of file + build-all-clis: + name: Build Only (No Release) + runs-on: [ubuntu-latest] + steps: + - uses: actions/checkout@v5 + + - name: Set up Go + uses: actions/setup-go@v6 + with: + go-version-file: 'go.mod' + + - name: Storage-CLI Build for Linux + env: + GOOS: linux + GOARCH: amd64 + CGO_ENABLED: 0 + run: | + echo "Building Storage CLI for Linux" + go build -ldflags "-X main.version=0.0.0" \ + -o "storage-cli-linux-amd64" + sha1sum "storage-cli-linux-amd64" + + - name: Storage-CLI Build for Windows + env: + GOOS: windows + GOARCH: amd64 + CGO_ENABLED: 0 + run: | + echo "Building Storage CLI for Windows" + go build -ldflags "-X main.version=0.0.0" \ + -o "storage-cli-windows-amd64.exe" + sha1sum "storage-cli-windows-amd64.exe" + + - name: Sanitize branch name + id: sanitize + run: | + BRANCH_NAME="${{ github.ref_name }}" + SAFE_BRANCH=$(echo "$BRANCH_NAME" | sed 's/[^a-zA-Z0-9._-]/-/g') + echo "branch=$SAFE_BRANCH" >> $GITHUB_OUTPUT + + - name: Upload Build Artifacts + uses: actions/upload-artifact@v4 + with: + name: storage-cli-${{ steps.sanitize.outputs.branch }}-${{ github.sha }} + path: | + storage-cli-linux-amd64 + storage-cli-windows-amd64.exe + retention-days: 30 \ No newline at end of file diff --git a/.github/workflows/release-manual.yml b/.github/workflows/release-manual.yml new file mode 100644 index 0000000..98809cb --- /dev/null +++ b/.github/workflows/release-manual.yml @@ -0,0 +1,119 @@ +name: Release Manual + +on: + workflow_dispatch: + inputs: + version: + description: 'Release version (e.g., v1.2.3)' + required: true + type: string + release: + types: [published] + +jobs: + tests: + name: Run Unit Tests + runs-on: [ubuntu-latest] + steps: + - name: Checkout Into Source Code + uses: actions/checkout@v5 + + - name: Set up Go + uses: actions/setup-go@v6 + with: + go-version-file: go.mod + + - name: Lint code + uses: golangci/golangci-lint-action@v8 + + - name: Run Unit Tests + run: | + export CGO_ENABLED=0 + go version + go run github.com/onsi/ginkgo/v2/ginkgo --skip-package=integration ./... + + build-and-release: + name: Build and Release + needs: tests + runs-on: ubuntu-latest + steps: + - name: Checkout Into Source Code + uses: actions/checkout@v5 + + - name: Set up Go + uses: actions/setup-go@v6 + with: + go-version-file: go.mod + + - name: Determine Version + id: version + run: | + if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then + INPUT_VERSION="${{ github.event.inputs.version }}" + else + INPUT_VERSION="${{ github.event.release.tag_name }}" + fi + + # Validate version starts with 'v' + if [[ ! "$INPUT_VERSION" == v* ]]; then + echo "Error: Version must start with 'v' (e.g., v1.2.3)" + echo "Provided: $INPUT_VERSION" + exit 1 + fi + + VERSION="$INPUT_VERSION" + VERSION_NUMBER=${VERSION#v} + echo "VERSION=$VERSION" >> $GITHUB_OUTPUT + echo "VERSION_NUMBER=$VERSION_NUMBER" >> $GITHUB_OUTPUT + echo "Building version: $VERSION (number: $VERSION_NUMBER)" + + - name: Create Tag (if workflow_dispatch) + if: github.event_name == 'workflow_dispatch' + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git tag -a "${{ steps.version.outputs.VERSION }}" -m "Release ${{ steps.version.outputs.VERSION }}" + git push origin "${{ steps.version.outputs.VERSION }}" + + - name: Build for Linux + env: + GOOS: linux + GOARCH: amd64 + CGO_ENABLED: 0 + run: | + echo "Building Storage CLI for Linux" + go build -ldflags "-X main.version=${{ steps.version.outputs.VERSION_NUMBER }}" \ + -o "storage-cli-${{ steps.version.outputs.VERSION_NUMBER }}-linux-amd64" + echo "### Linux Build Checksums" >> $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + sha1sum "storage-cli-${{ steps.version.outputs.VERSION_NUMBER }}-linux-amd64" >> $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + + - name: Build for Windows + env: + GOOS: windows + GOARCH: amd64 + CGO_ENABLED: 0 + run: | + echo "Building Storage CLI for Windows" + go build -ldflags "-X main.version=${{ steps.version.outputs.VERSION_NUMBER }}" \ + -o "storage-cli-${{ steps.version.outputs.VERSION_NUMBER }}-windows-amd64.exe" + echo "### Windows Build Checksums" >> $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + sha1sum "storage-cli-${{ steps.version.outputs.VERSION_NUMBER }}-windows-amd64.exe" >> $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + + - name: Create or Update Github Release + uses: ncipollo/release-action@v1 + with: + tag: ${{ steps.version.outputs.VERSION }} + name: Release ${{ steps.version.outputs.VERSION }} + body: Release ${{ steps.version.outputs.VERSION }} + artifacts: | + storage-cli-${{ steps.version.outputs.VERSION_NUMBER }}-linux-amd64 + storage-cli-${{ steps.version.outputs.VERSION_NUMBER }}-windows-amd64.exe + token: ${{ secrets.GITHUB_TOKEN }} + allowUpdates: true + makeLatest: true + omitNameDuringUpdate: ${{ github.event_name == 'release' }} + omitBodyDuringUpdate: ${{ github.event_name == 'release' }} \ No newline at end of file diff --git a/README.md b/README.md index 530ce19..19f51dd 100644 --- a/README.md +++ b/README.md @@ -104,6 +104,33 @@ Follow these steps to make a contribution to the project: ``` - Create a GitHub pull request, selecting `main` as the target branch +## Releases + +### Manual Release +Releases must be triggered manually by an approver. This can be done either via `GitHub Actions` (workflow dispatch) or through the `GitHub Releases` page using the **Draft a new release** option. The *Release Manual* workflow is responsible for creating and completing the release. + +Option 1: Release via Workflow Dispatch + +- Go to Actions and select the *Release Manual* workflow. + +- Click **Run workflow**. + +- Enter the next incremented version number with the v prefix (for example, v1.2.3). + +- The workflow will create the release and upload the build artifacts once completed. + +Option 2: Release via Draft Release + +- Go to Releases and click **Draft a new release**. + +- Create a new tag using the next incremented version with the v prefix. + +- Fill in the release title and description. + +- Click Publish release. + +- The release will appear immediately on the Releases page. This action will also trigger the *Release Manual* workflow, which will build the artifacts and upload them to the published release once the workflow finishes. + ## Notes These commit IDs represent the last migration checkpoint from each provider's original repository, marking the final commit that was copied during the consolidation process. diff --git a/gcs/README.md b/gcs/README.md index 93f8821..6a6b59e 100644 --- a/gcs/README.md +++ b/gcs/README.md @@ -11,6 +11,20 @@ This is **not** an official Google Product. ## GCS-Specific Configuration The GCS client requires a JSON configuration file. +``` json +{ + "bucket_name": " (required)", + "credentials_source": " ['static'|'none'|""]", + "json_key": " (required if credentials_source = 'static')", + "storage_class": " (optional - default: 'STANDARD', check for more options=https://docs.cloud.google.com/storage/docs/storage-classes)", + "encryption_key": " (optional)", +} +``` + +### Credentials Source Types +* **"":** specifies that credentials should be detected. Application Default Credentials will be used if avaliable. A read-only client will be used otherwise. +* **"none":** specifies that credentials are explicitly empty and that the client should be restricted to a read-only scope. +* **"static:"** specifies that a service account file included in json_key should be used for authentication. ### Authentication Methods (`credentials_source`) * `static`: A [service account](https://cloud.google.com/iam/docs/creating-managing-service-account-keys) key will be provided via the `json_key` field.