Compare commits

..

2 Commits

Author SHA1 Message Date
Marius 261e6c8027 Merge branch 'main' of github.com:tus/tusd into feature/disable-cors 2023-03-27 00:10:19 +02:00
Christian Kaps a0bcc71348 Disable cors headers 2023-02-07 20:10:57 +01:00
7 changed files with 58 additions and 671 deletions

View File

@ -1,156 +0,0 @@
# Taken from https://github.com/hrvey/combine-prs-workflow
# This action can be triggered manually to combine multiple PRs for
# dependency upgrades into a single PR. See the above links for
# more details.
name: 'Combine PRs'
# Controls when the action will run - in this case triggered manually
on:
workflow_dispatch:
inputs:
branchPrefix:
description: 'Branch prefix to find combinable PRs based on'
required: true
default: 'dependabot'
mustBeGreen:
description: 'Only combine PRs that are green (status is success). Set to false if repo does not run checks'
type: boolean
required: true
default: true
combineBranchName:
description: 'Name of the branch to combine PRs into'
required: true
default: 'combine-prs-branch'
ignoreLabel:
description: 'Exclude PRs with this label'
required: true
default: 'nocombine'
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "combine-prs"
combine-prs:
# The type of runner that the job will run on
runs-on: ubuntu-latest
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
- uses: actions/github-script@v6
id: create-combined-pr
name: Create Combined PR
with:
github-token: ${{secrets.GITHUB_TOKEN}}
script: |
const pulls = await github.paginate('GET /repos/:owner/:repo/pulls', {
owner: context.repo.owner,
repo: context.repo.repo
});
let branchesAndPRStrings = [];
let baseBranch = null;
let baseBranchSHA = null;
for (const pull of pulls) {
const branch = pull['head']['ref'];
console.log('Pull for branch: ' + branch);
if (branch.startsWith('${{ github.event.inputs.branchPrefix }}')) {
console.log('Branch matched prefix: ' + branch);
let statusOK = true;
if(${{ github.event.inputs.mustBeGreen }}) {
console.log('Checking green status: ' + branch);
const stateQuery = `query($owner: String!, $repo: String!, $pull_number: Int!) {
repository(owner: $owner, name: $repo) {
pullRequest(number:$pull_number) {
commits(last: 1) {
nodes {
commit {
statusCheckRollup {
state
}
}
}
}
}
}
}`
const vars = {
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: pull['number']
};
const result = await github.graphql(stateQuery, vars);
const [{ commit }] = result.repository.pullRequest.commits.nodes;
const state = commit.statusCheckRollup.state
console.log('Validating status: ' + state);
if(state != 'SUCCESS') {
console.log('Discarding ' + branch + ' with status ' + state);
statusOK = false;
}
}
console.log('Checking labels: ' + branch);
const labels = pull['labels'];
for(const label of labels) {
const labelName = label['name'];
console.log('Checking label: ' + labelName);
if(labelName == '${{ github.event.inputs.ignoreLabel }}') {
console.log('Discarding ' + branch + ' with label ' + labelName);
statusOK = false;
}
}
if (statusOK) {
console.log('Adding branch to array: ' + branch);
const prString = '#' + pull['number'] + ' ' + pull['title'];
branchesAndPRStrings.push({ branch, prString });
baseBranch = pull['base']['ref'];
baseBranchSHA = pull['base']['sha'];
}
}
}
if (branchesAndPRStrings.length == 0) {
core.setFailed('No PRs/branches matched criteria');
return;
}
try {
await github.rest.git.createRef({
owner: context.repo.owner,
repo: context.repo.repo,
ref: 'refs/heads/' + '${{ github.event.inputs.combineBranchName }}',
sha: baseBranchSHA
});
} catch (error) {
console.log(error);
core.setFailed('Failed to create combined branch - maybe a branch by that name already exists?');
return;
}
let combinedPRs = [];
let mergeFailedPRs = [];
for(const { branch, prString } of branchesAndPRStrings) {
try {
await github.rest.repos.merge({
owner: context.repo.owner,
repo: context.repo.repo,
base: '${{ github.event.inputs.combineBranchName }}',
head: branch,
});
console.log('Merged branch ' + branch);
combinedPRs.push(prString);
} catch (error) {
console.log('Failed to merge branch ' + branch);
mergeFailedPRs.push(prString);
}
}
console.log('Creating combined PR');
const combinedPRsString = combinedPRs.join('\n');
let body = '✅ This PR was created by the Combine PRs action by combining the following PRs:\n' + combinedPRsString;
if(mergeFailedPRs.length > 0) {
const mergeFailedPRsString = mergeFailedPRs.join('\n');
body += '\n\n⚠ The following PRs were left out due to merge conflicts:\n' + mergeFailedPRsString
}
await github.rest.pulls.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: 'Combined PR',
head: '${{ github.event.inputs.combineBranchName }}',
base: baseBranch,
body: body
});

View File

@ -9,7 +9,7 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
go-version: [stable, oldstable] go-version: [1.18.x, 1.19.x]
platform: [ubuntu-latest, macos-latest, windows-latest] platform: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.platform }} runs-on: ${{ matrix.platform }}
env: env:
@ -21,7 +21,7 @@ jobs:
- -
name: Install Go name: Install Go
uses: actions/setup-go@v4 uses: actions/setup-go@v3
with: with:
go-version: ${{ matrix.go-version }} go-version: ${{ matrix.go-version }}

View File

@ -21,7 +21,7 @@ jobs:
- -
name: Docker meta name: Docker meta
id: docker_meta id: docker_meta
uses: docker/metadata-action@v4.4.0 uses: docker/metadata-action@v4.3.0
with: with:
images: | images: |
ghcr.io/tus/tusd ghcr.io/tus/tusd
@ -35,7 +35,7 @@ jobs:
- -
name: Set up Docker Buildx name: Set up Docker Buildx
id: buildx id: buildx
uses: docker/setup-buildx-action@v2.5.0 uses: docker/setup-buildx-action@v2.4.1
with: with:
install: true install: true
@ -81,10 +81,10 @@ jobs:
uses: actions/checkout@v3 uses: actions/checkout@v3
- -
name: Install Go name: Install Go 1.19
uses: actions/setup-go@v4 uses: actions/setup-go@v3
with: with:
go-version: 'stable' go-version: '1.19.5'
- -
name: Build TUSD name: Build TUSD
@ -105,7 +105,7 @@ jobs:
- -
name: Deploy to heroku name: Deploy to heroku
uses: akhileshns/heroku-deploy@v3.12.14 uses: akhileshns/heroku-deploy@v3.12.13
with: with:
heroku_api_key: ${{secrets.HEROKU_API_KEY}} heroku_api_key: ${{secrets.HEROKU_API_KEY}}
heroku_app_name: ${{secrets.HEROKU_APP_NAME}} heroku_app_name: ${{secrets.HEROKU_APP_NAME}}

View File

@ -1,4 +1,4 @@
FROM --platform=$BUILDPLATFORM golang:1.20.4-alpine AS builder FROM golang:1.20.1-alpine AS builder
WORKDIR /go/src/github.com/tus/tusd WORKDIR /go/src/github.com/tus/tusd
# Add gcc and libc-dev early so it is cached # Add gcc and libc-dev early so it is cached
@ -19,17 +19,13 @@ COPY pkg/ ./pkg/
ARG GIT_VERSION ARG GIT_VERSION
ARG GIT_COMMIT ARG GIT_COMMIT
# Get the operating system and architecture to build for
ARG TARGETOS
ARG TARGETARCH
RUN set -xe \ RUN set -xe \
&& GOOS=$TARGETOS GOARCH=$TARGETARCH go build \ && GOOS=linux GOARCH=amd64 go build \
-ldflags="-X github.com/tus/tusd/cmd/tusd/cli.VersionName=${GIT_VERSION} -X github.com/tus/tusd/cmd/tusd/cli.GitCommit=${GIT_COMMIT} -X 'github.com/tus/tusd/cmd/tusd/cli.BuildDate=$(date --utc)'" \ -ldflags="-X github.com/tus/tusd/cmd/tusd/cli.VersionName=${GIT_VERSION} -X github.com/tus/tusd/cmd/tusd/cli.GitCommit=${GIT_COMMIT} -X 'github.com/tus/tusd/cmd/tusd/cli.BuildDate=$(date --utc)'" \
-o /go/bin/tusd ./cmd/tusd/main.go -o /go/bin/tusd ./cmd/tusd/main.go
# start a new stage that copies in the binary built in the previous stage # start a new stage that copies in the binary built in the previous stage
FROM alpine:3.18.0 FROM alpine:3.17.2
WORKDIR /srv/tusd-data WORKDIR /srv/tusd-data
COPY ./docker/entrypoint.sh /usr/local/share/docker-entrypoint.sh COPY ./docker/entrypoint.sh /usr/local/share/docker-entrypoint.sh

17
go.mod
View File

@ -6,19 +6,20 @@ module github.com/tus/tusd
go 1.16 go 1.16
require ( require (
cloud.google.com/go/storage v1.30.1 cloud.google.com/go/storage v1.29.0
github.com/Azure/azure-storage-blob-go v0.14.0 github.com/Azure/azure-storage-blob-go v0.14.0
github.com/aws/aws-sdk-go v1.44.275 github.com/aws/aws-sdk-go v1.44.211
github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40 github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40
github.com/golang/mock v1.6.0 github.com/golang/mock v1.6.0
github.com/golang/protobuf v1.5.3 github.com/golang/protobuf v1.5.2
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 github.com/grpc-ecosystem/go-grpc-middleware v1.3.0
github.com/prometheus/client_golang v1.15.1 github.com/prometheus/client_golang v1.14.0
github.com/sethgrid/pester v1.2.0 github.com/sethgrid/pester v1.2.0
github.com/stretchr/testify v1.8.4 github.com/stretchr/testify v1.8.2
github.com/vimeo/go-util v1.4.1 github.com/vimeo/go-util v1.4.1
google.golang.org/api v0.125.0 golang.org/x/sys v0.6.0 // indirect
google.golang.org/grpc v1.55.0 google.golang.org/api v0.111.0
google.golang.org/grpc v1.53.0
gopkg.in/Acconut/lockfile.v1 v1.1.0 gopkg.in/Acconut/lockfile.v1 v1.1.0
gopkg.in/h2non/gock.v1 v1.1.2 gopkg.in/h2non/gock.v1 v1.1.2
) )

496
go.sum

File diff suppressed because it is too large Load Diff

View File

@ -53,24 +53,6 @@ func NewHTTPError(err error, statusCode int) HTTPError {
return httpError{err, statusCode} return httpError{err, statusCode}
} }
type contextWithValues struct {
context.Context
valueHolder context.Context
}
func (c contextWithValues) Value(key interface{}) interface{} {
return c.valueHolder.Value(key)
}
func newContextWithValues(ctx context.Context) contextWithValues {
return contextWithValues{
// Use background to not get cancel event
Context: context.Background(),
// Use request context to get stored values
valueHolder: ctx,
}
}
var ( var (
ErrUnsupportedVersion = NewHTTPError(errors.New("unsupported version"), http.StatusPreconditionFailed) ErrUnsupportedVersion = NewHTTPError(errors.New("unsupported version"), http.StatusPreconditionFailed)
ErrMaxSizeExceeded = NewHTTPError(errors.New("maximum size exceeded"), http.StatusRequestEntityTooLarge) ErrMaxSizeExceeded = NewHTTPError(errors.New("maximum size exceeded"), http.StatusRequestEntityTooLarge)
@ -116,12 +98,6 @@ type HookEvent struct {
} }
func newHookEvent(info FileInfo, r *http.Request) HookEvent { func newHookEvent(info FileInfo, r *http.Request) HookEvent {
// The Host header field is not present in the header map, see https://pkg.go.dev/net/http#Request:
// > For incoming requests, the Host header is promoted to the
// > Request.Host field and removed from the Header map.
// That's why we add it back manually.
r.Header.Set("Host", r.Host)
return HookEvent{ return HookEvent{
Upload: info, Upload: info,
HTTPRequest: HTTPRequest{ HTTPRequest: HTTPRequest{
@ -308,7 +284,7 @@ func (handler *UnroutedHandler) Middleware(h http.Handler) http.Handler {
// PostFile creates a new file upload using the datastore after validating the // PostFile creates a new file upload using the datastore after validating the
// length and parsing the metadata. // length and parsing the metadata.
func (handler *UnroutedHandler) PostFile(w http.ResponseWriter, r *http.Request) { func (handler *UnroutedHandler) PostFile(w http.ResponseWriter, r *http.Request) {
ctx := newContextWithValues(r.Context()) ctx := context.Background()
// Check for presence of application/offset+octet-stream. If another content // Check for presence of application/offset+octet-stream. If another content
// type is defined, it will be ignored and treated as none was set because // type is defined, it will be ignored and treated as none was set because
@ -451,7 +427,7 @@ func (handler *UnroutedHandler) PostFile(w http.ResponseWriter, r *http.Request)
// HeadFile returns the length and offset for the HEAD request // HeadFile returns the length and offset for the HEAD request
func (handler *UnroutedHandler) HeadFile(w http.ResponseWriter, r *http.Request) { func (handler *UnroutedHandler) HeadFile(w http.ResponseWriter, r *http.Request) {
ctx := newContextWithValues(r.Context()) ctx := context.Background()
id, err := extractIDFromPath(r.URL.Path) id, err := extractIDFromPath(r.URL.Path)
if err != nil { if err != nil {
@ -516,7 +492,7 @@ func (handler *UnroutedHandler) HeadFile(w http.ResponseWriter, r *http.Request)
// PatchFile adds a chunk to an upload. This operation is only allowed // PatchFile adds a chunk to an upload. This operation is only allowed
// if enough space in the upload is left. // if enough space in the upload is left.
func (handler *UnroutedHandler) PatchFile(w http.ResponseWriter, r *http.Request) { func (handler *UnroutedHandler) PatchFile(w http.ResponseWriter, r *http.Request) {
ctx := newContextWithValues(r.Context()) ctx := context.Background()
// Check for presence of application/offset+octet-stream // Check for presence of application/offset+octet-stream
if r.Header.Get("Content-Type") != "application/offset+octet-stream" { if r.Header.Get("Content-Type") != "application/offset+octet-stream" {
@ -745,7 +721,7 @@ func (handler *UnroutedHandler) finishUploadIfComplete(ctx context.Context, uplo
// GetFile handles requests to download a file using a GET request. This is not // GetFile handles requests to download a file using a GET request. This is not
// part of the specification. // part of the specification.
func (handler *UnroutedHandler) GetFile(w http.ResponseWriter, r *http.Request) { func (handler *UnroutedHandler) GetFile(w http.ResponseWriter, r *http.Request) {
ctx := newContextWithValues(r.Context()) ctx := context.Background()
id, err := extractIDFromPath(r.URL.Path) id, err := extractIDFromPath(r.URL.Path)
if err != nil { if err != nil {
@ -866,7 +842,7 @@ func filterContentType(info FileInfo) (contentType string, contentDisposition st
// DelFile terminates an upload permanently. // DelFile terminates an upload permanently.
func (handler *UnroutedHandler) DelFile(w http.ResponseWriter, r *http.Request) { func (handler *UnroutedHandler) DelFile(w http.ResponseWriter, r *http.Request) {
ctx := newContextWithValues(r.Context()) ctx := context.Background()
// Abort the request handling if the required interface is not implemented // Abort the request handling if the required interface is not implemented
if !handler.composer.UsesTerminater { if !handler.composer.UsesTerminater {